From 4b8c86056956c68501295488d8ad92762db0d089 Mon Sep 17 00:00:00 2001 From: Frikky Date: Thu, 30 Jan 2025 15:21:45 +0100 Subject: [PATCH] Synced 2.0 updates --- frontend/src/components/AppModal.jsx | 133 +- frontend/src/components/Appsearch.jsx | 3 + frontend/src/components/CacheView.jsx | 19 +- frontend/src/components/ConfigureWorkflow.jsx | 20 +- frontend/src/components/EditWorkflow.jsx | 183 +- .../FixWorkflowValidationErrors.jsx | 10 +- frontend/src/components/LeftSideBar.jsx | 221 +- frontend/src/components/Oauth2Auth.jsx | 2 +- frontend/src/components/ParsedAction.jsx | 7405 ++--- frontend/src/components/Priorities.jsx | 324 +- .../src/components/ShuffleCodeEditor1.jsx | 6 +- .../src/components/WorkflowTemplatePopup2.jsx | 83 +- .../components/WorkflowValidationTimeline.jsx | 33 +- frontend/src/views/AngularWorkflow.jsx | 22299 ++++++++-------- frontend/src/views/AppCreator.jsx | 6 +- frontend/src/views/Apps.jsx | 1 - frontend/src/views/Apps2.jsx | 1 + frontend/src/views/RunWorkflow.jsx | 2 +- frontend/src/views/Usecases2.jsx | 5 +- frontend/src/views/Workflows2.jsx | 46 +- 20 files changed, 15790 insertions(+), 15012 deletions(-) diff --git a/frontend/src/components/AppModal.jsx b/frontend/src/components/AppModal.jsx index 41ca61a8..0d9a2194 100644 --- a/frontend/src/components/AppModal.jsx +++ b/frontend/src/components/AppModal.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { useNavigate } from 'react-router'; import { @@ -23,14 +23,14 @@ import ForkRightIcon from '@mui/icons-material/ForkRight'; import OpenInNewIcon from '@mui/icons-material/OpenInNew'; import LaunchIcon from '@mui/icons-material/Launch'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; -import { CloudDownloadOutlined } from '@mui/icons-material'; +import { CloudDownloadOutlined, Delete } from '@mui/icons-material'; import { findSpecificApp } from '../components/AppFramework.jsx'; import theme from "../theme.jsx"; import YAML from 'yaml'; import { toast } from 'react-toastify'; import { Link } from 'react-router-dom'; -const AppModal = ({ open, onClose, app, globalUrl }) => { +const AppModal = ({ open, onClose, app, globalUrl, getApps }) => { const [frameworkData, setFrameworkData] = useState({}) const [userdata, setUserdata] = useState({}) @@ -41,6 +41,8 @@ const AppModal = ({ open, onClose, app, globalUrl }) => { const [latestUsecase, setLatestUsecase] = useState([]) const [foundAppUsecase, setFoundAppUsecase] = useState({}) const [usecaseLoading, setUsecaseLoading] = useState(false) + const [deleteModalOpen, setDeleteModalOpen] = useState(false) + const [sharingConfiguration, setSharingConfiguration] = React.useState("you"); const navigate = useNavigate(); const parseUsecase = (subcase) => { const srcdata = findSpecificApp(frameworkData, subcase.type) @@ -294,8 +296,101 @@ const AppModal = ({ open, onClose, app, globalUrl }) => { setUsecaseLoading(true) getAvailableWorkflows() getFramework() + handleUpdateSharingConfiguration() }, [app]) + const handleUpdateSharingConfiguration = useCallback(() => { + if (app?.sharing === true) { + setSharingConfiguration("public") + }else { + setSharingConfiguration("you") + } + + }, [app?.id]) + + const deleteApp = (appId) => { + toast("Attempting to delete app"); + fetch(globalUrl + "/api/v1/apps/" + appId, { + method: "DELETE", + headers: { + Accept: "application/json", + }, + credentials: "include", + }) + .then((response) => { + if (response.status === 200) { + toast("Successfully deleted app"); + setTimeout(() => { + //delete apps from local storage + localStorage.removeItem("apps"); + getApps(); + }, 1000); + } else { + toast("Failed deleting app. Does it still exist?"); + } + }) + .catch((error) => { + toast(error.toString()); + }); + }; + + const deleteModal = deleteModalOpen ? ( + { + setDeleteModalOpen(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: "500px", + overflow: "hidden", + '& .MuiDialogContent-root': { + backgroundColor: theme?.palette?.DialogStyle?.backgroundColor, + }, + '& .MuiDialogTitle-root': { + backgroundColor: theme?.palette?.DialogStyle?.backgroundColor, + }, + } + }} + > + +
+ Are you sure?
+ Some workflows may stop working. +
+ + + + + +
+ ) : null; + const downloadApp = (inputdata) => { const id = inputdata.id; @@ -425,6 +520,7 @@ const AppModal = ({ open, onClose, app, globalUrl }) => { } }} > + {deleteModal} {
{app?.name} { ) : null} + {(userdata?.id === app?.owner)? ( + + + + ): null} + - {!leftSideBarOpenByClick && setExpandLeftNav(true);}} onMouseLeave={()=>{!leftSideBarOpenByClick && setExpandLeftNav(false);setOpenAutocomplete(false);}}> + {!leftSideBarOpenByClick && setExpandLeftNav(true)}} onMouseLeave={()=>{!leftSideBarOpenByClick && setExpandLeftNav(false);setOpenAutocomplete(false)}}> { color: currentOpenTab === "apps" && currentPath.includes("/apps") ? "#FFFFFF" : "#C8C8C8", justifyContent: "flex-start", textTransform: "none", - backgroundColor: currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/apps2") ? "#2f2f2f": "transparent", + backgroundColor: currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/apps") ? "#2f2f2f": "transparent", marginLeft: 16, fontSize: 18 }} @@ -1152,7 +1171,7 @@ useEffect(() => { event.currentTarget.style.backgroundColor = "#2f2f2f"; }} onMouseOut={(event)=>{ - event.currentTarget.style.backgroundColor = currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/search") ? "#2f2f2f": "transparent"; + event.currentTarget.style.backgroundColor = currentOpenTab === "apps" && expandLeftNav && currentPath.includes("/apps") ? "#2f2f2f": "transparent"; }} disableRipple={expandLeftNav ? false : true} > @@ -1205,7 +1224,7 @@ useEffect(() => { : "transparent"; }} > - { : "#C8C8C8" }} > - Discover + Content @@ -1262,7 +1281,7 @@ useEffect(() => { { to={"/forms"} style={{ ...hrefStyle, - pointerEvents: userdata?.support ? "auto" : "none", + pointerEvents: "auto", }} > + + + + + + + + + + + + + {recentworkflows?.length > 0 ? @@ -1549,6 +1642,7 @@ useEffect(() => { padding: option.id === "add_suborg" ? "0" : "12px 16px", marginTop: index !== 0 ? 8 : 0, borderRadius: 6, + marginLeft: option.margin_left ? option.margin_left : 0, }} onMouseOver={(e) => { e.currentTarget.style.backgroundColor = "#444444"; @@ -1618,12 +1712,15 @@ useEffect(() => { setAutocompleteValue(newInputValue); }} filterOptions={(options, params) => { + const normalize = (str) => str.toLowerCase().replace(/[\s-]+/g, ""); + const input = normalize(params.inputValue); + return options.filter((option) => - option.name - .toLowerCase() - .includes(params.inputValue.toLowerCase()) + normalize(option.name).includes(input) || + normalize(option.region_url).includes(input) ); }} + value={userOrgs} renderInput={(params) => ( { const authentication_url = authenticationType.token_uri; const redirectUri = `${window.location.protocol}//${window.location.host}/set_authentication`; - const workflowId = workflow !== undefined ? workflow.id : ""; + const workflowId = workflow !== undefined ? workflow.id : "" var state = `workflow_id%3D${workflowId}%26reference_action_id%3d${selectedAction.app_id}%26app_name%3d${selectedAction.app_name}%26app_id%3d${selectedAction.app_id}%26app_version%3d${selectedAction.app_version}%26authentication_url%3d${authentication_url}%26scope%3d${resources}%26client_id%3d${client_id}%26client_secret%3d${client_secret}`; diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index d546ceeb..b1dc6ba0 100755 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -13,82 +13,82 @@ import { green, yellow, red } from "../views/AngularWorkflow.jsx" //import { useAlert import { - Chip, - ButtonGroup, - Popper, - TextField, - TextareaAutosize, - Drawer, - Button, - Paper, - Tabs, - InputAdornment, - Tab, - ButtonBase, - Tooltip, - Select, - MenuItem, - Divider, - Dialog, - Modal, - DialogActions, - DialogTitle, - InputLabel, - DialogContent, - FormControl, - IconButton, - Menu, - Input, - FormGroup, - FormControlLabel, - Typography, - Checkbox, - Breadcrumbs, - CircularProgress, - Switch, - Collapse, - Autocomplete, + Chip, + ButtonGroup, + Popper, + TextField, + TextareaAutosize, + Drawer, + Button, + Paper, + Tabs, + InputAdornment, + Tab, + ButtonBase, + Tooltip, + Select, + MenuItem, + Divider, + Dialog, + Modal, + DialogActions, + DialogTitle, + InputLabel, + DialogContent, + FormControl, + IconButton, + Menu, + Input, + FormGroup, + FormControlLabel, + Typography, + Checkbox, + Breadcrumbs, + CircularProgress, + Switch, + Collapse, + Autocomplete, Box } from "@mui/material"; import { - HelpOutline as HelpOutlineIcon, - OpenInFull as OpenInFullIcon, - Description as DescriptionIcon, - GetApp as GetAppIcon, - Search as SearchIcon, - ArrowUpward as ArrowUpwardIcon, - Visibility as VisibilityIcon, - Done as DoneIcon, - Close as CloseIcon, - Error as ErrorIcon, - FindReplace as FindreplaceIcon, - ArrowLeft as ArrowLeftIcon, - Cached as CachedIcon, - DirectionsRun as DirectionsRunIcon, - Add as AddIcon, - Polymer as PolymerIcon, - FormatListNumbered as FormatListNumberedIcon, - Create as CreateIcon, - PlayArrow as PlayArrowIcon, - AspectRatio as AspectRatioIcon, - MoreVert as MoreVertIcon, - Apps as AppsIcon, - Schedule as ScheduleIcon, - FavoriteBorder as FavoriteBorderIcon, - Pause as PauseIcon, - Delete as DeleteIcon, - AddCircleOutline as AddCircleOutlineIcon, - Save as SaveIcon, - KeyboardArrowLeft as KeyboardArrowLeftIcon, - KeyboardArrowRight as KeyboardArrowRightIcon, - ArrowBack as ArrowBackIcon, - Settings as SettingsIcon, - LockOpen as LockOpenIcon, - ExpandMore as ExpandMoreIcon, - VpnKey as VpnKeyIcon, + HelpOutline as HelpOutlineIcon, + OpenInFull as OpenInFullIcon, + Description as DescriptionIcon, + GetApp as GetAppIcon, + Search as SearchIcon, + ArrowUpward as ArrowUpwardIcon, + Visibility as VisibilityIcon, + Done as DoneIcon, + Close as CloseIcon, + Error as ErrorIcon, + FindReplace as FindreplaceIcon, + ArrowLeft as ArrowLeftIcon, + Cached as CachedIcon, + DirectionsRun as DirectionsRunIcon, + Add as AddIcon, + Polymer as PolymerIcon, + FormatListNumbered as FormatListNumberedIcon, + Create as CreateIcon, + PlayArrow as PlayArrowIcon, + AspectRatio as AspectRatioIcon, + MoreVert as MoreVertIcon, + Apps as AppsIcon, + Schedule as ScheduleIcon, + FavoriteBorder as FavoriteBorderIcon, + Pause as PauseIcon, + Delete as DeleteIcon, + AddCircleOutline as AddCircleOutlineIcon, + Save as SaveIcon, + KeyboardArrowLeft as KeyboardArrowLeftIcon, + KeyboardArrowRight as KeyboardArrowRightIcon, + ArrowBack as ArrowBackIcon, + Settings as SettingsIcon, + LockOpen as LockOpenIcon, + ExpandMore as ExpandMoreIcon, + VpnKey as VpnKeyIcon, AutoFixHigh as AutoFixHighIcon, - Circle as CircleIcon, + Circle as CircleIcon, SquareFoot as SquareFootIcon, Storage as StorageIcon, Check as CheckIcon, @@ -96,239 +96,240 @@ import { } from '@mui/icons-material'; export const useStyles = makeStyles({ - root: { - "& .MuiAutocomplete-listbox": { - border: "2px solid grey", - color: "white", - fontSize: 18, - "& li:nth-child(even)": { - backgroundColor: "#CCC", - }, - "& li:nth-child(odd)": { - backgroundColor: "#FFF", - }, - }, - }, - inputRoot: { - color: "white", - "&:hover .MuiOutlinedInput-notchedOutline": { - borderColor: "#f86a3e", - }, - }, + root: { + "& .MuiAutocomplete-listbox": { + border: "2px solid grey", + color: "white", + fontSize: 18, + "& li:nth-child(even)": { + backgroundColor: "#CCC", + }, + "& li:nth-child(odd)": { + backgroundColor: "#FFF", + }, + }, + }, + inputRoot: { + color: "white", + "&:hover .MuiOutlinedInput-notchedOutline": { + borderColor: "#f86a3e", + }, + }, }); - + const openApiFieldDesc = "Generated by OpenAPI body example"; const ParsedAction = (props) => { - const { - workflow, - files, - setWorkflow, - setAction, - setSelectedAction, - setUpdate, - appActionArguments, - selectedApp, - workflowExecutions, - setSelectedResult, - selectedAction, - setSelectedApp, - setSelectedTrigger, - setSelectedEdge, - setCurrentView, - cy, - setAuthenticationModalOpen, - setVariablesModalOpen, - setCodeModalOpen, - selectedNameChange, - rightsidebarStyle, - showEnvironment, - selectedActionEnvironment, - environments, - setNewSelectedAction, - appApiViewStyle, - globalUrl, - setSelectedActionEnvironment, - requiresAuthentication, - hideExtraTypes, - scrollConfig, - setScrollConfig, - authenticationType, - appAuthentication, - getAppAuthentication, - actionDelayChange, - getParents, - isCloud, - lastSaved, - setLastSaved, - setShowVideo, - toolsAppId, - aiSubmit, + const { + workflow, + files, + setWorkflow, + setAction, + setSelectedAction, + setUpdate, + appActionArguments, + selectedApp, + workflowExecutions, + setSelectedResult, + selectedAction, + setSelectedApp, + setSelectedTrigger, + setSelectedEdge, + setCurrentView, + cy, + setAuthenticationModalOpen, + setVariablesModalOpen, + setCodeModalOpen, + selectedNameChange, + rightsidebarStyle, + showEnvironment, + selectedActionEnvironment, + environments, + setNewSelectedAction, + appApiViewStyle, + globalUrl, + setSelectedActionEnvironment, + requiresAuthentication, + hideExtraTypes, + scrollConfig, + setScrollConfig, + authenticationType, + appAuthentication, + getAppAuthentication, + actionDelayChange, + getParents, + isCloud, + lastSaved, + setLastSaved, + setShowVideo, + toolsAppId, + aiSubmit, - expansionModalOpen, - setExpansionModalOpen, - fixExample, + expansionModalOpen, + setExpansionModalOpen, + fixExample, - listCache, - setActiveDialog, - authGroups, - apps, - setEditorData, - setcodedata, - setAiQueryModalOpen, - } = props; + listCache, + setActiveDialog, + authGroups, + apps, + setEditorData, + setcodedata, + setAiQueryModalOpen, + } = props; - let navigate = useNavigate(); - const classes = useStyles(); + let navigate = useNavigate(); + const classes = useStyles(); - const [hideBody, setHideBody] = React.useState(false) - const [activateHidingBodyButton, setActivateHidingBodyButton] = React.useState(false) - const [appActionName, setAppActionName] = React.useState(selectedAction?.label); - const [delay, setDelay] = React.useState(selectedAction?.execution_delay || 0); - const [prevActionName, setPrevActionName] = React.useState(selectedAction?.label); - const [fieldCount, setFieldCount] = React.useState(0); - const [hiddenDescription, setHiddenDescription] = React.useState(true); - const [hiddenParameters, setHiddenParameters] = React.useState(true); - const [autoCompleting, setAutocompleting] = React.useState(false); - const [selectedActionParameters, setSelectedActionParameters] = React.useState(selectedAction?.parameters || []); - const [selectedVariableParameter, setSelectedVariableParameter] = React.useState(""); - const [paramUpdate, setParamUpdate] = React.useState(""); - const [actionlist, setActionlist] = React.useState([]); - const [jsonList, setJsonList] = React.useState([]); - const [showDropdown, setShowDropdown] = React.useState(false); - const [showDropdownNumber, setShowDropdownNumber] = React.useState(0); - const [showAutocomplete, setShowAutocomplete] = React.useState(false); - const [menuPosition, setMenuPosition] = useState(null); - const [uiBox, setUiBox] = useState(null); - const isIntegration = selectedAction.app_id === "integration" + const [hideBody, setHideBody] = React.useState(false) + const [activateHidingBodyButton, setActivateHidingBodyButton] = React.useState(false) + const [appActionName, setAppActionName] = React.useState(selectedAction?.label); + const [delay, setDelay] = React.useState(selectedAction?.execution_delay || 0); + const [prevActionName, setPrevActionName] = React.useState(selectedAction?.label); + const [fieldCount, setFieldCount] = React.useState(0); + const [hiddenDescription, setHiddenDescription] = React.useState(true); + const [hiddenParameters, setHiddenParameters] = React.useState(true); + const [autoCompleting, setAutocompleting] = React.useState(false); + const [selectedActionParameters, setSelectedActionParameters] = React.useState(selectedAction?.parameters || []); + const [selectedVariableParameter, setSelectedVariableParameter] = React.useState(""); + const [paramUpdate, setParamUpdate] = React.useState(""); + const [actionlist, setActionlist] = React.useState([]); + const [jsonList, setJsonList] = React.useState([]); + const [showDropdown, setShowDropdown] = React.useState(false); + const [showDropdownNumber, setShowDropdownNumber] = React.useState(0); + const [showAutocomplete, setShowAutocomplete] = React.useState(false); + const [menuPosition, setMenuPosition] = useState(null); + const [uiBox, setUiBox] = useState(null); + const isIntegration = selectedAction.app_id === "integration" + const [distributeAuthToSuborgs, setDistributeAuthToSuborgs] = useState(selectedAction?.selectedAuthentication?.suborg_distributed || false) - useEffect(() => { - if (setLastSaved !== undefined) { - setLastSaved(false) - } - }, [expansionModalOpen]) + useEffect(() => { + if (setLastSaved !== undefined) { + setLastSaved(false) + } + }, [expansionModalOpen]) - useEffect(() => { - // Changes the order of params to show in order: - // auth, required, optional - var changed = false - if (selectedActionParameters === undefined || selectedActionParameters === null || selectedActionParameters.length === 0) { - return - } + useEffect(() => { + // Changes the order of params to show in order: + // auth, required, optional + var changed = false + if (selectedActionParameters === undefined || selectedActionParameters === null || selectedActionParameters.length === 0) { + return + } - // Fixing required fields with a shitty structure :) - if (selectedApp !== undefined && selectedApp !== null && selectedApp.generated === true && selectedAction !== undefined && selectedAction !== null && selectedAction.name !== undefined && selectedAction.name !== null && selectedApp.actions !== undefined && selectedApp.actions !== null && selectedApp.actions.length > 0 && (selectedAction.required_body_fields === undefined || selectedAction.required_body_fields === null || selectedAction.required_body_fields.length === 0)) { - // Check for required fields - for (var actionkey in selectedApp.actions) { - var action = selectedApp.actions[actionkey] - if (action.name === selectedAction.name) { - selectedAction.required_body_fields = action.required_body_fields - break + // Fixing required fields with a shitty structure :) + if (selectedApp !== undefined && selectedApp !== null && selectedApp.generated === true && selectedAction !== undefined && selectedAction !== null && selectedAction.name !== undefined && selectedAction.name !== null && selectedApp.actions !== undefined && selectedApp.actions !== null && selectedApp.actions.length > 0 && (selectedAction.required_body_fields === undefined || selectedAction.required_body_fields === null || selectedAction.required_body_fields.length === 0)) { + // Check for required fields + for (var actionkey in selectedApp.actions) { + var action = selectedApp.actions[actionkey] + if (action.name === selectedAction.name) { + selectedAction.required_body_fields = action.required_body_fields + break + } } } - } - // Check if missing parameters? - var auth = [] - var required = [] - var optional = [] + // Check if missing parameters? + var auth = [] + var required = [] + var optional = [] - var bodyfield = [] - var special_optional = [] - var generated_optional = [] + var bodyfield = [] + var special_optional = [] + var generated_optional = [] - var keyorder = [] + var keyorder = [] - for (let paramkey in selectedActionParameters) { - var param = selectedActionParameters[paramkey] - keyorder.push(param.name) + for (let paramkey in selectedActionParameters) { + var param = selectedActionParameters[paramkey] + keyorder.push(param.name) - if (param.configuration) { - auth.push(param) - continue - } + if (param.configuration) { + auth.push(param) + continue + } - if (param?.value?.toLowerCase().includes("secret. replace")) { - param.value = "" - } + if (param?.value?.toLowerCase().includes("secret. replace")) { + param.value = "" + } - if (selectedApp?.generated === true && param?.name === "body") { - param.required = true - bodyfield.push(param) - continue - } + if (selectedApp?.generated === true && param?.name === "body") { + param.required = true + bodyfield.push(param) + continue + } - //if (param.name.startsWith("${") && param.name.endsWith("}")) { - // console.log("PARAM: ", param) - //} + //if (param.name.startsWith("${") && param.name.endsWith("}")) { + // console.log("PARAM: ", param) + //} - if (param.required === false && param.name.startsWith("${") && param.name.endsWith("}")) { - // Check if it's a required param - param.autocompleted = true - if (selectedAction.required_body_fields !== undefined && selectedAction.required_body_fields !== null && selectedAction.required_body_fields.length > 0) { + if (param.required === false && param.name.startsWith("${") && param.name.endsWith("}")) { + // Check if it's a required param + param.autocompleted = true + if (selectedAction.required_body_fields !== undefined && selectedAction.required_body_fields !== null && selectedAction.required_body_fields.length > 0) { - if (selectedAction.required_body_fields.includes(param.name)) { - param.required = true + if (selectedAction.required_body_fields.includes(param.name)) { + param.required = true + } } - } - } + } - if (param.required) { - required.push(param) - continue - } + if (param.required) { + required.push(param) + continue + } - if (param.name === "headers" || param.name === "queries") { - special_optional.push(param) - continue - } + if (param.name === "headers" || param.name === "queries") { + special_optional.push(param) + continue + } - if (hideBody && param?.description.includes("Generated")) { - continue - } + if (hideBody && param?.description.includes("Generated")) { + continue + } - if (param.field_active === true) { - param.autocompleted = true - generated_optional.push(param) - continue - } + if (param.field_active === true) { + param.autocompleted = true + generated_optional.push(param) + continue + } - optional.push(param) - } + optional.push(param) + } - // Sort order: auth > body(used for simple/advanced) > required > optional - // Optional field order: - // 1. headers & queries - // 2. other fields - // 3. generated fields & all else + // Sort order: auth > body(used for simple/advanced) > required > optional + // Optional field order: + // 1. headers & queries + // 2. other fields + // 3. generated fields & all else - const newparams = auth - .concat(bodyfield) - .concat(required) - .concat(generated_optional) - .concat(special_optional) - .concat(optional) + const newparams = auth + .concat(bodyfield) + .concat(required) + .concat(generated_optional) + .concat(special_optional) + .concat(optional) - var newkeyorder = [] - for (let paramkey in newparams) { - //console.log("Param: ", newparams[paramkey]) + var newkeyorder = [] + for (let paramkey in newparams) { + //console.log("Param: ", newparams[paramkey]) - newkeyorder.push(newparams[paramkey].name) - } + newkeyorder.push(newparams[paramkey].name) + } - if (keyorder.join(",") !== newkeyorder.join(",")) { - //toast("KEYORDER CHANGED!") + if (keyorder.join(",") !== newkeyorder.join(",")) { + //toast("KEYORDER CHANGED!") - setSelectedActionParameters(newparams) - selectedAction.parameters = newparams - setSelectedAction(selectedAction) - } - }, [selectedActionParameters]) + setSelectedActionParameters(newparams) + selectedAction.parameters = newparams + setSelectedAction(selectedAction) + } + }, [selectedActionParameters]) - useEffect(() => { - const shouldHide = localStorage.getItem("hideBody") + useEffect(() => { + const shouldHide = localStorage.getItem("hideBody") if (shouldHide !== null) { const ishiding = shouldHide !== "true" if (ishiding !== hideBody) { @@ -336,184 +337,227 @@ const ParsedAction = (props) => { } } - if (selectedActionEnvironment === undefined || selectedActionEnvironment === null || Object.keys(selectedActionEnvironment).length === 0) { + if (selectedActionEnvironment === undefined || selectedActionEnvironment === null || Object.keys(selectedActionEnvironment).length === 0) { - if (environments !== undefined && environments !== null && environments.length > 0) { - if (selectedAction.environment !== undefined && selectedAction.environment !== null) { + if (environments !== undefined && environments !== null && environments.length > 0) { + if (selectedAction.environment !== undefined && selectedAction.environment !== null) { - const foundenv = environments.find(env => env.id === selectedAction.environment || selectedAction.environment === env.Name) + const foundenv = environments.find(env => env.id === selectedAction.environment || selectedAction.environment === env.Name) - if (foundenv !== undefined && foundenv !== null) { - setSelectedActionEnvironment(foundenv) - } - } - } - } - }, []) + if (foundenv !== undefined && foundenv !== null) { + setSelectedActionEnvironment(foundenv) + } + } + } + } + }, []) - const keywords = [ - "len(", - "lower(", - "upper(", - "trim(", - "split(", - "length(", - "number(", - "parse(", - "join(", - ]; + const keywords = [ + "len(", + "lower(", + "upper(", + "trim(", + "split(", + "length(", + "number(", + "parse(", + "join(", + ]; - const getApp = (appId, setApp) => { - fetch(globalUrl + "/api/v1/apps/" + appId + "/config?openapi=false", { - headers: { - Accept: "application/json", - }, - credentials: "include", - }) - .then((response) => { - if (response.status === 200) { - //toast("Successfully GOT app "+appId) - } else { - toast("Failed getting app"); - } + const getApp = (appId, setApp) => { + fetch(globalUrl + "/api/v1/apps/" + appId + "/config?openapi=false", { + headers: { + Accept: "application/json", + }, + credentials: "include", + }) + .then((response) => { + if (response.status === 200) { + //toast("Successfully GOT app "+appId) + } else { + toast("Failed getting app"); + } - return response.json(); - }) - .then((responseJson) => { - console.log("RESPONSE: ", responseJson); + return response.json(); + }) + .then((responseJson) => { + console.log("RESPONSE: ", responseJson); - const parsedapp = - responseJson.app !== undefined && responseJson.app !== null - ? JSON.parse(atob(responseJson.app)) - : {}; - console.log("PARSED: ", parsedapp); - //data = parsedapp.body === undefined ? parsedapp : parsedapp.body + const parsedapp = + responseJson.app !== undefined && responseJson.app !== null + ? JSON.parse(atob(responseJson.app)) + : {}; + console.log("PARSED: ", parsedapp); + //data = parsedapp.body === undefined ? parsedapp : parsedapp.body - if ( - setApp && - parsedapp.actions !== undefined && - parsedapp.actions !== null - ) { - console.log("Inside first if"); - if ( - selectedApp.versions !== undefined && - selectedApp.versions !== null - ) { - parsedapp.versions = selectedApp.versions; - } + if ( + setApp && + parsedapp.actions !== undefined && + parsedapp.actions !== null + ) { + console.log("Inside first if"); + if ( + selectedApp.versions !== undefined && + selectedApp.versions !== null + ) { + parsedapp.versions = selectedApp.versions; + } - if ( - selectedApp.loop_versions !== undefined && - selectedApp.loop_versions !== null - ) { - parsedapp.loop_versions = selectedApp.loop_versions; - } + if ( + selectedApp.loop_versions !== undefined && + selectedApp.loop_versions !== null + ) { + parsedapp.loop_versions = selectedApp.loop_versions; + } - // Find authentication, and if it works? - // If authentication has less OR more fields, it has to change - //console.log(selected + // Find authentication, and if it works? + // If authentication has less OR more fields, it has to change + //console.log(selected - console.log("Inside first if2"); - var foundAction = parsedapp.actions.find( - (action) => - action.name.toLowerCase() === selectedAction.name.toLowerCase() - ); - if (foundAction !== null && foundAction !== undefined) { - var foundparams = []; - for (let [paramkey,paramkeyval] in Object.entries(foundAction.parameters)) { - const param = foundAction.parameters[paramkey]; + console.log("Inside first if2"); + var foundAction = parsedapp.actions.find( + (action) => + action.name.toLowerCase() === selectedAction.name.toLowerCase() + ); + if (foundAction !== null && foundAction !== undefined) { + var foundparams = []; + for (let [paramkey, paramkeyval] in Object.entries(foundAction.parameters)) { + const param = foundAction.parameters[paramkey]; - const foundParam = selectedAction.parameters.find( - (item) => item.name.toLowerCase() === param.name.toLowerCase() - ); - if (foundParam === undefined) { - console.log("COULDNT find Param: ", param); - } else { - foundAction.parameters[paramkey] = foundParam; - } - //foundparams.push(param.name) - } - } else { - toast("Couldn't find action " + selectedAction.name); - } + const foundParam = selectedAction.parameters.find( + (item) => item.name.toLowerCase() === param.name.toLowerCase() + ); + if (foundParam === undefined) { + console.log("COULDNT find Param: ", param); + } else { + foundAction.parameters[paramkey] = foundParam; + } + //foundparams.push(param.name) + } + } else { + toast("Couldn't find action " + selectedAction.name); + } - selectedAction.errors = []; - selectedAction.is_valid = true; + selectedAction.errors = []; + selectedAction.is_valid = true; - // Updating params for the new action - selectedAction.parameters = foundAction.parameters; - selectedAction.app_id = appId; - selectedAction.app_version = parsedapp.app_version; + // Updating params for the new action + selectedAction.parameters = foundAction.parameters; + selectedAction.app_id = appId; + selectedAction.app_version = parsedapp.app_version; - setSelectedAction(selectedAction); - setSelectedApp(parsedapp); - } - }) - .catch((error) => { - toast(error.toString()); - }); - }; + setSelectedAction(selectedAction); + setSelectedApp(parsedapp); + } + }) + .catch((error) => { + toast(error.toString()); + }); + }; + const changeDistribution = (data) => { + editAuthenticationConfig(data.id, "suborg_distribute") + } + const editAuthenticationConfig = (id, parentAction) => { + const data = { + id: id, + action: parentAction !== undefined && parentAction !== null ? parentAction : "assign_everywhere", + } - const defineStartnode = () => { - if (cy === undefined) { - return; - } + const url = globalUrl + "/api/v1/apps/authentication/" + id + "/config"; - var oldstartnode = cy.getElementById(workflow.start); - if (oldstartnode.length > 0) { - oldstartnode[0].data("isStartNode", false); - var oldnodecnt = workflow.actions.findIndex( - (a) => a.id === workflow.start - ); - if (workflow.actions[oldnodecnt] !== undefined) { - workflow.actions[oldnodecnt].isStartNode = false; - } - } + 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 appauth"); + } else { + if (distributeAuthToSuborgs) { + toast.success("Successfully updated auth"); + } else { + toast.success("Successfully distributed auth to suborgs"); + } + setTimeout(() => { + getAppAuthentication(); + setDistributeAuthToSuborgs(!distributeAuthToSuborgs) + }, 1000); + } + }) + ) + .catch((error) => { + toast("Err: " + error.toString()); + }); + }; - var newstartnode = cy.getElementById(selectedAction.id); - if (newstartnode.length > 0) { - newstartnode[0].data("isStartNode", true); - var newnodecnt = workflow.actions.findIndex( - (a) => a.id === selectedAction.id - ); - console.log("NEW NODE CNT: ", newnodecnt); - if (workflow.actions[newnodecnt] !== undefined) { - workflow.actions[newnodecnt].isStartNode = true; - console.log(workflow.actions[newnodecnt]); - } - } + const defineStartnode = () => { + if (cy === undefined) { + return; + } - // Find branches with triggers as source nodes - // Move these targets to be the new node - // Set arrows pointing to new startnode with errors - //for (var key in workflow.branches) { - // var item = workflow.branches[key] - // if (item.destination_id === oldstartnode[0].data()["id"]) { - // var curbranch = cy.getElementById(item.id) - // if (curbranch.length > 0) { - // //console.log(curbranch[0].data()) - // //curbranch[0].data("target", selectedAction.id) - // //curbranch[0].data("hasErrors", true) - // //workflow.branches[key].destination_id = selectedAction.id - // //console.log(curbranch[0].data()) - // } - // } - //} + var oldstartnode = cy.getElementById(workflow.start); + if (oldstartnode.length > 0) { + oldstartnode[0].data("isStartNode", false); + var oldnodecnt = workflow.actions.findIndex( + (a) => a.id === workflow.start + ); + if (workflow.actions[oldnodecnt] !== undefined) { + workflow.actions[oldnodecnt].isStartNode = false; + } + } - setUpdate("start_node" + selectedAction.id); - workflow.start = selectedAction.id; - setWorkflow(workflow); - //setStartNode(selectedAction.id) - }; + var newstartnode = cy.getElementById(selectedAction.id); + if (newstartnode.length > 0) { + newstartnode[0].data("isStartNode", true); + var newnodecnt = workflow.actions.findIndex( + (a) => a.id === selectedAction.id + ); + console.log("NEW NODE CNT: ", newnodecnt); + if (workflow.actions[newnodecnt] !== undefined) { + workflow.actions[newnodecnt].isStartNode = true; + console.log(workflow.actions[newnodecnt]); + } + } - useEffect(() => { + // Find branches with triggers as source nodes + // Move these targets to be the new node + // Set arrows pointing to new startnode with errors + //for (var key in workflow.branches) { + // var item = workflow.branches[key] + // if (item.destination_id === oldstartnode[0].data()["id"]) { + // var curbranch = cy.getElementById(item.id) + // if (curbranch.length > 0) { + // //console.log(curbranch[0].data()) + // //curbranch[0].data("target", selectedAction.id) + // //curbranch[0].data("hasErrors", true) + // //workflow.branches[key].destination_id = selectedAction.id + // //console.log(curbranch[0].data()) + // } + // } + //} + + setUpdate("start_node" + selectedAction.id); + workflow.start = selectedAction.id; + setWorkflow(workflow); + //setStartNode(selectedAction.id) + }; + + useEffect(() => { // Only set app action name if it has changed if (selectedAction.label !== appActionName) { setAppActionName(selectedAction.label); - const shouldHide = localStorage.getItem("hideBody") + const shouldHide = localStorage.getItem("hideBody") if (shouldHide !== null) { const ishiding = shouldHide !== "true" if (ishiding !== hideBody) { @@ -522,64 +566,64 @@ const ParsedAction = (props) => { } } - if(selectedAction.label !== prevActionName){ + if (selectedAction.label !== prevActionName) { setPrevActionName(selectedAction.label) } - + // Only set delay if it has changed const newDelay = selectedAction?.execution_delay || 0; if (newDelay !== delay) { setDelay(newDelay); } - + // Only set selected action parameters if they have changed if (selectedAction?.parameters?.length > 0 && selectedAction.label !== appActionName) { //console.log("PARAMS CHANGED DURING APPCHANGE: ", selectedAction.parameters) setSelectedActionParameters(selectedAction.parameters); } - + // Only set selected variable parameter if it is null or undefined if (!selectedVariableParameter && workflow.workflow_variables?.length > 0) { setSelectedVariableParameter(workflow.workflow_variables[0].name); } - },[selectedAction,selectedApp,setNewSelectedAction,workflow, workflowExecutions, getParents]) + }, [selectedAction, selectedApp, setNewSelectedAction, workflow, workflowExecutions, getParents]) useEffect(() => { - const newActionList = []; + const newActionList = []; const parentActionList = []; - // Process workflowExecutions - if (workflowExecutions.length > 0) { - for (let execution of workflowExecutions) { - const execArg = execution.execution_argument; - if (execArg && execArg.length > 0) { - const valid = validateJson(execArg); - if (valid.valid) { - newActionList.push({ - type: "Execution Argument", - name: "Execution Argument", - value: "$exec", - highlight: "exec", - autocomplete: "exec", - example: valid.result, - }) + // Process workflowExecutions + if (workflowExecutions.length > 0) { + for (let execution of workflowExecutions) { + const execArg = execution.execution_argument; + if (execArg && execArg.length > 0) { + const valid = validateJson(execArg); + if (valid.valid) { + newActionList.push({ + type: "Execution Argument", + name: "Execution Argument", + value: "$exec", + highlight: "exec", + autocomplete: "exec", + example: valid.result, + }) - break - } - } - } - } + break + } + } + } + } - // Add default Execution Argument if none were added - if (newActionList.length === 0) { - newActionList.push({ - type: "Execution Argument", - name: "Execution Argument", - value: "$exec", - highlight: "exec", - autocomplete: "exec", - example: "", - }) + // Add default Execution Argument if none were added + if (newActionList.length === 0) { + newActionList.push({ + type: "Execution Argument", + name: "Execution Argument", + value: "$exec", + highlight: "exec", + autocomplete: "exec", + example: "", + }) } // Look for cachekey @@ -609,105 +653,105 @@ const ParsedAction = (props) => { newActionList.push(cacheKey); } - // Process workflow variables - if (workflow.workflow_variables?.length > 0) { - for (let variable of workflow.workflow_variables) { - newActionList.push({ - type: "workflow_variable", - name: variable.name, - value: variable.value, - id: variable.id, - autocomplete: variable.name.split(" ").join("_"), - example: variable.value, - }); - } - } + // Process workflow variables + if (workflow.workflow_variables?.length > 0) { + for (let variable of workflow.workflow_variables) { + newActionList.push({ + type: "workflow_variable", + name: variable.name, + value: variable.value, + id: variable.id, + autocomplete: variable.name.split(" ").join("_"), + example: variable.value, + }); + } + } - // Process execution variables - if (workflow.execution_variables?.length > 0) { - for (let variable of workflow.execution_variables) { - let exampleOutput = ""; - for (let exec of workflowExecutions) { - const foundExec = exec.execution_variables?.find(exvar => exvar.name === variable.name); - if (foundExec?.value) { - exampleOutput = foundExec.value; - break; - } - } - newActionList.push({ - type: "execution_variable", - name: variable.name, - value: variable.value, - id: variable.id, - autocomplete: variable.name.split(" ").join("_"), - example: exampleOutput, - }); - } - } + // Process execution variables + if (workflow.execution_variables?.length > 0) { + for (let variable of workflow.execution_variables) { + let exampleOutput = ""; + for (let exec of workflowExecutions) { + const foundExec = exec.execution_variables?.find(exvar => exvar.name === variable.name); + if (foundExec?.value) { + exampleOutput = foundExec.value; + break; + } + } + newActionList.push({ + type: "execution_variable", + name: variable.name, + value: variable.value, + id: variable.id, + autocomplete: variable.name.split(" ").join("_"), + example: exampleOutput, + }); + } + } - // Process parent actions if getParents is provided - if (getParents) { - const parents = getParents(selectedAction); - if (parents.length > 1) { - const labels = []; - for (let parentNode of parents) { - if (parentNode.label !== "Execution Argument" && !labels.includes(parentNode.label)) { - labels.push(parentNode.label); - let exampleData = parentNode.example ?? ""; - if (!exampleData && workflowExecutions.length > 0) { - for (let exec of workflowExecutions) { - const foundResult = exec.results?.find(result => result.action.id === parentNode.id); - if (foundResult) { - const valid = validateJson(foundResult.result); - if (valid.valid && valid.result.success !== false) { - exampleData = valid.result; - break; - } - } - } - } + // Process parent actions if getParents is provided + if (getParents) { + const parents = getParents(selectedAction); + if (parents.length > 1) { + const labels = []; + for (let parentNode of parents) { + if (parentNode.label !== "Execution Argument" && !labels.includes(parentNode.label)) { + labels.push(parentNode.label); + let exampleData = parentNode.example ?? ""; + if (!exampleData && workflowExecutions.length > 0) { + for (let exec of workflowExecutions) { + const foundResult = exec.results?.find(result => result.action.id === parentNode.id); + if (foundResult) { + const valid = validateJson(foundResult.result); + if (valid.valid && valid.result.success !== false) { + exampleData = valid.result; + break; + } + } + } + } if (parentNode.label === undefined) { parentNode.label = "" } - newActionList.push({ - type: "action", - id: parentNode.id, - name: parentNode.label, - autocomplete: parentNode.label.split(" ").join("_"), - example: exampleData, - }); + newActionList.push({ + type: "action", + id: parentNode.id, + name: parentNode.label, + autocomplete: parentNode.label.split(" ").join("_"), + example: exampleData, + }); parentActionList.push({ - type: "action", - id: parentNode.id, - name: parentNode.label, - autocomplete: parentNode.label.split(" ").join("_"), - example: exampleData, - }); + type: "action", + id: parentNode.id, + name: parentNode.label, + autocomplete: parentNode.label.split(" ").join("_"), + example: exampleData, + }); - - } - } - } - } - let newParameters = selectedAction?.parameters?.map((param) => { + } + } + } + } + + let newParameters = selectedAction?.parameters?.map((param) => { let paramvalue = param.value === undefined || param.value === null ? "" : param.value; let errorVars = []; - if(paramvalue.includes("$")){ + if (paramvalue.includes("$")) { let actions = workflow.actions?.map((action) => { - return "$"+action.label?.toLowerCase(); + return "$" + action.label?.toLowerCase(); }) - if(newActionList?.length > 0){ + if (newActionList?.length > 0) { let appParentActions = parentActionList?.map(action => "$" + action.name.toLowerCase()); let notPresentAction = actions?.filter((action) => !appParentActions?.includes(action)) notPresentAction?.forEach((action) => { action = action.replace(" ", "_"); - if(paramvalue.includes(action)){ + if (paramvalue.includes(action)) { errorVars.push(action); // paramvalue = paramvalue.replace(action, "") // paramvalue = paramvalue.replace(/^\s*[\r\n]/gm, ""); @@ -717,281 +761,281 @@ const ParsedAction = (props) => { } let message = ""; - if(errorVars.length > 0){ - if(errorVars.length === 1){ + if (errorVars.length > 0) { + if (errorVars.length === 1) { message = errorVars[0] + " is not accessible in this action."; - }else{ + } else { message = errorVars.join(", ") + " are not accessible in this action."; } } - if (param?.configuration) { + if (param?.configuration && param?.name !== "url") { let regex = /(^|[^\\])\$/; if (regex.test(paramvalue)) { - if(message.length > 0){ + if (message.length > 0) { message += "\nUse \"\\$\" instead of \"$\" if you want to escape $ (1)"; - }else{ + } else { message = "Use \"\\$\" instead of \"$\" if you want to escape $ (2)"; } } } - return {...param, value: paramvalue, error: message} - }); + return { ...param, value: paramvalue, error: message } + }); setSelectedActionParameters(newParameters); - setActionlist(newActionList); - }, [workflow.execution_variables, paramUpdate, workflow.workflow_variables, workflowExecutions, workflow, selectedAction, listCache, getParents,setNewSelectedAction]); + setActionlist(newActionList); + }, [workflow.execution_variables, paramUpdate, workflow.workflow_variables, workflowExecutions, workflow, selectedAction, listCache, getParents, setNewSelectedAction]); - useEffect(() => { - selectedNameChange(appActionName) + useEffect(() => { + selectedNameChange(appActionName) - if (actionDelayChange !== undefined) { - actionDelayChange(delay) + if (actionDelayChange !== undefined) { + actionDelayChange(delay) + } + }, [appActionName, delay]) + + const handleParamChange = (event, count, data) => { + const newParams = [...selectedActionParameters]; + newParams.map((param) => { + if (param.name === data.name) { + param.value = event.target.value; } - },[appActionName,delay]) - - const handleParamChange = (event, count,data) => { - const newParams = [...selectedActionParameters]; - newParams.map((param) => { - if (param.name === data.name) { - param.value = event.target.value; + }) + setSelectedActionParameters(newParams); + setParamUpdate(event.target.value); + changeActionParameter(event, count, data) + } + + const calculateHelpertext = (input_data) => { + var helperText = "" + var looperText = "" + //const found = input_data.match(/[$]{1}([a-zA-Z0-9_-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,}/g) + var found = input_data.match(/[\\]{0,1}[$]{1}([a-zA-Z0-9_@-]+\.?){1}([a-zA-Z0-9#_@-]+\.?){0,}/g) + + if (found !== null && found !== undefined) { + var new_occurences = [] + for (let [key, keyval] in Object.entries(found)) { + if (found[key][0] !== "\\") { + new_occurences.push(found[key]) } - }) - setSelectedActionParameters(newParams); - setParamUpdate(event.target.value); - changeActionParameter(event, count, data) + } + + found = new_occurences.valueOf() } - const calculateHelpertext = (input_data) => { - var helperText = "" - var looperText = "" - //const found = input_data.match(/[$]{1}([a-zA-Z0-9_-]+\.?){1}([a-zA-Z0-9#_-]+\.?){0,}/g) - var found = input_data.match(/[\\]{0,1}[$]{1}([a-zA-Z0-9_@-]+\.?){1}([a-zA-Z0-9#_@-]+\.?){0,}/g) + if (found !== null) { + try { + // When the found array is empty. + for (let i = 0; i < found.length; i++) { + const variableSplit = found[i].split(".#") + if ((variableSplit.length - 1) > 1) { + //console.log("Larger than 1: ", variableSplit) + if (looperText.length === 0) { + looperText += "PS: Double looping (.#.#) may cause problems." + } + } - if (found !== null && found !== undefined) { - var new_occurences = [] - for (let [key,keyval] in Object.entries(found)) { - if (found[key][0] !== "\\") { - new_occurences.push(found[key]) + var foundSlice = false + for (let j = 0; j < actionlist.length; j++) { + //console.log("ACTION: ", found[i], actionlist[j]) + //console.log("ACTION :", found[i].split(".")[0].slice(1,).toLowerCase(), actionlist[j].autocomplete.toLowerCase()) + if (found[i].split(".")[0].slice(1,).toLowerCase() == actionlist[j].autocomplete.toLowerCase()) { + //console.log("Found: ", found[i]) + // Validate path? + + foundSlice = true + } + } + + if (!foundSlice) { + if (!helperText.includes("Invalid variables")) { + helperText += "Invalid variables: " + } + helperText += found[i] + ", " + } + } + } catch (e) { + console.log("Parsing error: ", e) + } + } + + if (looperText.length > 0) { + if (helperText.length > 0) { + helperText += ". " + } + + helperText += looperText + } + + return helperText + } + + const changeActionParameter = (event, count, data, viewForceUpdate) => { + //console.log("Action change: ", selectedAction, data) + if (data.name.startsWith("${") && data.name.endsWith("}")) { + // PARAM FIX - Gonna use the ID field, even though it's a hack + const paramcheck = selectedAction.parameters.find((param) => param.name === "body"); + + if (paramcheck !== undefined) { + // Escapes all double quotes + //var toReplace = event.target.value.trim() + var toReplace = event.target.value + + + if (!toReplace.startsWith("{") && !toReplace.startsWith("[")) { + toReplace = toReplace.replaceAll('\\"', '"').replaceAll('"', '\\"') + } + + if ( + paramcheck["value_replace"] === undefined || + paramcheck["value_replace"] === null + ) { + paramcheck["value_replace"] = [ + { + key: data.name, + value: toReplace, + }, + ]; + + } else { + const subparamindex = paramcheck["value_replace"].findIndex( + (param) => param.key === data.name + ); + if (subparamindex === -1) { + paramcheck["value_replace"].push({ + key: data.name, + value: toReplace, + }); + } else { + paramcheck["value_replace"][subparamindex]["value"] = toReplace; } } - found = new_occurences.valueOf() - } + if (selectedActionParameters[count].value_replace === undefined) { + selectedActionParameters[count].value_replace = paramcheck + } - if (found !== null) { - try { - // When the found array is empty. - for (let i = 0; i < found.length; i++) { - const variableSplit = found[i].split(".#") - if ((variableSplit.length-1) > 1) { - //console.log("Larger than 1: ", variableSplit) - if (looperText.length === 0) { - looperText += "PS: Double looping (.#.#) may cause problems." - } - } + if (selectedAction?.parameters[count] !== undefined && selectedAction?.parameters[count].value_replace === undefined) { + selectedAction.parameters[count].value_replace = paramcheck + } - var foundSlice = false - for (let j = 0; j < actionlist.length; j++) { - //console.log("ACTION: ", found[i], actionlist[j]) - //console.log("ACTION :", found[i].split(".")[0].slice(1,).toLowerCase(), actionlist[j].autocomplete.toLowerCase()) - if(found[i].split(".")[0].slice(1,).toLowerCase() == actionlist[j].autocomplete.toLowerCase()){ - //console.log("Found: ", found[i]) - // Validate path? + if (paramcheck["value_replace"] === undefined) { + selectedActionParameters[count]["value_replace"] = paramcheck - foundSlice = true - } - } - - if (!foundSlice) { - if (!helperText.includes("Invalid variables")) { - helperText+= "Invalid variables: " - } - helperText+= found[i] + ", " - } + if (selectedAction?.parameters[count] !== undefined) { + selectedAction.parameters[count]["value_replace"] = paramcheck + } + } else { + selectedActionParameters[count]["value_replace"] = paramcheck["value_replace"]; + if (selectedAction?.parameters[count] !== undefined) { + selectedAction.parameters[count]["value_replace"] = paramcheck["value_replace"]; } - } catch (e) { - console.log("Parsing error: ", e) } + setSelectedAction(selectedAction); + //setUpdate(Math.random()) + return; } - - if (looperText.length > 0) { - if (helperText.length > 0) { - helperText += ". " - } - - helperText += looperText - } - - return helperText } - const changeActionParameter = (event, count, data, viewForceUpdate) => { - //console.log("Action change: ", selectedAction, data) - if (data.name.startsWith("${") && data.name.endsWith("}")) { - // PARAM FIX - Gonna use the ID field, even though it's a hack - const paramcheck = selectedAction.parameters.find((param) => param.name === "body"); - - if (paramcheck !== undefined) { - // Escapes all double quotes - //var toReplace = event.target.value.trim() - var toReplace = event.target.value - - if (!toReplace.startsWith("{") && !toReplace.startsWith("[")) { - toReplace = toReplace.replaceAll('\\"', '"').replaceAll('"', '\\"') - } - - if ( - paramcheck["value_replace"] === undefined || - paramcheck["value_replace"] === null - ) { - paramcheck["value_replace"] = [ - { - key: data.name, - value: toReplace, - }, - ]; - - } else { - const subparamindex = paramcheck["value_replace"].findIndex( - (param) => param.key === data.name - ); - if (subparamindex === -1) { - paramcheck["value_replace"].push({ - key: data.name, - value: toReplace, - }); - } else { - paramcheck["value_replace"][subparamindex]["value"] = toReplace; - } - } - - if (selectedActionParameters[count].value_replace === undefined) { - selectedActionParameters[count].value_replace = paramcheck - } - - if (selectedAction?.parameters[count] !== undefined && selectedAction?.parameters[count].value_replace === undefined) { - selectedAction.parameters[count].value_replace = paramcheck - } - - if (paramcheck["value_replace"] === undefined) { - selectedActionParameters[count]["value_replace"] = paramcheck - - if (selectedAction?.parameters[count] !== undefined) { - selectedAction.parameters[count]["value_replace"] = paramcheck + if (event.target.value[event.target.value.length - 1] === "$") { + if (!showDropdown) { + setShowAutocomplete(false); + setShowDropdown(true); + setShowDropdownNumber(count); } - } else { - selectedActionParameters[count]["value_replace"] = paramcheck["value_replace"]; - if (selectedAction?.parameters[count] !== undefined) { - selectedAction.parameters[count]["value_replace"] = paramcheck["value_replace"]; + } else { + if (showDropdown) { + setShowDropdown(false); } - } - setSelectedAction(selectedAction); - //setUpdate(Math.random()) - return; - } - } + } + // bad detection mechanism probably + if (event.target.value[event.target.value.length - 1] === "." && actionlist.length > 0) { + console.log("GET THE LAST ARGUMENT FOR NODE!"); + // THIS IS AN EXAMPLE OF SHOWING IT + /* + + const inputdata = {"data": "1.2.3.4", "dataType": "4.5.6.6"} + setJsonList(GetParsedPaths(inputdata, "")) + if (!showDropdown) { + setShowAutocomplete(false) + setShowDropdown(true) + setShowDropdownNumber(count) + } + console.log(jsonList) + */ - if (event.target.value[event.target.value.length - 1] === "$") { - if (!showDropdown) { - setShowAutocomplete(false); - setShowDropdown(true); - setShowDropdownNumber(count); - } - } else { - if (showDropdown) { - setShowDropdown(false); - } - } + // Search for the item backwards + // 1. Reverse search backwards from . -> $ + // 2. Search the actionlist for the item + // 3. Find the data for the specific item - // bad detection mechanism probably - if (event.target.value[event.target.value.length - 1] === "." && actionlist.length > 0) { - console.log("GET THE LAST ARGUMENT FOR NODE!"); - // THIS IS AN EXAMPLE OF SHOWING IT - /* - - const inputdata = {"data": "1.2.3.4", "dataType": "4.5.6.6"} - setJsonList(GetParsedPaths(inputdata, "")) - if (!showDropdown) { - setShowAutocomplete(false) - setShowDropdown(true) - setShowDropdownNumber(count) + var curstring = ""; + var record = false; + for (let [key, keyval] in Object.entries(selectedActionParameters[count].value)) { + const item = selectedActionParameters[count].value[key]; + if (record) { + curstring += item; } - console.log(jsonList) - */ - // Search for the item backwards - // 1. Reverse search backwards from . -> $ - // 2. Search the actionlist for the item - // 3. Find the data for the specific item + if (item === "$") { + record = true; + curstring = ""; + } + } - var curstring = ""; - var record = false; - for (let [key,keyval] in Object.entries(selectedActionParameters[count].value)) { - const item = selectedActionParameters[count].value[key]; - if (record) { - curstring += item; - } + //console.log("CURSTRING: ", curstring) + if (curstring.length > 0 && actionlist !== null) { + // Search back in the action list + curstring = curstring.split(" ").join("_").toLowerCase(); + var actionItem = actionlist.find( + (data) => + data.autocomplete.split(" ").join("_").toLowerCase() === curstring + ); + if (actionItem !== undefined) { + console.log("Found item: ", actionItem); - if (item === "$") { - record = true; - curstring = ""; - } - } + //actionItem.example = actionItem.example.trim() + //actionItem.example = actionItem.example.split(" None").join(" \"None\"") + //actionItem.example = actionItem.example.split("\'").join("\"") - //console.log("CURSTRING: ", curstring) - if (curstring.length > 0 && actionlist !== null) { - // Search back in the action list - curstring = curstring.split(" ").join("_").toLowerCase(); - var actionItem = actionlist.find( - (data) => - data.autocomplete.split(" ").join("_").toLowerCase() === curstring - ); - if (actionItem !== undefined) { - console.log("Found item: ", actionItem); + var jsonvalid = true; + try { + const tmp = String(JSON.parse(actionItem.example)); + if ( + !actionItem.example.includes("{") && + !actionItem.example.includes("[") + ) { + jsonvalid = false; + } + } catch (e) { + jsonvalid = false; + } - //actionItem.example = actionItem.example.trim() - //actionItem.example = actionItem.example.split(" None").join(" \"None\"") - //actionItem.example = actionItem.example.split("\'").join("\"") + if (jsonvalid) { + setJsonList(GetParsedPaths(JSON.parse(actionItem.example), "")); - var jsonvalid = true; - try { - const tmp = String(JSON.parse(actionItem.example)); - if ( - !actionItem.example.includes("{") && - !actionItem.example.includes("[") - ) { - jsonvalid = false; - } - } catch (e) { - jsonvalid = false; - } - - if (jsonvalid) { - setJsonList(GetParsedPaths(JSON.parse(actionItem.example), "")); - - if (!showDropdown) { - setShowAutocomplete(false); - setShowDropdown(true); - setShowDropdownNumber(count); - } - } - } - } - } else { - if (jsonList.length > 0) { - setJsonList([]); - } - } + if (!showDropdown) { + setShowAutocomplete(false); + setShowDropdown(true); + setShowDropdownNumber(count); + } + } + } + } + } else { + if (jsonList.length > 0) { + setJsonList([]); + } + } selectedActionParameters[count].autocompleted = false selectedAction.parameters[count].autocompleted = false selectedActionParameters[count].value = event.target.value; selectedAction.parameters[count].value = event.target.value; - var forceUpdate = false + var forceUpdate = false if (isCloud && (selectedAction.app_name === "Shuffle Tools" || selectedAction.app_name === "email") && (selectedAction.name === "send_email_shuffle" || selectedAction.name === "send_sms_shuffle") && data.name === "apikey") { console.log("APIKEY - this shouldn't show up!") } @@ -1008,8 +1052,8 @@ const ParsedAction = (props) => { selectedActionParameters[count].value = splitparsed[0] selectedAction.parameters[count].value = splitparsed[0] - selectedActionParameters[1].value = splitparsed[1] - selectedAction.parameters[1].value = splitparsed[1] + selectedActionParameters[1].value = splitparsed[1] + selectedAction.parameters[1].value = splitparsed[1] } else { // Remove .# and after const splitparsed = parsedvalue.split(".#") @@ -1037,233 +1081,233 @@ const ParsedAction = (props) => { } //console.log("END OF THIS THING") - //setUpdate(event.target.value) - }; + //setUpdate(event.target.value) + }; - - const changeActionParameterCodeMirror = (event, count, data) => { - if (data.startsWith("${") && data.endsWith("}")) { - // PARAM FIX - Gonna use the ID field, even though it's a hack - const paramcheck = selectedAction.parameters.find(param => param.name === "body") - if (paramcheck !== undefined) { - // Escapes all double quotes - const toReplace = event.target.value.trim().replaceAll("\\\"", "\"").replaceAll("\"", "\\\""); - console.log("REPLACE WITH: ", toReplace) - if (paramcheck["value_replace"] === undefined || paramcheck["value_replace"] === null) { - paramcheck["value_replace"] = [{ + + const changeActionParameterCodeMirror = (event, count, data) => { + if (data.startsWith("${") && data.endsWith("}")) { + // PARAM FIX - Gonna use the ID field, even though it's a hack + const paramcheck = selectedAction.parameters.find(param => param.name === "body") + if (paramcheck !== undefined) { + // Escapes all double quotes + const toReplace = event.target.value.trim().replaceAll("\\\"", "\"").replaceAll("\"", "\\\""); + console.log("REPLACE WITH: ", toReplace) + if (paramcheck["value_replace"] === undefined || paramcheck["value_replace"] === null) { + paramcheck["value_replace"] = [{ + "key": data.name, + "value": toReplace, + }] + + console.log("IN IF: ", paramcheck) + + } else { + const subparamindex = paramcheck["value_replace"].findIndex(param => param.key === data.name) + if (subparamindex === -1) { + paramcheck["value_replace"].push({ "key": data.name, "value": toReplace, - }] - - console.log("IN IF: ", paramcheck) - + }) } else { - const subparamindex = paramcheck["value_replace"].findIndex(param => param.key === data.name) - if (subparamindex === -1) { - paramcheck["value_replace"].push({ - "key": data.name, - "value": toReplace, - }) - } else { - paramcheck["value_replace"][subparamindex]["value"] = toReplace - } + paramcheck["value_replace"][subparamindex]["value"] = toReplace } - //console.log("PARAM: ", paramcheck) - //if (paramcheck.id === undefined) { - // console.log("Normal paramcheck") - //} else { - // selectedActionParameters[count]["value_replace"] = paramcheck - // selectedAction.parameters[count]["value_replace"] = paramcheck - //} - - if (paramcheck["value_replace"] === undefined) { - selectedActionParameters[count]["value_replace"] = paramcheck - selectedAction.parameters[count]["value_replace"] = paramcheck - } else { - selectedActionParameters[count]["value_replace"] = paramcheck["value_replace"] - selectedAction.parameters[count]["value_replace"] = paramcheck["value_replace"] - } - console.log("RESULT: ", selectedAction) - setSelectedAction(selectedAction) - //setUpdate(Math.random()) - return } + //console.log("PARAM: ", paramcheck) + //if (paramcheck.id === undefined) { + // console.log("Normal paramcheck") + //} else { + // selectedActionParameters[count]["value_replace"] = paramcheck + // selectedAction.parameters[count]["value_replace"] = paramcheck + //} + + if (paramcheck["value_replace"] === undefined) { + selectedActionParameters[count]["value_replace"] = paramcheck + selectedAction.parameters[count]["value_replace"] = paramcheck + } else { + selectedActionParameters[count]["value_replace"] = paramcheck["value_replace"] + selectedAction.parameters[count]["value_replace"] = paramcheck["value_replace"] + } + console.log("RESULT: ", selectedAction) + setSelectedAction(selectedAction) + //setUpdate(Math.random()) + return } + } - if (event.target.value[event.target.value.length-1] === "$") { - if (!showDropdown) { - setShowAutocomplete(false) - setShowDropdown(true) - setShowDropdownNumber(count) - } - } else { - if (showDropdown) { - setShowDropdown(false) - } + if (event.target.value[event.target.value.length - 1] === "$") { + if (!showDropdown) { + setShowAutocomplete(false) + setShowDropdown(true) + setShowDropdownNumber(count) } - - - // bad detection mechanism probably - if (event.target.value[event.target.value.length-1] === "." && actionlist.length > 0) { - console.log("GET THE LAST ARGUMENT FOR NODE!") - // THIS IS AN EXAMPLE OF SHOWING IT - /* - const inputdata = {"data": "1.2.3.4", "dataType": "4.5.6.6"} - setJsonList(GetParsedPaths(inputdata, "")) - if (!showDropdown) { - setShowAutocomplete(false) - setShowDropdown(true) - setShowDropdownNumber(count) - } - console.log(jsonList) - */ - - // Search for the item backwards - // 1. Reverse search backwards from . -> $ - // 2. Search the actionlist for the item - // 3. Find the data for the specific item - - var curstring = "" - var record = false - for (let [key,keyval] in Object.entries(selectedActionParameters[count].value)) { - const item = selectedActionParameters[count].value[key] - if (record) { - curstring += item - } - - if (item === "$") { - record = true - curstring = "" - } - } - - //console.log("CURSTRING: ", curstring) - if (curstring.length > 0 && actionlist !== null) { - // Search back in the action list - curstring = curstring.split(" ").join("_").toLowerCase() - var actionItem = actionlist.find(data => data.autocomplete.split(" ").join("_").toLowerCase() === curstring) - if (actionItem !== undefined) { - console.log("Found item: ", actionItem) - - //actionItem.example = actionItem.example.trim() - //actionItem.example = actionItem.example.split(" None").join(" \"None\"") - //actionItem.example = actionItem.example.split("\'").join("\"") - - var jsonvalid = true - try { - const tmp = String(JSON.parse(actionItem.example)) - if (!actionItem.example.includes("{") && !actionItem.example.includes("[")) { - jsonvalid = false - } - } catch (e) { - jsonvalid = false - } - - if (jsonvalid) { - setJsonList(GetParsedPaths(JSON.parse(actionItem.example), "")) - - if (!showDropdown) { - setShowAutocomplete(false) - setShowDropdown(true) - setShowDropdownNumber(count) - } - } - } - } - } else { - if (jsonList.length > 0) { - setJsonList([]) - } + } else { + if (showDropdown) { + setShowDropdown(false) } - - setTimeout(() => { - selectedActionParameters[count].autocompleted = false - selectedAction.parameters[count].autocompleted = false - selectedActionParameters[count].value = data - selectedAction.parameters[count].value = data - }, 100); - setSelectedAction(selectedAction) - //setUpdate(Math.random()) - //setUpdate(event.target.value) } - const changeActionParameterVariable = (fieldvalue, count) => { - //console.log("CALLED THIS ONE WITH VALUE!", fieldvalue) - //if (selectedVariableParameter === fieldvalue) { - // return - //} + // bad detection mechanism probably + if (event.target.value[event.target.value.length - 1] === "." && actionlist.length > 0) { + console.log("GET THE LAST ARGUMENT FOR NODE!") + // THIS IS AN EXAMPLE OF SHOWING IT + /* + const inputdata = {"data": "1.2.3.4", "dataType": "4.5.6.6"} + setJsonList(GetParsedPaths(inputdata, "")) + if (!showDropdown) { + setShowAutocomplete(false) + setShowDropdown(true) + setShowDropdownNumber(count) + } + console.log(jsonList) + */ - setSelectedVariableParameter(fieldvalue); + // Search for the item backwards + // 1. Reverse search backwards from . -> $ + // 2. Search the actionlist for the item + // 3. Find the data for the specific item - selectedActionParameters[count].action_field = fieldvalue; - selectedAction.parameters = selectedActionParameters; + var curstring = "" + var record = false + for (let [key, keyval] in Object.entries(selectedActionParameters[count].value)) { + const item = selectedActionParameters[count].value[key] + if (record) { + curstring += item + } - setSelectedApp(selectedApp); - setSelectedAction(selectedAction); - setUpdate(fieldvalue); - }; + if (item === "$") { + record = true + curstring = "" + } + } - // Sets ACTION_RESULT things - const changeActionParameterActionResult = (fieldvalue, count) => { - //cy.nodes().forEach(function( ele ) { - // if (ele.data()["label"] === fieldvalue) { - // selectedActionParameters[count].action_field = ele.id() - // return - // } - //}); + //console.log("CURSTRING: ", curstring) + if (curstring.length > 0 && actionlist !== null) { + // Search back in the action list + curstring = curstring.split(" ").join("_").toLowerCase() + var actionItem = actionlist.find(data => data.autocomplete.split(" ").join("_").toLowerCase() === curstring) + if (actionItem !== undefined) { + console.log("Found item: ", actionItem) - selectedActionParameters[count].action_field = fieldvalue; - selectedAction.parameters = selectedActionParameters; + //actionItem.example = actionItem.example.trim() + //actionItem.example = actionItem.example.split(" None").join(" \"None\"") + //actionItem.example = actionItem.example.split("\'").join("\"") - // FIXME - check if startnode + var jsonvalid = true + try { + const tmp = String(JSON.parse(actionItem.example)) + if (!actionItem.example.includes("{") && !actionItem.example.includes("[")) { + jsonvalid = false + } + } catch (e) { + jsonvalid = false + } - // Set value - setSelectedApp(selectedApp); + if (jsonvalid) { + setJsonList(GetParsedPaths(JSON.parse(actionItem.example), "")) - setSelectedAction(selectedAction); - setUpdate(Math.random()); - }; + if (!showDropdown) { + setShowAutocomplete(false) + setShowDropdown(true) + setShowDropdownNumber(count) + } + } + } + } + } else { + if (jsonList.length > 0) { + setJsonList([]) + } + } - const changeActionParameterVariant = (data, count) => { - selectedActionParameters[count].variant = data; - selectedActionParameters[count].value = ""; + setTimeout(() => { + selectedActionParameters[count].autocompleted = false + selectedAction.parameters[count].autocompleted = false + selectedActionParameters[count].value = data + selectedAction.parameters[count].value = data + }, 100); + setSelectedAction(selectedAction) + //setUpdate(Math.random()) + //setUpdate(event.target.value) + } - if (data === "ACTION_RESULT" && getParents !== undefined) { - var parents = getParents(selectedAction); - if (parents.length > 0) { - selectedActionParameters[count].action_field = parents[0].label; - } else { - selectedActionParameters[count].action_field = ""; - } - } else if (data === "WORKFLOW_VARIABLE") { - if ( - workflow.workflow_variables !== null && - workflow.workflow_variables !== undefined && - workflow.workflow_variables.length > 0 - ) { - selectedActionParameters[count].action_field = - workflow.workflow_variables[0].name; - } - } - selectedAction.parameters = selectedActionParameters; + const changeActionParameterVariable = (fieldvalue, count) => { + //console.log("CALLED THIS ONE WITH VALUE!", fieldvalue) + //if (selectedVariableParameter === fieldvalue) { + // return + //} - // This is a stupid workaround to make it refresh rofl - setSelectedAction({}); + setSelectedVariableParameter(fieldvalue); - if (setSelectedTrigger !== undefined) { - setSelectedTrigger({}); - setSelectedApp({}); - setSelectedEdge({}); - } - // FIXME - check if startnode + selectedActionParameters[count].action_field = fieldvalue; + selectedAction.parameters = selectedActionParameters; - // Set value - setSelectedApp(selectedApp); - setSelectedAction(selectedAction); - setUpdate(Math.random()); - }; + setSelectedApp(selectedApp); + setSelectedAction(selectedAction); + setUpdate(fieldvalue); + }; + + // Sets ACTION_RESULT things + const changeActionParameterActionResult = (fieldvalue, count) => { + //cy.nodes().forEach(function( ele ) { + // if (ele.data()["label"] === fieldvalue) { + // selectedActionParameters[count].action_field = ele.id() + // return + // } + //}); + + selectedActionParameters[count].action_field = fieldvalue; + selectedAction.parameters = selectedActionParameters; + + // FIXME - check if startnode + + // Set value + setSelectedApp(selectedApp); + + setSelectedAction(selectedAction); + setUpdate(Math.random()); + }; + + const changeActionParameterVariant = (data, count) => { + selectedActionParameters[count].variant = data; + selectedActionParameters[count].value = ""; + + if (data === "ACTION_RESULT" && getParents !== undefined) { + var parents = getParents(selectedAction); + if (parents.length > 0) { + selectedActionParameters[count].action_field = parents[0].label; + } else { + selectedActionParameters[count].action_field = ""; + } + } else if (data === "WORKFLOW_VARIABLE") { + if ( + workflow.workflow_variables !== null && + workflow.workflow_variables !== undefined && + workflow.workflow_variables.length > 0 + ) { + selectedActionParameters[count].action_field = + workflow.workflow_variables[0].name; + } + } + + selectedAction.parameters = selectedActionParameters; + + // This is a stupid workaround to make it refresh rofl + setSelectedAction({}); + + if (setSelectedTrigger !== undefined) { + setSelectedTrigger({}); + setSelectedApp({}); + setSelectedEdge({}); + } + // FIXME - check if startnode + + // Set value + setSelectedApp(selectedApp); + setSelectedAction(selectedAction); + setUpdate(Math.random()); + }; const returnHelperText = (name, value) => { @@ -1275,7 +1319,7 @@ const ParsedAction = (props) => { var helperText = "" if (name.includes("url")) { if (value.includes("localhost") || value.includes("127.0.0.1")) { - helperText = "Can't use localhost in Shuffle. Please change to server's IP." + helperText = "Can't use localhost in Shuffle. Please change to server's IP." } } @@ -1315,7 +1359,7 @@ const ParsedAction = (props) => { if (selectedAction.name === "set_cache_value") { var actionKey = "" var actionValue = "" - for (let [key,keyval] in Object.entries(selectedActionParameters)) { + for (let [key, keyval] in Object.entries(selectedActionParameters)) { const param = selectedActionParameters[key] if (param.name === "key") { actionKey = param.value @@ -1331,7 +1375,7 @@ const ParsedAction = (props) => { } if (!actionKey.includes(".#") && actionValue.includes(".#")) { - return When the key ({actionKey}) is static, but the value is a list ({actionValue}), it will overwrite the list. You may be looking for the {}} style={{cursor: "pointer", color: "#FF8544", }}>Check Cache Contains action instead. + return When the key ({actionKey}) is static, but the value is a list ({actionValue}), it will overwrite the list. You may be looking for the { }} style={{ cursor: "pointer", color: "#FF8544", }}>Check Cache Contains action instead. } } @@ -1349,91 +1393,91 @@ const ParsedAction = (props) => { selectedAction.errors = ["Suggestion: " + suggestionText] } - return - - Tip: {suggestionText} - + return + + Tip: {suggestionText} + } - // FIXME: Issue #40 - selectedActionParameters not reset + // FIXME: Issue #40 - selectedActionParameters not reset if (Object.getOwnPropertyNames(selectedAction)?.length > 0 && selectedActionParameters?.length > 0) { - var wrapperapp = { - "id": "", - "name": "noapp", - "large_image": "", - } - - var actionname = selectedAction.name.toLowerCase() - if (actionname === "email" || actionname === "communication") { - actionname = "comms" - } - - if (isIntegration) { - - // Check if actionname uppercase is in the parsedDatatypeImages() dictionary - if (parsedDatatypeImages()[actionname.toUpperCase()] !== undefined) { - var newimage = parsedDatatypeImages()[actionname.toUpperCase()] - //newimage = - wrapperapp.large_image = newimage - } else { - console.log("Couldn't find actionname: ", actionname) + var wrapperapp = { + "id": "", + "name": "noapp", + "large_image": "", } - } - var authWritten = false; - var noAppSelected = false - if (selectedAction.parameters !== undefined && selectedAction.parameters !== null && selectedAction.parameters.length > 0) { - var paramIndex = selectedAction.parameters.findIndex((param) => param.name === "app_name") - if (paramIndex === -1 || selectedAction.parameters[paramIndex].value === "" || selectedAction.parameters[paramIndex].value === "noapp") { - // Check the actual value and if it's the same - noAppSelected = true - } - } + var actionname = selectedAction.name.toLowerCase() + if (actionname === "email" || actionname === "communication") { + actionname = "comms" + } + + if (isIntegration) { + + // Check if actionname uppercase is in the parsedDatatypeImages() dictionary + if (parsedDatatypeImages()[actionname.toUpperCase()] !== undefined) { + var newimage = parsedDatatypeImages()[actionname.toUpperCase()] + //newimage = + wrapperapp.large_image = newimage + } else { + console.log("Couldn't find actionname: ", actionname) + } + } + + var authWritten = false; + var noAppSelected = false + if (selectedAction.parameters !== undefined && selectedAction.parameters !== null && selectedAction.parameters.length > 0) { + var paramIndex = selectedAction.parameters.findIndex((param) => param.name === "app_name") + if (paramIndex === -1 || selectedAction.parameters[paramIndex].value === "" || selectedAction.parameters[paramIndex].value === "noapp") { + // Check the actual value and if it's the same + noAppSelected = true + } + } } const ActionSelectOption = (actionprops) => { const { option, newActionname, newActiondescription, useIcon, extraDescription, } = actionprops; - const [hover, setHover] = React.useState(false); + const [hover, setHover] = React.useState(false); return (
setHover(true)} onMouseLeave={() => setHover(false)} - onClick={(event) => { - // event.preventDefault() - //setSelectedAction(actionprops) - //setShowActionList(false) - //setUpdate(Math.random()) - // - if (option !== undefined && option !== null) { - setNewSelectedAction({ - target: { - value: option.name - } - }); - } + onClick={(event) => { + // event.preventDefault() + //setSelectedAction(actionprops) + //setShowActionList(false) + //setUpdate(Math.random()) + // + if (option !== undefined && option !== null) { + setNewSelectedAction({ + target: { + value: option.name + } + }); + } - document.activeElement.blur(); + document.activeElement.blur(); - const disabledUiBox = localStorage.getItem("disabled_ui_box") - if (disabledUiBox === "true") { - } else { - setHiddenDescription(false) - } - }} + const disabledUiBox = localStorage.getItem("disabled_ui_box") + if (disabledUiBox === "true") { + } else { + setHiddenDescription(false) + } + }} > -
+
{ > {useIcon} - {newActionname} + {newActionname}
- {extraDescription.length > 0 ? - - {extraDescription} + {extraDescription.length > 0 ? + + {extraDescription} - : null} + : null}
) } - const sortByCategoryLabel = (a, b) => { - const aHasCategoryLabel = a.category_label !== undefined && a.category_label !== null && a.category_label.length > 0 - const bHasCategoryLabel = b.category_label !== undefined && b.category_label !== null && b.category_label.length > 0 + const sortByCategoryLabel = (a, b) => { + const aHasCategoryLabel = a.category_label !== undefined && a.category_label !== null && a.category_label.length > 0 + const bHasCategoryLabel = b.category_label !== undefined && b.category_label !== null && b.category_label.length > 0 - // Sort by existence and length of "category_label" - if (aHasCategoryLabel && !bHasCategoryLabel) { - return -1 - } else if (!aHasCategoryLabel && bHasCategoryLabel) { - return 1 - } else { - return 0 - } - } + // Sort by existence and length of "category_label" + if (aHasCategoryLabel && !bHasCategoryLabel) { + return -1 + } else if (!aHasCategoryLabel && bHasCategoryLabel) { + return 1 + } else { + return 0 + } + } // Function to deduplicate based on the "name" field const deduplicateByName = (array) => { - const uniqueNames = {}; - return array.filter(item => { - if (!item.hasOwnProperty('name') || !item.name.length) { - return true - } - if (!uniqueNames[item.name]) { - uniqueNames[item.name] = true - return true - } - return false - }) + const uniqueNames = {}; + return array.filter(item => { + if (!item.hasOwnProperty('name') || !item.name.length) { + return true + } + if (!uniqueNames[item.name]) { + uniqueNames[item.name] = true + return true + } + return false + }) } - // Gets the most important actions first - const renderedActionOptions = deduplicateByName(( - selectedApp.actions === undefined || selectedApp.actions === null ? [] : - selectedApp.actions.filter((a) => - a.category_label !== undefined && a.category_label !== null && a.category_label.length > 0).concat(sortByKey(selectedApp.actions, "label")) - ).sort(sortByCategoryLabel)) - + // Gets the most important actions first + const renderedActionOptions = deduplicateByName(( + selectedApp.actions === undefined || selectedApp.actions === null ? [] : + selectedApp.actions.filter((a) => + a.category_label !== undefined && a.category_label !== null && a.category_label.length > 0).concat(sortByKey(selectedApp.actions, "label")) + ).sort(sortByCategoryLabel)) - const selectedAppIcon = selectedAction.large_image - var newAppname = selectedAction?.name?.charAt(0).toUpperCase() + selectedAction?.name?.substring(1) - if (newAppname === undefined || newAppname === null) { - newAppname = "" - } else { - newAppname = newAppname.replaceAll("_", " ") - } + const selectedAppIcon = selectedAction.large_image - var optionalFound = false - return ( -
+ var newAppname = selectedAction?.name?.charAt(0).toUpperCase() + selectedAction?.name?.substring(1) + if (newAppname === undefined || newAppname === null) { + newAppname = "" + } else { + try { + newAppname = newAppname?.replaceAll("_", " ") + } catch (e) { + console.log("Error in replace newappname: ", e) + } - {hideExtraTypes === true ? null : ( - -
-
-
{ - //window.open("/apps/${selectedAction.app_id}", "_blank") - }} - > - - - + } -

- {newAppname} -

-
-
- { - if (workflowExecutions.length > 0) { - // Look for the ID - var found = false; - for (let [key,keyval] in Object.entries(workflowExecutions)) { - if (workflowExecutions[key].results === undefined || workflowExecutions[key].results === null) { - continue; - } + var optionalFound = false + return ( +
- var foundResult = workflowExecutions[key].results.find( - (result) => result.action.id === selectedAction.id - ) + {hideExtraTypes === true ? null : ( + +
+
+
{ + //window.open("/apps/${selectedAction.app_id}", "_blank") + }} + > + + + - if (foundResult === undefined || foundResult === null) { - continue - } +

+ {newAppname} +

+
+
+ { + if (workflowExecutions.length > 0) { + // Look for the ID + var found = false; + for (let [key, keyval] in Object.entries(workflowExecutions)) { + if (workflowExecutions[key].results === undefined || workflowExecutions[key].results === null) { + continue; + } - const oldstartnode = cy.getElementById(selectedAction.id); - if (oldstartnode !== undefined && oldstartnode !== null) { - const foundname = oldstartnode.data("label") - if (foundname !== undefined && foundname !== null) { - foundResult.action.label = foundname - } - } + var foundResult = workflowExecutions[key].results.find( + (result) => result.action.id === selectedAction.id + ) - setSelectedResult(foundResult); - if (setCodeModalOpen !== undefined) { - setCodeModalOpen(true) - - found = true - } + if (foundResult === undefined || foundResult === null) { + continue + } - break - } + const oldstartnode = cy.getElementById(selectedAction.id); + if (oldstartnode !== undefined && oldstartnode !== null) { + const foundname = oldstartnode.data("label") + if (foundname !== undefined && foundname !== null) { + foundResult.action.label = foundname + } + } - if (!found) { - toast("No result for this action yet. Please run the workflow first.") - } - } - }} - > - - - - - { - setAuthenticationModalOpen(true) - }} - > - - - - + setSelectedResult(foundResult); + if (setCodeModalOpen !== undefined) { + setCodeModalOpen(true) - { - if (setAiQueryModalOpen !== undefined) { - setAiQueryModalOpen(true) - } else { - aiSubmit("Fill based on previous values", undefined, undefined, selectedAction) - } - - setAutocompleting(true) - setTimeout(() => { - setAutocompleting(false) - }, 3000) - }} - > - - {autoCompleting ? - - : - - } - - -
-
-
- {selectedApp.versions !== null && - selectedApp.versions !== undefined && - selectedApp.versions.length > 1 ? ( - - ) : null} -
-
-
-
- Name + { + if (setAiQueryModalOpen !== undefined) { + setAiQueryModalOpen(true) + } else { + aiSubmit("Fill based on previous values", undefined, undefined, selectedAction) + } + + setAutocompleting(true) + setTimeout(() => { + setAutocompleting(false) + }, 3000) + }} + > + + {autoCompleting ? + + : + + } + + +
+
+
+ {selectedApp.versions !== null && + selectedApp.versions !== undefined && + selectedApp.versions.length > 1 ? ( + + ) : null} +
+
+
+
+ Name { onBlur={(e) => { // Copy the name value const name = e.target.value - const parsedBaseLabel = "$"+prevActionName.toLowerCase().replaceAll(" ", "_") - const newname = "$"+name.toLowerCase().replaceAll(" ", "_") + const parsedBaseLabel = "$" + prevActionName.toLowerCase().replaceAll(" ", "_") + const newname = "$" + name.toLowerCase().replaceAll(" ", "_") // Check if it's the same as the current name in use //if (name === selectedAction.label) { @@ -1736,10 +1785,10 @@ const ParsedAction = (props) => { // Change in actions, triggers & conditions // Highlight the changes somehow with a glow? - if (workflow.branches !== undefined && workflow.branches !== null) { - for (let [key,keyval] in Object.entries(workflow.branches)) { + if (workflow.branches !== undefined && workflow.branches !== null) { + for (let [key, keyval] in Object.entries(workflow.branches)) { if (workflow.branches[key].conditions !== undefined && workflow.branches[key].conditions !== null) { - for (let [subkey,subkeyval] in Object.entries(workflow.branches[key].conditions)) { + for (let [subkey, subkeyval] in Object.entries(workflow.branches[key].conditions)) { const condition = workflow.branches[key].conditions[subkey] const sourceparam = condition.source const destinationparam = condition.destination @@ -1751,46 +1800,46 @@ const ParsedAction = (props) => { var cnt = -1 var previous = 0 while (true) { - cnt += 1 + cnt += 1 // Need to make sure e.g. changing the first here doesn't change the 2nd // $change_me // $change_me_2 - + const foundindex = sourceparam.value.toLowerCase().indexOf(parsedBaseLabel, previous) if (foundindex === previous && foundindex !== 0) { break } - + if (foundindex >= 0) { - previous = foundindex+newname.length + previous = foundindex + newname.length // Need to add diff of length to word - + // Check location: // If it's a-zA-Z_ then don't replace - if (sourceparam.value.length > foundindex+parsedBaseLabel.length) { + if (sourceparam.value.length > foundindex + parsedBaseLabel.length) { const regex = /[a-zA-Z0-9_]/g; - const match = sourceparam.value[foundindex+parsedBaseLabel.length].match(regex); + const match = sourceparam.value[foundindex + parsedBaseLabel.length].match(regex); if (match !== null) { continue } } - + console.log("Old found: ", workflow.branches[key].conditions[subkey].source.value) - const extralength = newname.length-parsedBaseLabel.length - sourceparam.value = sourceparam.value.substring(0, foundindex) + newname + sourceparam.value.substring(foundindex-extralength+newname.length, sourceparam.value.length) + const extralength = newname.length - parsedBaseLabel.length + sourceparam.value = sourceparam.value.substring(0, foundindex) + newname + sourceparam.value.substring(foundindex - extralength + newname.length, sourceparam.value.length) console.log("New: ", workflow.branches[key].conditions[subkey].source.value) - } else { + } else { break } - + // Break no matter what after 5 replaces. May need to increase if (cnt >= 5) { break } - + } - } catch (e) { + } catch (e) { console.log("Failed value replacement based on index: ", e) } } @@ -1800,46 +1849,46 @@ const ParsedAction = (props) => { var cnt = -1 var previous = 0 while (true) { - cnt += 1 + cnt += 1 // Need to make sure e.g. changing the first here doesn't change the 2nd // $change_me // $change_me_2 - + const foundindex = destinationparam.value.toLowerCase().indexOf(parsedBaseLabel, previous) if (foundindex === previous && foundindex !== 0) { break } - + if (foundindex >= 0) { - previous = foundindex+newname.length + previous = foundindex + newname.length // Need to add diff of length to word - + // Check location: // If it's a-zA-Z_ then don't replace - if (destinationparam.value.length > foundindex+parsedBaseLabel.length) { + if (destinationparam.value.length > foundindex + parsedBaseLabel.length) { const regex = /[a-zA-Z0-9_]/g; - const match = destinationparam.value[foundindex+parsedBaseLabel.length].match(regex); + const match = destinationparam.value[foundindex + parsedBaseLabel.length].match(regex); if (match !== null) { continue } } - + console.log("Old found: ", workflow.branches[key].conditions[subkey].destination.value) - const extralength = newname.length-parsedBaseLabel.length - destinationparam.value = destinationparam.value.substring(0, foundindex) + newname + destinationparam.value.substring(foundindex-extralength+newname.length, destinationparam.value.length) + const extralength = newname.length - parsedBaseLabel.length + destinationparam.value = destinationparam.value.substring(0, foundindex) + newname + destinationparam.value.substring(foundindex - extralength + newname.length, destinationparam.value.length) console.log("New: ", workflow.branches[key].conditions[subkey].destination.value) - } else { + } else { break } - + // Break no matter what after 5 replaces. May need to increase if (cnt >= 5) { break } - + } - } catch (e) { + } catch (e) { console.log("Failed value replacement based on index: ", e) } } @@ -1848,7 +1897,7 @@ const ParsedAction = (props) => { } } - for (let [key,keyval] in Object.entries(workflow.actions)) { + for (let [key, keyval] in Object.entries(workflow.actions)) { if (workflow.actions[key].id === selectedAction.id) { continue } @@ -1873,7 +1922,7 @@ const ParsedAction = (props) => { var cnt = -1 var previous = 0 while (true) { - cnt += 1 + cnt += 1 // Need to make sure e.g. changing the first here doesn't change the 2nd // $change_me // $change_me_2 @@ -1881,303 +1930,332 @@ const ParsedAction = (props) => { if (foundindex === previous && foundindex !== 0) { break } - + if (foundindex >= 0) { - previous = foundindex+newname.length + previous = foundindex + newname.length // Need to add diff of length to word - + // Check location: // If it's a-zA-Z_ then don't replace - if (param.value.length > foundindex+parsedBaseLabel.length) { + if (param.value.length > foundindex + parsedBaseLabel.length) { const regex = /[a-zA-Z0-9_]/g; - const match = param.value[foundindex+parsedBaseLabel.length].match(regex); + const match = param.value[foundindex + parsedBaseLabel.length].match(regex); if (match !== null) { continue } } - - const extralength = newname.length-parsedBaseLabel.length - param.value = param.value.substring(0, foundindex) + newname + param.value.substring(foundindex-extralength+newname.length, param.value.length) - } else { + const extralength = newname.length - parsedBaseLabel.length + param.value = param.value.substring(0, foundindex) + newname + param.value.substring(foundindex - extralength + newname.length, param.value.length) + + } else { break } - + // Break no matter what after 5 replaces. May need to increase if (cnt >= 5) { break } - + } - } catch (e) { + } catch (e) { console.log("Failed value replacement based on index: ", e) } } } setWorkflow(workflow) - setUpdate(Math.random()) + setUpdate(Math.random()) setPrevActionName(name) }} />
{/*!isCloud ? null :*/} -
- - - Delay - { - setDelay(event.target.value) - }} - /> - - -
+
+ + + Delay + { + setDelay(event.target.value) + }} + /> + + +
{/**/}
- - )} + + )} - {selectedApp.name !== undefined && - selectedAction.authentication !== null && - selectedAction.authentication !== undefined && - selectedAction.authentication.length === 0 && - requiresAuthentication ? ( -
- - - - - -
- ) : null} + setAuthenticationModalOpen(true); + }} + > + Authenticate{" "} + {selectedApp.name.replaceAll("_", " ")} + + + +
+ ) : null} - {selectedAction.authentication !== undefined && + {selectedAction.authentication !== undefined && selectedAction.authentication !== null && selectedAction.authentication.length > 0 ? ( -
- Authentication -
- { - if (selectedAction.parameters[key].name === "url" && authenticationType?.type === "oauth2-app" && selectedAction.parameters[key].value.includes("http")) { - continue - } + if (e.target.value === "No selection") { + selectedAction.selectedAuthentication = {}; + selectedAction.authentication_id = ""; - if (selectedAction.parameters[key].example !== undefined && selectedAction.parameters[key].example !== null && selectedAction.parameters[key].example !== "") { - if (selectedAction.parameters[key].example.toLowerCase().includes("apik") || selectedAction.parameters[key].example.toLowerCase().includes("key") || selectedAction.parameters[key].example.toLowerCase().includes("pass") || selectedAction.parameters[key].example.toLowerCase().includes("****")) { - selectedAction.parameters[key].value = "" - } else { - selectedAction.parameters[key].value = selectedAction.parameters[key].example - } + for (let [key, keyval] in Object.entries(selectedAction.parameters)) { + if (selectedAction.parameters[key].configuration === false) { + //console.log("FIELDSKIP: ", selectedAction.parameters[key].name) + continue + } - } else { - selectedAction.parameters[key].value = "" - } - } - setSelectedAction(selectedAction) - setUpdate(Math.random()) - - } else if (e.target.value === "authgroups") { - if (authGroups !== undefined && authGroups !== null && authGroups.length === 0) { - toast("No auth groups created. Opening window to create one") + if (selectedAction.parameters[key].name === "url" && authenticationType?.type === "oauth2-app" && selectedAction.parameters[key].value.includes("http")) { + continue + } - setTimeout(() => { - window.open("/admin?tab=app_auth", "_blank") - }, 2500) - } else { - selectedAction.selectedAuthentication = {}; - selectedAction.authentication_id = "authgroups" + if (selectedAction.parameters[key].example !== undefined && selectedAction.parameters[key].example !== null && selectedAction.parameters[key].example !== "") { + if (selectedAction.parameters[key].example.toLowerCase().includes("apik") || selectedAction.parameters[key].example.toLowerCase().includes("key") || selectedAction.parameters[key].example.toLowerCase().includes("pass") || selectedAction.parameters[key].example.toLowerCase().includes("****")) { + selectedAction.parameters[key].value = "" + } else { + selectedAction.parameters[key].value = selectedAction.parameters[key].example + } - for (let [key,keyval] in Object.entries(selectedAction.parameters)) { - //console.log(selectedAction.parameters[key]) - if (selectedAction.parameters[key].configuration) { + } else { + selectedAction.parameters[key].value = "" + } + } - if (selectedAction.parameters[key].name === "url" && authenticationType?.type === "oauth2-app") { - } else { - selectedAction.parameters[key].value = "authgroup controlled" - } - } - } + setSelectedAction(selectedAction) + setUpdate(Math.random()) - setSelectedAction(selectedAction) - setUpdate(Math.random()) - } - } else { - selectedAction.selectedAuthentication = e.target.value; - selectedAction.authentication_id = e.target.value.id; - setSelectedAction(selectedAction) - setUpdate(Math.random()) - } - }} - style={{ - backgroundColor: theme.palette.inputColor, - color: "white", - height: 35, - maxWidth: rightsidebarStyle.maxWidth - 80, - borderRadius: theme.palette?.borderRadius, - }} - > - - No selection - - {selectedAction.authentication.map((data) => { - if (data.last_modified === true) { - //console.log("LAST MODIFIED: ", data.label) - } + } else if (e.target.value === "authgroups") { + if (authGroups !== undefined && authGroups !== null && authGroups.length === 0) { + toast("No auth groups created. Opening window to create one") - return ( - + setTimeout(() => { + window.open("/admin?tab=app_auth", "_blank") + }, 2500) + } else { + selectedAction.selectedAuthentication = {}; + selectedAction.authentication_id = "authgroups" - {data?.validation?.valid === true ? - + for (let [key, keyval] in Object.entries(selectedAction.parameters)) { + //console.log(selectedAction.parameters[key]) + if (selectedAction.parameters[key].configuration) { + + if (selectedAction.parameters[key].name === "url" && authenticationType?.type === "oauth2-app") { + } else { + selectedAction.parameters[key].value = "authgroup controlled" + } + } + } + + setSelectedAction(selectedAction) + setUpdate(Math.random()) + } + } else { + selectedAction.selectedAuthentication = e.target.value; + selectedAction.authentication_id = e.target.value.id; + + setDistributeAuthToSuborgs(e.target.value?.suborg_distributed || false) + + setSelectedAction(selectedAction) + setUpdate(Math.random()) + } + }} + style={{ + backgroundColor: theme.palette.inputColor, + color: "white", + height: 35, + maxWidth: rightsidebarStyle.maxWidth - 80, + borderRadius: theme.palette?.borderRadius, + }} + > + + No selection + + {selectedAction.authentication.map((data) => { + if (data.last_modified === true) { + //console.log("LAST MODIFIED: ", data.label) + } + + return ( + + + {data?.validation?.valid === true ? + + + + : null} + {data?.last_modified === true ? + + : null} + {/*data.app.app_version !== undefined && data.app.app_version !== null && data.app.app_version !== "" && data.app.app_version !== "undefined" ? - - : null } - {data?.last_modified === true ? - - : null} - {/*data.app.app_version !== undefined && data.app.app_version !== null && data.app.app_version !== "" && data.app.app_version !== "undefined" ? - - : null*/} - {data.label} - - ); - })} + : null*/} + {data.label} + + ); + })} - + - - Auth Groups - + + Auth Groups + - + - - { - setAuthenticationModalOpen(true); - }} - > - - - -
-
- ) : null} + + { + setAuthenticationModalOpen(true); + }} + > + + + +
+ +
+ ) : null} - {selectedAction.authentication_id === "authgroups" && (authGroups === undefined || authGroups === null || authGroups.length === 0) ? - - - Create your first Authentication group - - - : null} + {selectedAction.authentication_id === "authgroups" && (authGroups === undefined || authGroups === null || authGroups.length === 0) ? + + + Create your first Authentication group + + + : null} - {/*showEnvironment !== undefined && showEnvironment && environments.length > 1 && !isIntegration ? ( + {/*showEnvironment !== undefined && showEnvironment && environments.length > 1 && !isIntegration ? (
Environment 0 - ? selectedAction.execution_variable.name - : "No selection" - } - SelectDisplayProps={{ - style: { - }, - }} - fullWidth - onChange={(e) => { - if (e.target.value === "No selection") { - selectedAction.execution_variable = { name: "No selection" }; - } else { - const value = workflow.execution_variables.find( - (a) => a.name === e.target.value - ); - selectedAction.execution_variable = value; - } - setSelectedAction(selectedAction); - setUpdate(Math.random()); - }} - style={{ - backgroundColor: theme.palette.inputColor, - color: "white", - height: "50px", - borderRadius: theme.palette?.borderRadius, - }} - > - - No selection - - - {workflow.execution_variables.map((data) => ( - - {data.name} - - ))} - -
- ) : null} + {workflow.execution_variables !== undefined && workflow.execution_variables !== null && workflow.execution_variables.length > 0 ? ( +
+ Execution variable (optional) + +
+ ) : null} - -
- {/*hideExtraTypes ? null : + +
+ {/*hideExtraTypes ? null :
Actions
*/} - {setNewSelectedAction !== undefined ? ( - { - // FIXME: Sorting - // Most popular - // Is categorized - // Uncategorized - return option.category_label !== undefined && option.category_label !== null && option.category_label.length > 0 ? "Most used" : "All Actions"; - }} - renderGroup={(params) => { + {setNewSelectedAction !== undefined ? ( + { + // FIXME: Sorting + // Most popular + // Is categorized + // Uncategorized + return option.category_label !== undefined && option.category_label !== null && option.category_label.length > 0 ? "Most used" : "All Actions"; + }} + renderGroup={(params) => { - return ( -
  • - {params.group} - {params.children} -
  • - ) - }} - options={renderedActionOptions} - ListboxProps={{ - style: { - backgroundColor: theme.palette.surfaceColor, - color: "white", - }, - }} - filterOptions={(options, { inputValue }) => { - const lowercaseValue = inputValue.toLowerCase() - options = options.filter(x => x.name.replaceAll("_", " ").toLowerCase().includes(lowercaseValue) || x.description.toLowerCase().includes(lowercaseValue)) - - return options - }} - getOptionLabel={(option) => { - if (option === undefined || option === null || option.name === undefined || option.name === null ) { - return null; - } - - const newname = ( - option.name.charAt(0).toUpperCase() + option.name.substring(1) - ).replaceAll("_", " "); - - return newname; - }} - fullWidth - sx={{ - '& .MuiOutlinedInput-root': { - height: 40, // Adjust the input height - }, - '& .MuiAutocomplete-input': { - padding: '8px', // Adjust the text padding - }, - }} - - style={{ - backgroundColor: theme.palette.backgroundColor, - height: 35, - borderRadius: theme.palette?.borderRadius, - }} - onChange={(event, newValue) => { - // Workaround with event lol - if (newValue !== undefined && newValue !== null) { - setNewSelectedAction({ - target: { - value: newValue.name - } - }); - } - }} - renderOption={(props, option, state) => { - var newActionname = option.name; - if (option.label !== undefined && option.label !== null && option.label.length > 0) { - newActionname = option.label; - } - - var newActiondescription = option.description; - //console.log("DESC: ", newActiondescription) - if (option.description === undefined || option.description === null) { - newActiondescription = "Description: No description defined for this action" - } else { - newActiondescription = "Description: "+newActiondescription - } - - const iconInfo = GetIconInfo({ name: option.name }); - const useIcon = iconInfo.originalIcon; - - if (newActionname === undefined || newActionname === null) { - newActionname = "No name" - option.name = "No name" - option.label = "No name" - } - - newActionname = (newActionname.charAt(0).toUpperCase() + newActionname.substring(1)).replaceAll("_", " "); - - var method = "" - var extraDescription = "" - if (option.name.includes("get_")) { - method = "GET" - } else if (option.name.includes("post_")) { - method = "POST" - } else if (option.name.includes("put_")) { - method = "PUT" - } else if (option.name.includes("patch_")) { - method = "PATCH" - } else if (option.name.includes("delete_")) { - method = "DELETE" - } else if (option.name.includes("options_")) { - method = "OPTIONS" - } else if (option.name.includes("connect_")) { - method = "CONNECT" - } - - // FIXME: Should it require a base URL? - if (method.length > 0 && option.description !== undefined && option.description !== null && option.description.includes("http")) { - var extraUrl = "" - const descSplit = option.description.split("\n") - // Last line of descSplit - if (descSplit.length > 0) { - extraUrl = descSplit[descSplit.length-1] - } - - if (extraUrl.length > 0) { - if (extraUrl.includes(" ")) { - extraUrl = extraUrl.split(" ")[0] - } - - if (extraUrl.includes("#")) { - extraUrl = extraUrl.split("#")[0] - } - - extraDescription = `${method} ${extraUrl}` - } else { - //console.log("No url found. Check again :)") - } - } - - return ( - - ); - }} - renderInput={(params) => { - if (params.inputProps?.value) { - const prefixes = ["Post", "Put", "Patch"]; - for (let prefix of prefixes) { - if (params.inputProps.value.startsWith(prefix)) { - let newValue = params.inputProps.value.replace(prefix + " ", ""); - if (newValue.length > 1) { - newValue = newValue.charAt(0).toUpperCase() + newValue.substring(1); - } - // Set the new value without mutating inputProps - params = { ...params, inputProps: { ...params.inputProps, value: newValue } }; - break; - } - } - // Check if it starts with "Get List" and method is "Get" - if (params.inputProps.value.startsWith("Get List")) { - console.log("Get List"); - } - } - - - const actionDescription = null - - return ( - + {params.group} + {params.children} + + ) + }} + options={renderedActionOptions} + ListboxProps={{ + style: { + backgroundColor: theme.palette.surfaceColor, + color: "white", }, }} - > - { + const lowercaseValue = inputValue.toLowerCase() + options = options.filter(x => x.name.replaceAll("_", " ").toLowerCase().includes(lowercaseValue) || x.description.toLowerCase().includes(lowercaseValue)) - data-lpignore="true" - autocomplete="off" - dataLPIgnore="true" - autoComplete="off" - - color="primary" - id="checkbox-search" - variant="body1" - style={theme.palette.textFieldStyle} - label={isIntegration ? "Choose a category" : "Find Actions"} - variant="outlined" - name={`disable_autocomplete_${Math.random()}`} - /> - - ); - }} - /> - ) : null} - -
    { - selectedActionParameters !== undefined && selectedActionParameters !== null && Object.getOwnPropertyNames(selectedAction).length > 0 && selectedActionParameters.length > 0 ? -
    - {isIntegration ? - apps !== undefined && apps !== null && apps.length > 0 ? -
    -
    { - - selectedAction.example = "noapp" - selectedAction.large_image = newimage - if (cy !== undefined && cy !== null) { - const foundnode = cy.getElementById(selectedAction.id) - if (foundnode !== undefined && foundnode !== null) { - foundnode.data("large_image", newimage) - } + return options + }} + getOptionLabel={(option) => { + if (option === undefined || option === null || option.name === undefined || option.name === null) { + return null; } - const iconInfo = GetIconInfo(selectedAction) - if (iconInfo !== undefined && iconInfo !== null) { - selectedAction.fillGradient = iconInfo.fillGradient - - selectedAction.iconBackground = iconInfo.iconBackgroundColor - selectedAction.fillstyle = "linear-gradient" + const newname = ( + option.name.charAt(0).toUpperCase() + option.name.substring(1) + ).replaceAll("_", " "); + + return newname; + }} + fullWidth + sx={{ + '& .MuiOutlinedInput-root': { + height: 40, // Adjust the input height + }, + '& .MuiAutocomplete-input': { + padding: '8px', // Adjust the text padding + }, + }} + + style={{ + backgroundColor: theme.palette.backgroundColor, + height: 35, + borderRadius: theme.palette?.borderRadius, + }} + onChange={(event, newValue) => { + // Workaround with event lol + if (newValue !== undefined && newValue !== null) { + setNewSelectedAction({ + target: { + value: newValue.name + } + }); + } + }} + renderOption={(props, option, state) => { + var newActionname = option.name; + if (option.label !== undefined && option.label !== null && option.label.length > 0) { + newActionname = option.label; } - if (paramIndex === -1) { - console.log("Couldn't find app_name parameter") - selectedAction.parameters.push({ - name: "app_name", - value: wrapperapp.name, - autocompleted: false, - }) + var newActiondescription = option.description; + //console.log("DESC: ", newActiondescription) + if (option.description === undefined || option.description === null) { + newActiondescription = "Description: No description defined for this action" } else { - selectedAction.parameters[paramIndex].value = wrapperapp.name - } - - setSelectedAction(selectedAction) - setUpdate(Math.random()) - - }}> - -
    - -
    -
    -
    - {apps.map((app, appIndex) => { - if (app.categories === undefined || app.categories === null || app.categories.length === 0) { - return null + newActiondescription = "Description: " + newActiondescription } - var found = false + const iconInfo = GetIconInfo({ name: option.name }); + const useIcon = iconInfo.originalIcon; + if (newActionname === undefined || newActionname === null) { + newActionname = "No name" + option.name = "No name" + option.label = "No name" + } - for (var key in app.categories) { - if (app.categories[key].toLowerCase() !== actionname) { - continue + newActionname = (newActionname.charAt(0).toUpperCase() + newActionname.substring(1)).replaceAll("_", " "); + + var method = "" + var extraDescription = "" + if (option.name.includes("get_")) { + method = "GET" + } else if (option.name.includes("post_")) { + method = "POST" + } else if (option.name.includes("put_")) { + method = "PUT" + } else if (option.name.includes("patch_")) { + method = "PATCH" + } else if (option.name.includes("delete_")) { + method = "DELETE" + } else if (option.name.includes("options_")) { + method = "OPTIONS" + } else if (option.name.includes("connect_")) { + method = "CONNECT" + } + + // FIXME: Should it require a base URL? + if (method.length > 0 && option.description !== undefined && option.description !== null && option.description.includes("http")) { + var extraUrl = "" + const descSplit = option.description.split("\n") + // Last line of descSplit + if (descSplit.length > 0) { + extraUrl = descSplit[descSplit.length - 1] } - found = true - break - } + if (extraUrl.length > 0) { + if (extraUrl.includes(" ")) { + extraUrl = extraUrl.split(" ")[0] + } - if (!found) { - return null - } + if (extraUrl.includes("#")) { + extraUrl = extraUrl.split("#")[0] + } - var isAppSelected = false - const paramIndex = selectedAction.parameters.findIndex((param) => param.name === "app_name") - if (paramIndex > -1) { - // Check the actual value and if it's the same - if (selectedAction.parameters[paramIndex].value === app.name) { - isAppSelected = true + extraDescription = `${method} ${extraUrl}` + } else { + //console.log("No url found. Check again :)") } } return ( -
    { - selectedAction.example = "" - selectedAction.large_image = app.large_image - if (cy !== undefined && cy !== null) { - const foundnode = cy.getElementById(selectedAction.id) - if (foundnode !== undefined && foundnode !== null) { - foundnode.data("large_image", app.large_image) - } - } - - if (paramIndex === -1) { - console.log("Couldn't find app_name parameter") - selectedAction.parameters.push({ - name: "app_name", - value: app.name, - autocompleted: false, - }) - } else { - selectedAction.parameters[paramIndex].value = app.name + + ); + }} + renderInput={(params) => { + if (params.inputProps?.value) { + const prefixes = ["Post", "Put", "Patch"]; + for (let prefix of prefixes) { + if (params.inputProps.value.startsWith(prefix)) { + let newValue = params.inputProps.value.replace(prefix + " ", ""); + if (newValue.length > 1) { + newValue = newValue.charAt(0).toUpperCase() + newValue.substring(1); + } + // Set the new value without mutating inputProps + params = { ...params, inputProps: { ...params.inputProps, value: newValue } }; + break; } - - setSelectedAction(selectedAction) - setUpdate(Math.random()) + } + // Check if it starts with "Get List" and method is "Get" + if (params.inputProps.value.startsWith("Get List")) { + console.log("Get List"); + } + } - }}> - - - -
    - ) - })} -
    - : null - : - -
    - {/* + + const actionDescription = null + + return ( + + + + ); + }} + /> + ) : null} + +
    { + selectedActionParameters !== undefined && selectedActionParameters !== null && Object.getOwnPropertyNames(selectedAction).length > 0 && selectedActionParameters.length > 0 ? +
    + {isIntegration ? + apps !== undefined && apps !== null && apps.length > 0 ? +
    +
    { + + selectedAction.example = "noapp" + selectedAction.large_image = newimage + if (cy !== undefined && cy !== null) { + const foundnode = cy.getElementById(selectedAction.id) + if (foundnode !== undefined && foundnode !== null) { + foundnode.data("large_image", newimage) + } + } + + const iconInfo = GetIconInfo(selectedAction) + if (iconInfo !== undefined && iconInfo !== null) { + selectedAction.fillGradient = iconInfo.fillGradient + + selectedAction.iconBackground = iconInfo.iconBackgroundColor + selectedAction.fillstyle = "linear-gradient" + } + + if (paramIndex === -1) { + console.log("Couldn't find app_name parameter") + selectedAction.parameters.push({ + name: "app_name", + value: wrapperapp.name, + autocompleted: false, + }) + } else { + selectedAction.parameters[paramIndex].value = wrapperapp.name + } + + setSelectedAction(selectedAction) + setUpdate(Math.random()) + + }}> + +
    + +
    +
    +
    + {apps.map((app, appIndex) => { + if (app.categories === undefined || app.categories === null || app.categories.length === 0) { + return null + } + + var found = false + + + for (var key in app.categories) { + if (app.categories[key].toLowerCase() !== actionname) { + continue + } + + found = true + break + } + + if (!found) { + return null + } + + var isAppSelected = false + const paramIndex = selectedAction.parameters.findIndex((param) => param.name === "app_name") + if (paramIndex > -1) { + // Check the actual value and if it's the same + if (selectedAction.parameters[paramIndex].value === app.name) { + isAppSelected = true + } + } + + return ( +
    { + selectedAction.example = "" + selectedAction.large_image = app.large_image + if (cy !== undefined && cy !== null) { + const foundnode = cy.getElementById(selectedAction.id) + if (foundnode !== undefined && foundnode !== null) { + foundnode.data("large_image", app.large_image) + } + } + + if (paramIndex === -1) { + console.log("Couldn't find app_name parameter") + selectedAction.parameters.push({ + name: "app_name", + value: app.name, + autocompleted: false, + }) + } else { + selectedAction.parameters[paramIndex].value = app.name + } + + setSelectedAction(selectedAction) + setUpdate(Math.random()) + + }}> + + + +
    + ) + })} +
    + : null + : + +
    + {/* */} - - } + + } - {selectedAction.template === true && selectedAction.matching_actions !== undefined && selectedAction.matching_actions !== null && selectedAction.matching_actions.length > 0 ? -
    - - Select an app you want to use - - { - console.log("LABEL: ", option) - if ( - option === undefined || - option === null || - option.app_name === undefined || - option.app_name === null - ) { - return null; - } - - const newname = ( - option.app_name.charAt(0).toUpperCase() + option.app_name.substring(1) - ).replaceAll("_", " "); - return newname; - }} - options={selectedAction.matching_actions} - fullWidth - style={{ - backgroundColor: theme.palette.inputColor, - height: 35, - borderRadius: theme.palette?.borderRadius, - }} - onChange={(event, newValue) => { - console.log("SELECT: ", event, newValue) - // Workaround with event lol - //if (newValue !== undefined && newValue !== null) { - // setNewSelectedAction({ target: { value: newValue.name } }); - //} - }} - renderOption={(props, data, state) => { - var newActionname = data.app_name; - if ( - data.label !== undefined && - data.label !== null && - data.label.length > 0 - ) { - newActionname = data.label; - } - - const iconInfo = GetIconInfo({ name: data.app_name }); - const useIcon = iconInfo.originalIcon; - - console.log("Actionname 1: ", newActionname) - - newActionname = ( - newActionname.charAt(0).toUpperCase() + - newActionname.substring(1) - ).replaceAll("_", " "); - - return ( -
    - - {useIcon} - - {newActionname} -
    - ); - }} - renderInput={(params) => { - if (params.inputProps !== undefined && params.inputProps !== null && params.inputProps.value !== undefined && params.inputProps.value !== null) { - const prefixes = ["Post", "Put", "Patch"] - for (let [key,keyval] in Object.entries(prefixes)) { - if (params.inputProps.value.startsWith(prefixes[key])) { - params.inputProps.value = params.inputProps.value.replace(prefixes[key]+" ", "", -1) - if (params.inputProps.value.length > 1) { - params.inputProps.value = params.inputProps.value.charAt(0).toUpperCase()+params.inputProps.value.substring(1) + {selectedAction.template === true && selectedAction.matching_actions !== undefined && selectedAction.matching_actions !== null && selectedAction.matching_actions.length > 0 ? +
    + + Select an app you want to use + + { + console.log("LABEL: ", option) + if ( + option === undefined || + option === null || + option.app_name === undefined || + option.app_name === null + ) { + return null; + } + + const newname = ( + option.app_name.charAt(0).toUpperCase() + option.app_name.substring(1) + ).replaceAll("_", " "); + return newname; + }} + options={selectedAction.matching_actions} + fullWidth + style={{ + backgroundColor: theme.palette.inputColor, + height: 35, + borderRadius: theme.palette?.borderRadius, + }} + onChange={(event, newValue) => { + console.log("SELECT: ", event, newValue) + // Workaround with event lol + //if (newValue !== undefined && newValue !== null) { + // setNewSelectedAction({ target: { value: newValue.name } }); + //} + }} + renderOption={(props, data, state) => { + var newActionname = data.app_name; + if ( + data.label !== undefined && + data.label !== null && + data.label.length > 0 + ) { + newActionname = data.label; + } + + const iconInfo = GetIconInfo({ name: data.app_name }); + const useIcon = iconInfo.originalIcon; + + console.log("Actionname 1: ", newActionname) + + newActionname = ( + newActionname.charAt(0).toUpperCase() + + newActionname.substring(1) + ).replaceAll("_", " "); + + return ( +
    + + {useIcon} + + {newActionname} +
    + ); + }} + renderInput={(params) => { + if (params.inputProps !== undefined && params.inputProps !== null && params.inputProps.value !== undefined && params.inputProps.value !== null) { + const prefixes = ["Post", "Put", "Patch"] + for (let [key, keyval] in Object.entries(prefixes)) { + if (params.inputProps.value.startsWith(prefixes[key])) { + params.inputProps.value = params.inputProps.value.replace(prefixes[key] + " ", "", -1) + if (params.inputProps.value.length > 1) { + params.inputProps.value = params.inputProps.value.charAt(0).toUpperCase() + params.inputProps.value.substring(1) + } + break + } + } + } + + return ( + + ); + }} + /> +
    + : null} + {selectedAction.description !== undefined && selectedAction.description !== null && selectedAction.description.length > 0 && hiddenParameters === false ? ( +
    + + Description + + + {selectedAction.description} + +
    + ) : null} + + {suggestionInfo()} + {selectedActionParameters?.map((data, count) => { + if (data.variant === "") { + data.variant = "STATIC_VALUE"; + } + + if (isIntegration && data.name === "app_name") { + return null + } + + if (data.value === "authgroup controlled") { + if (data?.name === "url" && authenticationType?.type === "oauth2-app") { + } else { + return null + } + } + + if (selectedAction.parameters === undefined || selectedAction.parameters === null || selectedAction.parameters.length !== selectedActionParameters.length) { + + //selectedAction.parameters = selectedActionParameters + //console.log("PARAM BUG - length change(?): ", selectedAction) + } + + //!selectedAction.auth_not_required && + if (selectedAction.selectedAuthentication !== undefined && selectedAction.selectedAuthentication.fields !== undefined && selectedAction.selectedAuthentication.fields[data.name] !== undefined) { + + // This sets the placeholder in the frontend. (Replaced in backend) + if (selectedActionParameters[count] !== undefined) { + selectedActionParameters[count].value = selectedAction.selectedAuthentication.fields[data.name] + } + + if (selectedAction.parameters[count] !== undefined) { + selectedAction.parameters[count].value = selectedAction.selectedAuthentication.fields[data.name] + } + + setSelectedAction(selectedAction); + //setUpdate(Math.random()) + + if (authWritten) { + return null; + } + + authWritten = true; + return null + + /* + // FIXME: Is this part necessary to show? + return ( + + Authentication fields are hidden + + ); + */ + } + + + // Added autofill to make this ALOT simpler + if (isCloud && (selectedAction.app_name === "Shuffle Tools" || selectedAction.app_name === "email") && (selectedAction.name === "send_email_shuffle" || selectedAction.name === "send_sms_shuffle") && data.name === "apikey") { + if (selectedActionParameters[count].length === 0) { + selectedAction.parameters[count].value = "TMP: Will be replaced during execution if cloud" + setSelectedAction(selectedAction) + } + + return null + } + + var staticcolor = "inherit"; + var actioncolor = "inherit"; + var varcolor = "inherit"; + var multiline + if ( + data.multiline !== undefined && + data.multiline !== null && + data.multiline === true + ) { + multiline = true; + } + + // make data.value from array to comma separated string if it is an array + if (data.value !== undefined && data.value !== null && Array.isArray(data.value)) { + data.value = data.value.join(",") + } + + if (data.value !== undefined && data.value !== null && + data.value.startsWith("{") && data.value.endsWith("}")) { + multiline = true + } + + var placeholder = "Value"; + if (data.example !== undefined && data.example !== null && data.example.length > 0) { + + placeholder = data.example; + + // if (data.name === "url") { + // data.value = data.example; + // } + // In case of data.example + if (data.value === undefined || data.value === null) { + data.value = "" + } + + if (data.value.length === 0) { + if (data.name.toLowerCase() === "headers") { + //console.log("Should show headers field instead with + and -!") + + // Check if file ID exists + // + const fileFound = selectedActionParameters.find(param => param.name === "file_id") + if (fileFound === undefined || fileFound === null) { + data.value = data.example + } else { + // Purposely unset it if set by default when using files + data.value = "" + } + } + } + + /* + if (data.name !== "queries" && data.name !== "key" && data.name !== "value" ) { + data.value = data.example + } + } + */ + } + + if (selectedAction.name === "custom_action" && data.name === "body") { + for (var key in selectedActionParameters) { + const param = selectedActionParameters[key] + if (param.name === "method") { + if (param.value === "GET") { + return null } - break } } } - return ( - - ); - }} - /> -
    - : null} - {selectedAction.description !== undefined && selectedAction.description !== null && selectedAction.description.length > 0 && hiddenParameters === false ? ( -
    - - Description - - - {selectedAction.description} - -
    - ) : null} - - {suggestionInfo()} - {selectedActionParameters?.map((data, count) => { - if (data.variant === "") { - data.variant = "STATIC_VALUE"; - } - - if (isIntegration && data.name === "app_name") { - return null - } - - if (data.value === "authgroup controlled") { - if (data?.name === "url" && authenticationType?.type === "oauth2-app") { - } else { - return null - } - } - - if (selectedAction.parameters === undefined || selectedAction.parameters === null || selectedAction.parameters.length !== selectedActionParameters.length) { - - //selectedAction.parameters = selectedActionParameters - //console.log("PARAM BUG - length change(?): ", selectedAction) - } - - //!selectedAction.auth_not_required && - if (selectedAction.selectedAuthentication !== undefined && selectedAction.selectedAuthentication.fields !== undefined && selectedAction.selectedAuthentication.fields[data.name] !== undefined) { - - // This sets the placeholder in the frontend. (Replaced in backend) - if (selectedActionParameters[count] !== undefined) { - selectedActionParameters[count].value = selectedAction.selectedAuthentication.fields[data.name] - } - - if (selectedAction.parameters[count] !== undefined) { - selectedAction.parameters[count].value = selectedAction.selectedAuthentication.fields[data.name] - } - - setSelectedAction(selectedAction); - //setUpdate(Math.random()) - - if (authWritten) { - return null; - } - - authWritten = true; - return null - - /* - // FIXME: Is this part necessary to show? - return ( - - Authentication fields are hidden - - ); - */ - } - - - // Added autofill to make this ALOT simpler - if (isCloud && (selectedAction.app_name === "Shuffle Tools" || selectedAction.app_name === "email") && (selectedAction.name === "send_email_shuffle" || selectedAction.name === "send_sms_shuffle") && data.name === "apikey") { - if (selectedActionParameters[count].length === 0) { - selectedAction.parameters[count].value = "TMP: Will be replaced during execution if cloud" - setSelectedAction(selectedAction) - } - - return null - } - - var staticcolor = "inherit"; - var actioncolor = "inherit"; - var varcolor = "inherit"; - var multiline - if ( - data.multiline !== undefined && - data.multiline !== null && - data.multiline === true - ) { - multiline = true; - } - - // make data.value from array to comma separated string if it is an array - if (data.value !== undefined && data.value !== null && Array.isArray(data.value)) { - data.value = data.value.join(",") - } - - if (data.value !== undefined && data.value !== null && - data.value.startsWith("{") && data.value.endsWith("}")) { - multiline = true - } - - var placeholder = "Value"; - if (data.example !== undefined && data.example !== null && data.example.length > 0) { - - placeholder = data.example; - - // if (data.name === "url") { - // data.value = data.example; - // } - // In case of data.example - if (data.value === undefined || data.value === null) { - data.value = "" - } - - if (data.value.length === 0) { - if (data.name.toLowerCase() === "headers") { - //console.log("Should show headers field instead with + and -!") - - // Check if file ID exists - // - const fileFound = selectedActionParameters.find(param => param.name === "file_id") - if (fileFound === undefined || fileFound === null) { - data.value = data.example - } else { - // Purposely unset it if set by default when using files - data.value = "" - } - } - } - - /* - if (data.name !== "queries" && data.name !== "key" && data.name !== "value" ) { - data.value = data.example - } - } - */ - } - - if (selectedAction.name === "custom_action" && data.name === "body") { - for (var key in selectedActionParameters) { - const param = selectedActionParameters[key] - if (param.name === "method") { - if (param.value === "GET") { - return null - } - } - } - } - - if (data.name.startsWith("${") && data.name.endsWith("}")) { - const paramcheck = selectedAction.parameters.find((param) => param.name === "body"); - - - if (paramcheck !== undefined && paramcheck !== null) { - if ( - paramcheck["value_replace"] !== undefined && - paramcheck["value_replace"] !== null - ) { - //console.log("IN THE VALUE REPLACE: ", paramcheck["value_replace"]) - const subparamindex = paramcheck["value_replace"].findIndex( - (param) => param.key === data.name - ); - if (subparamindex !== -1) { - data.value = - paramcheck["value_replace"][subparamindex]["value"]; - } - } - } - } - - - var showCacheConfig = false - if (data.name === "key" && selectedAction.name.includes("cache") && selectedAction.app_name === "Shuffle Tools") { - // Show a key popout button - showCacheConfig = true - } - - var disabled = false; - var rows = "3"; - var openApiHelperText = "This is an OpenAPI specific field"; - - - if (selectedApp.generated && data.name === "headers") { - //console.log("HEADER: ", data) - //if (data.value.length === 0) { - //} - //setSelectedActionParameters(selectedActionParameters) - } - - var hideBodyButtonValue = ( -
    - - { - // Set localstorage - localStorage.setItem("hideBody", "true") - - setHideBody(false) - const updatedParameters = selectedActionParameters.map((param) => { - if (param.name === "body") { - return { - ...param, - id: "UNTOGGLED", - } - } - - if (param.description === openApiFieldDesc) { - // Check required fields here - if (selectedAction.required_body_fields !== undefined && selectedAction.required_body_fields !== null && selectedAction.required_body_fields.length > 0) { - // Look for the field name in the required_body_fields - if (selectedAction.required_body_fields.includes(param.name)) { - param.required = true - } else { - param.required = false - } - } - - return { ...param, field_active: true } - } - - return param - }) - - setSelectedActionParameters(updatedParameters) - }} - /> - { - localStorage.setItem("hideBody", "false") - setHideBody(true) - // Make sure the body field is shown - var foundvalue = false - const updatedParameters = selectedActionParameters.map((param) => { - if (param.name === "body") { - return { - ...param, - id: "TOGGLED", - } - } - - if (param.description === openApiFieldDesc) { - if (param.value.length > 0) { - foundvalue = true - } - - return { ...param, field_active: false } - } - - return param - }) - - if (foundvalue === true) { - toast.info("Please fill either Simple fields OR Advanced body, not both") - } - - setSelectedActionParameters(updatedParameters) - }} - /> - -
    - ) - - var showButtonField = false - if (selectedApp.generated === true && data.name === "body") { - const regex = /\${(\w+)}/g; - const found = placeholder.match(regex); - - var newhidebody = hideBody - showButtonField = true - if (found === undefined || found === null || found.length === 0) { - newhidebody = false - hideBodyButtonValue = null - - if (hideBody === false) { - setHideBody(true) - } - } - - if (newhidebody === true) { - //toast("BODYBUTTON TRUE") - } else { - - rows = "1"; - disabled = true; - openApiHelperText = "OpenAPI spec: fill the following fields."; - - var changed = false; - var tempArray = [] - for (let specKey in found) { - const tmpitem = found[specKey]; - var skip = false; - - for (let innerkey in selectedActionParameters) { - if (selectedActionParameters[innerkey].name === tmpitem) { - skip = true; - break; - } - } - - if (skip) { - //console.log("SKIPPING ", tmpitem) - continue; - } - - changed = true; - var isRequired = false - // Check if original field name is in the selectedAction.required_body_fields - if (selectedAction.required_body_fields !== undefined && selectedAction.required_body_fields !== null) { - for (let innerkey in selectedAction.required_body_fields) { - if (selectedAction.required_body_fields[innerkey] === tmpitem) { - isRequired = true - break - } - } - } - - tempArray.push({ - action_field: "", - configuration: false, - description: openApiFieldDesc, - example: "", - id: "", - multiline: false, - name: tmpitem, - options: null, - required: isRequired, - schema: { type: "string" }, - skip_multicheck: false, - tags: null, - value: "", - variant: "STATIC_VALUE", - field_active: true, - - autocompleted: false, - }); - } - - var required = selectedActionParameters.filter(item => item.required === true) - var notRequired = selectedActionParameters.filter(item => item.required === false) - - if (tempArray.length > 0) { - // Sort tempArray based on tempArray.required - tempArray.sort((a, b) => (a.required < b.required) ? 1 : -1) - // Add all items to the selectedActionParameters array - for (let innerkey in tempArray) { - tempArray[innerkey].id = "ADDED" - - if (tempArray[innerkey].required === true) { - required.push(tempArray[innerkey]) - } else { - notRequired.push(tempArray[innerkey]) - } - } - } - - if (changed) { - // Sort selectedActionParameters based on selectedActionParameters.required - // Find the "headers" and "queries" field names and put them on the first indexes anyway - var newArray = required.concat(notRequired) - - - setSelectedActionParameters(newArray) - } - - } - } - - const clickedFieldId = "rightside_field_" + count; - - var baseHelperText = "" - if (data !== undefined && data !== null && data.value !== undefined && data.value !== null && data.value.length > 0) { - baseHelperText = calculateHelpertext(data.value) - } - - var tmpitem = data.name.valueOf(); - if (data.name.startsWith("${") && data.name.endsWith("}")) { - tmpitem = tmpitem.slice(2, data.name.length - 1); - } - - if (tmpitem === "from_shuffle") { - tmpitem = "from" - } - - tmpitem = ( - tmpitem.charAt(0).toUpperCase() + tmpitem.substring(1) - ).replaceAll("_", " "); - - if (tmpitem === "Username basic") { - tmpitem = "Username" - } else if (tmpitem === "Password basic") { - tmpitem = "Password" - } - - // No longer multiline for new fields - //multiline = data.name.startsWith("${") && data.name.endsWith("}") ? true : multiline - - if (data.name === "body") { - //console.log("BODY: ", data) - if (hideBody === false) { - return hideBodyButtonValue - } - - rows = "4" - multiline = true - disabled = false - } - - const description = data.description === undefined ? "" : data?.description; - - const tooltipDescription = ( - - - - {tmpitem.charAt(0).toUpperCase() + tmpitem.slice(1)} - - { - setUiBox("closed") - }} - > - - - - - - - Required: {data.required === true || data.configuration === true ? "True" : "False"} - - - Description: {description} - - - Ex. : {data?.example?.length > 0 ? data.example : "No example available"} - - { - data?.configuration === true ? - ( - - Auth: Use "\$" instead of "$" - - ) : null - } - -
    { - e.preventDefault() - e.stopPropagation() - - localStorage.setItem("disabled_ui_box", "true") - setUiBox("closed") - }}> - - Don't show again - -
    -
    -
    - ); - - - var datafield = ( - - - - - { - event.preventDefault() - - // Get cursor position - // This makes it so we can put it in the right location? - setMenuPosition({ - top: event.pageY + 10, - left: event.pageX + 10, - }); - setShowDropdownNumber(count); - setShowDropdown(true); - setShowAutocomplete(true); - }} - /> - - - - ), - }} - multiline={multiline} - onClick={() => { - /* - setExpansionModalOpen(false); - */ - - if (setScrollConfig !== undefined && scrollConfig !== null && scrollConfig !== undefined && scrollConfig.selected !== clickedFieldId) { - - scrollConfig.selected = clickedFieldId - setScrollConfig(scrollConfig) - } - }} - rows={data.name.startsWith("${") && data.name.endsWith("}") ? 2 : rows} - color="primary" - // defaultValue={data.value} - value={ - data?.value - } - error={ - data?.error?.length > 0 ? true : false - } - helperText={data?.error?.length > 0 ? errorHelperText(data?.name,data?.value,data?.error) : returnHelperText(data.name, data.value)} - //options={{ - // theme: 'gruvbox-dark', - // keyMap: 'sublime', - // mode: 'python', - //}} - //height={multiline ? 50 : 150} - type={ - placeholder.includes("***") || - (data.configuration && - (data.name.toLowerCase().includes("api") || - data.name.toLowerCase().includes("key") || - data.name.toLowerCase().includes("pass"))) - ? "password" - : "text" - } - placeholder={placeholder} - onChange={(event) => { - handleParamChange(event, count, data) - }} - onFocus={(event) => { - // Get local storage key "disabled_ui_box" and check if it's true - const disabledUiBox = localStorage.getItem("disabled_ui_box") - if (disabledUiBox === "true") { - } else { - //setUiBox(event.target.id) - } - }} - onBlur={(event) => { - handleParamChange(event, count, data) - - baseHelperText = calculateHelpertext(event.target.value) - if (setLastSaved !== undefined) { - setLastSaved(false) - } - - // Check if we clicked the tooltip or not - const tooltipid = "rightside_field_tooltip" + count - const foundElement = document.getElementById(tooltipid) - if (foundElement !== null && foundElement !== undefined) { - console.log("FOUND: ", foundElement) - } else { - //console.log("TOOLTIP -> NOT FOUND") - //setUiBox("closed") - } - }} - /> - - ) - - // Finds headers from a string to be used for autocompletion - const findHeaders = (inputdata) => { - var splitdata = inputdata.split("\n") - - var foundnewline = false - var allValues = [] - for (let [key,keyval] in Object.entries(splitdata)) { - const line = splitdata[key] - if (line === "") { - foundnewline = true - continue - } - - var splitvalue = "" - if (line.includes(":")) { - splitvalue = ":" - } - - if (line.includes("=")) { - splitvalue = "=" - } - - if (splitvalue.length === 0){ - allValues.push({ - key: line, - value: "", - }) - continue - } - - var splitKeys = line.split(splitvalue) - if (splitKeys.length > 1) { - allValues.push({ - key: splitKeys[0].trim(), - value: splitKeys[1].trim(), - }) - } else { - console.log("No keys for ", line) - } - } - - // Just add one - if (foundnewline) { - allValues.push({ - key: "", - value: "", - }) - } - - return allValues - } - - if (data.name.toLowerCase() === "headers") { - //var tmpheaders = findHeaders(data.value) - var tmpheaders = findHeaders(selectedActionParameters[count].value) - const tmpdatafield = -
    - {tmpheaders.map((inputdata, index) => { - const oldkey = inputdata.key - const oldval = inputdata.value - - return ( - -
    - { - console.log("Change from oldkey to new: ", oldkey, e.target.value) - - // Find the right line to replace! - //const newval = selectedActionParameters[count].value.replace(oldval, e.target.value, 1) - const tmpsplit = selectedActionParameters[count].value.split("\n") - var valsplit = [] - var add_empty = false - for (let [key,keyval] in Object.entries(tmpsplit)) { - if (tmpsplit[key] === "") { - add_empty = true - continue - } - - valsplit.push(tmpsplit[key]) - } - - if (add_empty) { - valsplit.push("") - } - console.log("Split: ", valsplit) - - var newarr = [] - for (let [key,keyval] in Object.entries(valsplit)) { - var line = valsplit[key] - - if (key == index) { - if (oldkey === "") { - if (line.includes("=") || line.includes(":")) { - newarr.push(e.target.value + line) - } else { - newarr.push(e.target.value + ": " + line) - } - } else { - newarr.push(line.replace(oldkey, e.target.value, 1)) - } - - } else { - newarr.push(line) - } - } - - var newval = newarr.join("\n") - console.log("Fixed: ", newval) - - selectedActionParameters[count].value = newval - selectedAction.parameters[count].value = newval - setSelectedAction(selectedAction) - setSelectedActionParameters(selectedActionParameters) - }} - /> - { - console.log("Change from oldval to new: ", oldval, e.target.value) - - // Find the right line to replace! - //const newval = selectedActionParameters[count].value.replace(oldval, e.target.value, 1) - var tmpsplit = selectedActionParameters[count].value.split("\n") - var valsplit = [] - var add_empty = false - for (let [key,keyval] in Object.entries(tmpsplit)) { - if (tmpsplit[key] === "") { - add_empty = true - continue - } - - valsplit.push(tmpsplit[key]) - } - - if (add_empty) { - valsplit.push("") - } - console.log("Split: ", valsplit) - - var newarr = [] - for (let [key,keyval] in Object.entries(valsplit)) { - var line = valsplit[key] - - if (key == index) { - if (oldval === "") { - if (line.includes("=") || line.includes(":")) { - newarr.push(line + e.target.value) - } else { - newarr.push(line + ": " + e.target.value) - } - } else { - newarr.push(line.replace(oldval, e.target.value, 1)) - } - - } else { - newarr.push(line) - } - } - - var newval = newarr.join("\n") - console.log("Fixed: ", newval) - - selectedActionParameters[count].value = newval - selectedAction.parameters[count].value = newval - setSelectedAction(selectedAction) - setSelectedActionParameters(selectedActionParameters) - }} - /> -
    -
    - ) - })} - -
    - } - - //const regexp = new RegExp("\W+\.", "g") - //let match - //while ((match = regexp.exec(data.value)) !== null) { - // console.log(`Found ${match[0]} start=${match.index} end=${regexp.lastIndex}.`); - //} - - //const str = = data.value.search(submatch) - //console.log("FOUND? ", n) - //for (var key in keywords) { - // const keyword = keywords[key] - // if (data.value.includes(keyword)) { - // console.log("INCLUDED: ", keyword) - // } - //} - - if (files !== undefined && files !== null && data.name.toLowerCase() === "file_category") { - //selectedActionParameters[count].options.length > 0 - console.log("FileS: ", files) - if (files.namespaces !== undefined && files.namespaces !== null && files.namespaces.length > 0) { - data.options = files.namespaces - } - } - - //const keywords = ["len", "lower", "upper", "trim", "split", "length", "number", "parse", "join"] - if ( - selectedActionParameters[count].schema !== undefined && - selectedActionParameters[count].schema !== null && - selectedActionParameters[count].schema.type === "file" - ) { - datafield = ( - - - { - setMenuPosition({ - top: event.pageY + 10, - left: event.pageX + 10, - }); - setShowDropdownNumber(count); - setShowDropdown(true); - setShowAutocomplete(true); - }} - /> - - - ), - }} - helperText={returnHelperText(data.name, data.value)} - fullWidth - multiline={multiline} - rows={"3"} - color="primary" - defaultValue={data.value} - type={"text"} - placeholder={"The file ID to get"} - id={"rightside_field_" + count} - onChange={(event) => { - changeActionParameter(event, count, data); - }} - onBlur={(event) => {}} - /> - ) - } else if ( - (data.options !== undefined && data.options !== null && data.options.length > 0) || - (selectedActionParameters[count].options !== undefined && selectedActionParameters[count].options !== null && selectedActionParameters[count].options.length > 0)) { - const parsedoptions = data.options !== undefined && data.options !== null && data.options.length > 0 ? data.options : selectedActionParameters[count].options - - if (selectedActionParameters[count].value === "") { - // && selectedActionParameters[count].required) { - // Rofl, dirty workaround :) - const e = { - target: { - value: parsedoptions[0], - }, - }; - - changeActionParameter(e, count, data); - } - - var multi = false - if (selectedActionParameters[count].multiselect !== undefined && selectedActionParameters[count].multiselect !== null && selectedActionParameters[count].multiselect === true) { - multi = true - - selectedActionParameters[count].value = selectedActionParameters[count].value.split(",") - } - - datafield = ( - - ); - } else if (data.variant === "STATIC_VALUE") { - staticcolor = "#FF8544"; - } - - if (data.field_active === false) { - //console.log("Field not active: ", data?.name) - return null - } - - // Shows nested list of nodes > their JSON lists - const ActionlistWrapper = (props) => { - const handleMenuClose = () => { - setShowAutocomplete(false); - - if ( - !selectedActionParameters[count].value[ - selectedActionParameters[count].value.length - 1 - ] === "$" - ) { - setShowDropdown(false); - } - - setUpdate(Math.random()); - setMenuPosition(null); - }; - - const handleItemClick = (values) => { - if (values === undefined ||values === null ||values.length === 0) { - return; - } - - var toComplete = selectedActionParameters[count].value.trim() - .endsWith("$") - ? values[0].autocomplete - : "$" + values[0].autocomplete; - - toComplete = toComplete.toLowerCase().replaceAll(" ", "_"); - for (let [key,keyval] in Object.entries(values)) { - if (key == 0 || values[key].autocomplete.length === 0) { - continue; - } - - toComplete += values[key].autocomplete; - } - - - - // Handles the fields under OpenAPI body to be parsed. - if (data.name.startsWith("${") && data.name.endsWith("}")) { - const paramcheck = selectedAction.parameters.find( - (param) => param.name === "body" - ) - - if (paramcheck !== undefined) { - if (paramcheck["value_replace"] === undefined || paramcheck["value_replace"] === null) { - paramcheck["value_replace"] = [ - { - key: data.name, - value: toComplete, - }, - ] - } else { - const subparamindex = paramcheck["value_replace"] - .findIndex((param) => param.key === data.name); - - if (subparamindex === -1) { - paramcheck["value_replace"].push({ - key: data.name, - value: toComplete, - }) - - } else { - paramcheck["value_replace"][subparamindex]["value"] += - toComplete; - } - } - - selectedActionParameters[count]["value_replace"] = paramcheck; - - selectedAction.parameters = selectedActionParameters - //selectedAction.parameters[count]["value_replace"] = paramcheck; - setSelectedAction(selectedAction); - setUpdate(Math.random()); - - setShowDropdown(false); - setMenuPosition(null); - return; - } - } - - console.log("In nestedclick!!") - var newValue = selectedActionParameters[count].value + toComplete - changeActionParameter({target: {value: newValue}}, count, data, true) - //selectedActionParameters[count].value += toComplete; - //selectedAction.parameters[count].value = selectedActionParameters[count].value; - //setSelectedAction(selectedAction); - //setUpdate(Math.random()); - - setShowDropdown(false); - setMenuPosition(null); - }; - - const iconStyle = { - marginRight: 15, - }; - - return ( - { - 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 #FF8544"; - } else { - exec_text_field.style.border = ""; - } - } - - // Also doing arguments - if ( - workflow.triggers !== undefined && - workflow.triggers !== null && - workflow.triggers.length > 0 - ) { - for (let [key,keyval] in Object.entries(workflow.triggers)) { - const item = workflow.triggers[key]; - - if (cy !== undefined) { - var node = cy.getElementById(item.id); - if (node.length > 0) { - if (inside) { - node.addClass("shuffle-hover-highlight"); - } else { - node.removeClass("shuffle-hover-highlight"); - } - } - } - } - } - }; - - const handleActionHover = (inside, actionId) => { - if (cy !== undefined) { - var node = cy.getElementById(actionId); - if (node.length > 0) { - if (inside) { - node.addClass("shuffle-hover-highlight"); - } else { - node.removeClass("shuffle-hover-highlight"); - } - } - } - }; - - 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 (innerdata.type === "workflow_variable") { - // Try to parse the value if it's a string that could be JSON - if (typeof innerdata.value === "string") { - try { - const parsedValue = JSON.parse(innerdata.value) - if (typeof parsedValue === "object") { - parsedPaths = GetParsedPaths(parsedValue, ""); - } - } catch (e) { - // Not valid JSON, use the value directly - parsedPaths = GetParsedPaths(innerdata.value, ""); - } - } else if (typeof innerdata.value === "object") { - parsedPaths = GetParsedPaths(innerdata.value, ""); - } - } else 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(innerdata.example) - 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 baseIndent =
    - //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 ( - baseIndent - ) - })} - {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) + if (data.name.startsWith("${") && data.name.endsWith("}")) { + const paramcheck = selectedAction.parameters.find((param) => param.name === "body"); + + + if (paramcheck !== undefined && paramcheck !== null) { + if ( + paramcheck["value_replace"] !== undefined && + paramcheck["value_replace"] !== null + ) { + //console.log("IN THE VALUE REPLACE: ", paramcheck["value_replace"]) + const subparamindex = paramcheck["value_replace"].findIndex( + (param) => param.key === data.name + ); + if (subparamindex !== -1) { + data.value = + paramcheck["value_replace"][subparamindex]["value"]; + } } - - //selectedActionParameters[count].value += `{{ $${innerdata.name}.${newname} | size }}` - selectedActionParameters[count].value += `$${innerdata.name}.${newname}` - selectedAction.parameters[count].value = selectedActionParameters[count].value; - setSelectedAction(selectedAction); + } + } + + + var showCacheConfig = false + if (data.name === "key" && selectedAction.name.includes("cache") && selectedAction.app_name === "Shuffle Tools") { + // Show a key popout button + showCacheConfig = true + } + + var disabled = false; + var rows = "3"; + var openApiHelperText = "This is an OpenAPI specific field"; + + + if (selectedApp.generated && data.name === "headers") { + //console.log("HEADER: ", data) + //if (data.value.length === 0) { + //} + //setSelectedActionParameters(selectedActionParameters) + } + + var hideBodyButtonValue = ( +
    + + { + // Set localstorage + localStorage.setItem("hideBody", "true") + + setHideBody(false) + const updatedParameters = selectedActionParameters.map((param) => { + if (param.name === "body") { + return { + ...param, + id: "UNTOGGLED", + } + } + + if (param.description === openApiFieldDesc) { + // Check required fields here + if (selectedAction.required_body_fields !== undefined && selectedAction.required_body_fields !== null && selectedAction.required_body_fields.length > 0) { + // Look for the field name in the required_body_fields + if (selectedAction.required_body_fields.includes(param.name)) { + param.required = true + } else { + param.required = false + } + } + + return { ...param, field_active: true } + } + + return param + }) + + setSelectedActionParameters(updatedParameters) + }} + /> + { + localStorage.setItem("hideBody", "false") + setHideBody(true) + // Make sure the body field is shown + var foundvalue = false + const updatedParameters = selectedActionParameters.map((param) => { + if (param.name === "body") { + return { + ...param, + id: "TOGGLED", + } + } + + if (param.description === openApiFieldDesc) { + if (param.value.length > 0) { + foundvalue = true + } + + return { ...param, field_active: false } + } + + return param + }) + + if (foundvalue === true) { + toast.info("Please fill either Simple fields OR Advanced body, not both") + } + + setSelectedActionParameters(updatedParameters) + }} + /> + +
    + ) + + var showButtonField = false + if (selectedApp.generated === true && data.name === "body") { + const regex = /\${(\w+)}/g; + const found = placeholder.match(regex); + + var newhidebody = hideBody + showButtonField = true + if (found === undefined || found === null || found.length === 0) { + newhidebody = false + hideBodyButtonValue = null + + if (hideBody === false) { + setHideBody(true) + } + } + + if (newhidebody === true) { + //toast("BODYBUTTON TRUE") + } else { + + rows = "1"; + disabled = true; + openApiHelperText = "OpenAPI spec: fill the following fields."; + + var changed = false; + var tempArray = [] + for (let specKey in found) { + const tmpitem = found[specKey]; + var skip = false; + + for (let innerkey in selectedActionParameters) { + if (selectedActionParameters[innerkey].name === tmpitem) { + skip = true; + break; + } + } + + if (skip) { + //console.log("SKIPPING ", tmpitem) + continue; + } + + changed = true; + var isRequired = false + // Check if original field name is in the selectedAction.required_body_fields + if (selectedAction.required_body_fields !== undefined && selectedAction.required_body_fields !== null) { + for (let innerkey in selectedAction.required_body_fields) { + if (selectedAction.required_body_fields[innerkey] === tmpitem) { + isRequired = true + break + } + } + } + + tempArray.push({ + action_field: "", + configuration: false, + description: openApiFieldDesc, + example: "", + id: "", + multiline: false, + name: tmpitem, + options: null, + required: isRequired, + schema: { type: "string" }, + skip_multicheck: false, + tags: null, + value: "", + variant: "STATIC_VALUE", + field_active: true, + + autocompleted: false, + }); + } + + var required = selectedActionParameters.filter(item => item.required === true) + var notRequired = selectedActionParameters.filter(item => item.required === false) + + if (tempArray.length > 0) { + // Sort tempArray based on tempArray.required + tempArray.sort((a, b) => (a.required < b.required) ? 1 : -1) + // Add all items to the selectedActionParameters array + for (let innerkey in tempArray) { + tempArray[innerkey].id = "ADDED" + + if (tempArray[innerkey].required === true) { + required.push(tempArray[innerkey]) + } else { + notRequired.push(tempArray[innerkey]) + } + } + } + + if (changed) { + // Sort selectedActionParameters based on selectedActionParameters.required + // Find the "headers" and "queries" field names and put them on the first indexes anyway + var newArray = required.concat(notRequired) + + + setSelectedActionParameters(newArray) + } + + } + } + + const clickedFieldId = "rightside_field_" + count; + + var baseHelperText = "" + if (data !== undefined && data !== null && data.value !== undefined && data.value !== null && data.value.length > 0) { + baseHelperText = calculateHelpertext(data.value) + } + + var tmpitem = data.name.valueOf(); + if (data.name.startsWith("${") && data.name.endsWith("}")) { + tmpitem = tmpitem.slice(2, data.name.length - 1); + } + + if (tmpitem === "from_shuffle") { + tmpitem = "from" + } + + tmpitem = ( + tmpitem.charAt(0).toUpperCase() + tmpitem.substring(1) + ).replaceAll("_", " "); + + if (tmpitem === "Username basic") { + tmpitem = "Username" + } else if (tmpitem === "Password basic") { + tmpitem = "Password" + } + + // No longer multiline for new fields + //multiline = data.name.startsWith("${") && data.name.endsWith("}") ? true : multiline + + if (data.name === "body") { + //console.log("BODY: ", data) + if (hideBody === false) { + return hideBodyButtonValue + } + + rows = "4" + multiline = true + disabled = false + } + + const description = data.description === undefined ? "" : data?.description; + + const tooltipDescription = ( + + + + {tmpitem.charAt(0).toUpperCase() + tmpitem.slice(1)} + + { + setUiBox("closed") + }} + > + + + + + + + Required: {data.required === true || data.configuration === true ? "True" : "False"} + + + Description: {description} + + + Ex. : {data?.example?.length > 0 ? data.example : "No example available"} + + { + data?.configuration === true ? + ( + + Auth: Use "\$" instead of "$" + + ) : null + } + +
    { + e.preventDefault() + e.stopPropagation() + + localStorage.setItem("disabled_ui_box", "true") + setUiBox("closed") + }}> + + Don't show again + +
    +
    +
    + ); + + + var datafield = ( + + + + + { + event.preventDefault() + + // Get cursor position + // This makes it so we can put it in the right location? + setMenuPosition({ + top: event.pageY + 10, + left: event.pageX + 10, + }); + setShowDropdownNumber(count); + setShowDropdown(true); + setShowAutocomplete(true); + }} + /> + + + + ), + }} + multiline={multiline} + onClick={() => { + /* + setExpansionModalOpen(false); + */ + + if (setScrollConfig !== undefined && scrollConfig !== null && scrollConfig !== undefined && scrollConfig.selected !== clickedFieldId) { + + scrollConfig.selected = clickedFieldId + setScrollConfig(scrollConfig) + } + }} + rows={data.name.startsWith("${") && data.name.endsWith("}") ? 2 : rows} + color="primary" + // defaultValue={data.value} + value={ + data?.value + } + error={ + data?.error?.length > 0 ? true : false + } + helperText={data?.error?.length > 0 ? errorHelperText(data?.name, data?.value, data?.error) : returnHelperText(data.name, data.value)} + //options={{ + // theme: 'gruvbox-dark', + // keyMap: 'sublime', + // mode: 'python', + //}} + //height={multiline ? 50 : 150} + type={ + placeholder.includes("***") || + (data.configuration && + (data.name.toLowerCase().includes("api") || + data.name.toLowerCase().includes("key") || + data.name.toLowerCase().includes("pass"))) + ? "password" + : "text" + } + placeholder={placeholder} + onChange={(event) => { + handleParamChange(event, count, data) + }} + onFocus={(event) => { + // Get local storage key "disabled_ui_box" and check if it's true + const disabledUiBox = localStorage.getItem("disabled_ui_box") + if (disabledUiBox === "true") { + } else { + //setUiBox(event.target.id) + } + }} + onBlur={(event) => { + handleParamChange(event, count, data) + + baseHelperText = calculateHelpertext(event.target.value) + if (setLastSaved !== undefined) { + setLastSaved(false) + } + + // Check if we clicked the tooltip or not + const tooltipid = "rightside_field_tooltip" + count + const foundElement = document.getElementById(tooltipid) + if (foundElement !== null && foundElement !== undefined) { + console.log("FOUND: ", foundElement) + } else { + //console.log("TOOLTIP -> NOT FOUND") + //setUiBox("closed") + } + }} + /> + + ) + + // Finds headers from a string to be used for autocompletion + const findHeaders = (inputdata) => { + var splitdata = inputdata.split("\n") + + var foundnewline = false + var allValues = [] + for (let [key, keyval] in Object.entries(splitdata)) { + const line = splitdata[key] + if (line === "") { + foundnewline = true + continue + } + + var splitvalue = "" + if (line.includes(":")) { + splitvalue = ":" + } + + if (line.includes("=")) { + splitvalue = "=" + } + + if (splitvalue.length === 0) { + allValues.push({ + key: line, + value: "", + }) + continue + } + + var splitKeys = line.split(splitvalue) + if (splitKeys.length > 1) { + allValues.push({ + key: splitKeys[0].trim(), + value: splitKeys[1].trim(), + }) + } else { + console.log("No keys for ", line) + } + } + + // Just add one + if (foundnewline) { + allValues.push({ + key: "", + value: "", + }) + } + + return allValues + } + + if (data.name.toLowerCase() === "headers") { + //var tmpheaders = findHeaders(data.value) + var tmpheaders = findHeaders(selectedActionParameters[count].value) + const tmpdatafield = +
    + {tmpheaders.map((inputdata, index) => { + const oldkey = inputdata.key + const oldval = inputdata.value + + return ( + +
    + { + console.log("Change from oldkey to new: ", oldkey, e.target.value) + + // Find the right line to replace! + //const newval = selectedActionParameters[count].value.replace(oldval, e.target.value, 1) + const tmpsplit = selectedActionParameters[count].value.split("\n") + var valsplit = [] + var add_empty = false + for (let [key, keyval] in Object.entries(tmpsplit)) { + if (tmpsplit[key] === "") { + add_empty = true + continue + } + + valsplit.push(tmpsplit[key]) + } + + if (add_empty) { + valsplit.push("") + } + console.log("Split: ", valsplit) + + var newarr = [] + for (let [key, keyval] in Object.entries(valsplit)) { + var line = valsplit[key] + + if (key == index) { + if (oldkey === "") { + if (line.includes("=") || line.includes(":")) { + newarr.push(e.target.value + line) + } else { + newarr.push(e.target.value + ": " + line) + } + } else { + newarr.push(line.replace(oldkey, e.target.value, 1)) + } + + } else { + newarr.push(line) + } + } + + var newval = newarr.join("\n") + console.log("Fixed: ", newval) + + selectedActionParameters[count].value = newval + selectedAction.parameters[count].value = newval + setSelectedAction(selectedAction) + setSelectedActionParameters(selectedActionParameters) + }} + /> + { + console.log("Change from oldval to new: ", oldval, e.target.value) + + // Find the right line to replace! + //const newval = selectedActionParameters[count].value.replace(oldval, e.target.value, 1) + var tmpsplit = selectedActionParameters[count].value.split("\n") + var valsplit = [] + var add_empty = false + for (let [key, keyval] in Object.entries(tmpsplit)) { + if (tmpsplit[key] === "") { + add_empty = true + continue + } + + valsplit.push(tmpsplit[key]) + } + + if (add_empty) { + valsplit.push("") + } + console.log("Split: ", valsplit) + + var newarr = [] + for (let [key, keyval] in Object.entries(valsplit)) { + var line = valsplit[key] + + if (key == index) { + if (oldval === "") { + if (line.includes("=") || line.includes(":")) { + newarr.push(line + e.target.value) + } else { + newarr.push(line + ": " + e.target.value) + } + } else { + newarr.push(line.replace(oldval, e.target.value, 1)) + } + + } else { + newarr.push(line) + } + } + + var newval = newarr.join("\n") + console.log("Fixed: ", newval) + + selectedActionParameters[count].value = newval + selectedAction.parameters[count].value = newval + setSelectedAction(selectedAction) + setSelectedActionParameters(selectedActionParameters) + }} + /> +
    +
    + ) + })} + +
    + } + + //const regexp = new RegExp("\W+\.", "g") + //let match + //while ((match = regexp.exec(data.value)) !== null) { + // console.log(`Found ${match[0]} start=${match.index} end=${regexp.lastIndex}.`); + //} + + //const str = = data.value.search(submatch) + //console.log("FOUND? ", n) + //for (var key in keywords) { + // const keyword = keywords[key] + // if (data.value.includes(keyword)) { + // console.log("INCLUDED: ", keyword) + // } + //} + + if (files !== undefined && files !== null && data.name.toLowerCase() === "file_category") { + //selectedActionParameters[count].options.length > 0 + console.log("FileS: ", files) + if (files.namespaces !== undefined && files.namespaces !== null && files.namespaces.length > 0) { + data.options = files.namespaces + } + } + + //const keywords = ["len", "lower", "upper", "trim", "split", "length", "number", "parse", "join"] + if ( + selectedActionParameters[count].schema !== undefined && + selectedActionParameters[count].schema !== null && + selectedActionParameters[count].schema.type === "file" + ) { + datafield = ( + + + { + setMenuPosition({ + top: event.pageY + 10, + left: event.pageX + 10, + }); + setShowDropdownNumber(count); + setShowDropdown(true); + setShowAutocomplete(true); + }} + /> + + + ), + }} + helperText={returnHelperText(data.name, data.value)} + fullWidth + multiline={multiline} + rows={"3"} + color="primary" + defaultValue={data.value} + type={"text"} + placeholder={"The file ID to get"} + id={"rightside_field_" + count} + onChange={(event) => { + changeActionParameter(event, count, data); + }} + onBlur={(event) => { }} + /> + ) + } else if ( + (data.options !== undefined && data.options !== null && data.options.length > 0) || + (selectedActionParameters[count].options !== undefined && selectedActionParameters[count].options !== null && selectedActionParameters[count].options.length > 0)) { + const parsedoptions = data.options !== undefined && data.options !== null && data.options.length > 0 ? data.options : selectedActionParameters[count].options + + if (selectedActionParameters[count].value === "") { + // && selectedActionParameters[count].required) { + // Rofl, dirty workaround :) + const e = { + target: { + value: parsedoptions[0], + }, + }; + + changeActionParameter(e, count, data); + } + + var multi = false + if (selectedActionParameters[count].multiselect !== undefined && selectedActionParameters[count].multiselect !== null && selectedActionParameters[count].multiselect === true) { + multi = true + + selectedActionParameters[count].value = selectedActionParameters[count].value.split(",") + } + + datafield = ( + + ); + } else if (data.variant === "STATIC_VALUE") { + staticcolor = "#FF8544"; + } + + if (data.field_active === false) { + //console.log("Field not active: ", data?.name) + return null + } + + // Shows nested list of nodes > their JSON lists + const ActionlistWrapper = (props) => { + const handleMenuClose = () => { + setShowAutocomplete(false); + + if ( + !selectedActionParameters[count].value[ + selectedActionParameters[count].value.length - 1 + ] === "$" + ) { + setShowDropdown(false); + } + setUpdate(Math.random()); + setMenuPosition(null); + }; + + const handleItemClick = (values) => { + if (values === undefined || values === null || values.length === 0) { + return; + } + + var toComplete = selectedActionParameters[count].value.trim() + .endsWith("$") + ? values[0].autocomplete + : "$" + values[0].autocomplete; + + toComplete = toComplete.toLowerCase().replaceAll(" ", "_"); + for (let [key, keyval] in Object.entries(values)) { + if (key == 0 || values[key].autocomplete.length === 0) { + continue; + } + + toComplete += values[key].autocomplete; + } + + + + // Handles the fields under OpenAPI body to be parsed. + if (data.name.startsWith("${") && data.name.endsWith("}")) { + const paramcheck = selectedAction.parameters.find( + (param) => param.name === "body" + ) + + if (paramcheck !== undefined) { + if (paramcheck["value_replace"] === undefined || paramcheck["value_replace"] === null) { + paramcheck["value_replace"] = [ + { + key: data.name, + value: toComplete, + }, + ] + } else { + const subparamindex = paramcheck["value_replace"] + .findIndex((param) => param.key === data.name); + + if (subparamindex === -1) { + paramcheck["value_replace"].push({ + key: data.name, + value: toComplete, + }) + + } else { + paramcheck["value_replace"][subparamindex]["value"] += + toComplete; + } + } + + selectedActionParameters[count]["value_replace"] = paramcheck; + + selectedAction.parameters = selectedActionParameters + //selectedAction.parameters[count]["value_replace"] = paramcheck; + setSelectedAction(selectedAction); + setUpdate(Math.random()); + + setShowDropdown(false); + setMenuPosition(null); + return; + } + } + + console.log("In nestedclick!!") + var newValue = selectedActionParameters[count].value + toComplete + changeActionParameter({ target: { value: newValue } }, count, data, true) + //selectedActionParameters[count].value += toComplete; + //selectedAction.parameters[count].value = selectedActionParameters[count].value; + //setSelectedAction(selectedAction); + //setUpdate(Math.random()); + setShowDropdown(false); setMenuPosition(null); - }} /> : null} -
    -
    -
    - ); - })} - - - ) : ( - handleMouseover()} - onMouseOut={() => { - handleMouseOut(); - }} - onClick={() => { - handleItemClick([innerdata]); - }} - > - -
    - {icon} {innerdata.name} -
    -
    -
    - ); - })} - - ); - } - - const buttonTitle = `Authenticate API ${selectedApp.name.replaceAll("_", " ")}` - const hasAutocomplete = data?.autocompleted === true - if (data.variant === undefined || data.variant === null) { - data.variant = "STATIC_VALUE" - } + }; - const isFirstOptional = optionalFound === false && data.configuration === false && data.required === false ? true : false - if (optionalFound === false && data.configuration === false && data.required === false) { - optionalFound = true - } + const iconStyle = { + marginRight: 15, + }; - return ( -
    - {isFirstOptional ? : null} - {showButtonField === true ? hideBodyButtonValue : null} -
    - {data.configuration === true ? ( - - { - setAuthenticationModalOpen(true); - }} - /> - - ) : null} + return ( + { + 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" ? ( + + ) : ( + + ); - {hasAutocomplete === true ? - data.field_active === true ? - - - + 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 #FF8544"; + } else { + exec_text_field.style.border = ""; + } + } - : - - - - : - null} + // Also doing arguments + if ( + workflow.triggers !== undefined && + workflow.triggers !== null && + workflow.triggers.length > 0 + ) { + for (let [key, keyval] in Object.entries(workflow.triggers)) { + const item = workflow.triggers[key]; - {showCacheConfig === true ? - - - - - - : null} + if (cy !== undefined) { + var node = cy.getElementById(item.id); + if (node.length > 0) { + if (inside) { + node.addClass("shuffle-hover-highlight"); + } else { + node.removeClass("shuffle-hover-highlight"); + } + } + } + } + } + }; -
    - {tmpitem} {selectedActionParameters[count].required || selectedActionParameters[count].configuration ? "*" : ""} -
    + const handleActionHover = (inside, actionId) => { + if (cy !== undefined) { + var node = cy.getElementById(actionId); + if (node.length > 0) { + if (inside) { + node.addClass("shuffle-hover-highlight"); + } else { + node.removeClass("shuffle-hover-highlight"); + } + } + } + }; - + const handleMouseover = () => { + if (innerdata.type === "Execution Argument") { + handleExecArgumentHover(true); + } else if (innerdata.type === "action") { + handleActionHover(true, innerdata.id); + } + }; - { - const clickedField = document.getElementById(clickedFieldId) - if (clickedField !== null) { - clickedField.focus() - } - }} - onClick={(event) => { - // Set focus to the Textfield we just clicked - // This is to ensure focus is set correctly at all times with blur - const clickedField = document.getElementById(clickedFieldId) - if (clickedField !== null) { - clickedField.focus() - } + const handleMouseOut = () => { + if (innerdata.type === "Execution Argument") { + handleExecArgumentHover(false); + } else if (innerdata.type === "action") { + handleActionHover(false, innerdata.id); + } + }; - event.preventDefault() - setFieldCount(count) - setExpansionModalOpen(true) - setActiveDialog("codeeditor") - //setcodedata(data.value) - var parsedvalue = data.value - if (parsedvalue === undefined || parsedvalue === null) { - parsedvalue = "" - } + var parsedPaths = []; + if (innerdata.type === "workflow_variable") { + // Try to parse the value if it's a string that could be JSON + if (typeof innerdata.value === "string") { + try { + const parsedValue = JSON.parse(innerdata.value) + if (typeof parsedValue === "object") { + parsedPaths = GetParsedPaths(parsedValue, ""); + } + } catch (e) { + // Not valid JSON, use the value directly + parsedPaths = GetParsedPaths(innerdata.value, ""); + } + } else if (typeof innerdata.value === "object") { + parsedPaths = GetParsedPaths(innerdata.value, ""); + } + } else if (typeof innerdata.example === "object") { + parsedPaths = GetParsedPaths(innerdata.example, ""); + } - //console.log("Required fields: ", selectedActionParameters[count]) - navigate(`?action_id=${selectedAction.id}&field=${data.name}&action_name=${selectedAction.name}`) - setEditorData({ - "name": data.name, - "value": fixExample(parsedvalue), - "field_number": count, - "actionlist": actionlist, - "field_id": clickedFieldId, + 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 + } - "example": fixExample(selectedActionParameters[count].example), - }) + //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(innerdata.example) + 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 baseIndent =
    + //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 ( + baseIndent + ) + })} + {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 }}` + selectedActionParameters[count].value += `$${innerdata.name}.${newname}` + selectedAction.parameters[count].value = selectedActionParameters[count].value; + setSelectedAction(selectedAction); + setUpdate(Math.random()); + setShowDropdown(false); + setMenuPosition(null); + }} /> : null} +
    +
    +
    + ); + })} + + + ) : ( + handleMouseover()} + onMouseOut={() => { + handleMouseOut(); + }} + onClick={() => { + handleItemClick([innerdata]); + }} + > + +
    + {icon} {innerdata.name} +
    +
    +
    + ); + })} + + ); + } + + const buttonTitle = `Authenticate API ${selectedApp.name.replaceAll("_", " ")}` + const hasAutocomplete = data?.autocompleted === true + if (data.variant === undefined || data.variant === null) { + data.variant = "STATIC_VALUE" + } + + var isFirstOptional = optionalFound === false && data.configuration === false && data.required === false ? true : false + if (optionalFound === false && data.configuration === false && data.required === false) { + optionalFound = true + } + + if (isFirstOptional) { + // Check if any required fields are found + var foundRequired = false + for (var key in selectedActionParameters) { + if (selectedActionParameters[key]?.required === true) { + foundRequired = true + break + } + } + + if (!foundRequired) { + isFirstOptional = false + } + } + + return ( +
    + {isFirstOptional ? : null} + {showButtonField === true ? hideBodyButtonValue : null} +
    + {data.configuration === true ? ( + + { + setAuthenticationModalOpen(true); + }} + /> + + ) : null} + + {hasAutocomplete === true ? + data.field_active === true ? + + + + + : + + + + : + null} + + {showCacheConfig === true ? + + + + + + : null} + +
    + {tmpitem} {selectedActionParameters[count].required || selectedActionParameters[count].configuration ? "*" : ""} +
    + + + + { + const clickedField = document.getElementById(clickedFieldId) + if (clickedField !== null) { + clickedField.focus() + } + }} + onClick={(event) => { + // Set focus to the Textfield we just clicked + // This is to ensure focus is set correctly at all times with blur + const clickedField = document.getElementById(clickedFieldId) + if (clickedField !== null) { + clickedField.focus() + } + + event.preventDefault() + setFieldCount(count) + setExpansionModalOpen(true) + setActiveDialog("codeeditor") + //setcodedata(data.value) + var parsedvalue = data.value + if (parsedvalue === undefined || parsedvalue === null) { + parsedvalue = "" + } + + //console.log("Required fields: ", selectedActionParameters[count]) + navigate(`?action_id=${selectedAction.id}&field=${data.name}&action_name=${selectedAction.name}`) + setEditorData({ + "name": data.name, + "value": fixExample(parsedvalue), + "field_number": count, + "actionlist": actionlist, + "field_id": clickedFieldId, + + "example": fixExample(selectedActionParameters[count].example), + }) + + }} + /> + -
    - {datafield} - {/*shufflecode*/} - {showDropdown && - showDropdownNumber === count && - data.variant === "STATIC_VALUE" && - jsonList.length > 0 ? ( - - - Autocomplete - - { + setShowAutocomplete(false); - if (!selectedActionParameters[count].value[selectedActionParameters[count].value.length - 1] === ".") { - setShowDropdown(false); - } + if (!selectedActionParameters[count].value[selectedActionParameters[count].value.length - 1] === ".") { + setShowDropdown(false); + } - setUpdate(Math.random()); - }} - onClick={() => { - setShowAutocomplete(true) - }} - fullWidth - open={showAutocomplete} - style={{ - color: "white", - height: 35, - marginTop: 2, - borderRadius: theme.palette?.borderRadius, - }} - onChange={(e) => { - console.log("SELECT ONCHANGE DONE") + setUpdate(Math.random()); + }} + onClick={() => { + setShowAutocomplete(true) + }} + fullWidth + open={showAutocomplete} + style={{ + color: "white", + height: 35, + marginTop: 2, + borderRadius: theme.palette?.borderRadius, + }} + onChange={(e) => { + console.log("SELECT ONCHANGE DONE") - if (selectedActionParameters[count].value[selectedActionParameters[count].value.length - 1] === ".") { - e.target.value.autocomplete = e.target.value.autocomplete.slice(1,e.target.value.autocomplete.length); - } + if (selectedActionParameters[count].value[selectedActionParameters[count].value.length - 1] === ".") { + e.target.value.autocomplete = e.target.value.autocomplete.slice(1, e.target.value.autocomplete.length); + } - selectedActionParameters[count].value += e.target.value.autocomplete; - selectedAction.parameters[count].value = selectedActionParameters[count].value; - setSelectedAction(selectedAction); - setUpdate(Math.random()); + selectedActionParameters[count].value += e.target.value.autocomplete; + selectedAction.parameters[count].value = selectedActionParameters[count].value; + setSelectedAction(selectedAction); + setUpdate(Math.random()); - setShowDropdown(false); - }} - > - {jsonList.map((data) => { - const iconStyle = { - marginRight: 15, - }; + setShowDropdown(false); + }} + > + {jsonList.map((data) => { + const iconStyle = { + marginRight: 15, + }; - const icon = - data.type === "value" ? ( - - ) : data.type === "list" ? ( - - ) : ( - - ) + const icon = + data.type === "value" ? ( + + ) : data.type === "list" ? ( + + ) : ( + + ) - return ( - {}} - > - -
    - {icon} {data.name} -
    -
    -
    - ); - })} - -
    - ) : null} - {showDropdown && - showDropdownNumber === count && - data.variant === "STATIC_VALUE" && - jsonList.length === 0 ? ( - - ) : null} -
    - ); - })} -
    - : null - } - -
    -
    -
    - ); + return ( + { }} + > + +
    + {icon} {data.name} +
    +
    +
    + ); + })} + + + ) : null} + {showDropdown && + showDropdownNumber === count && + data.variant === "STATIC_VALUE" && + jsonList.length === 0 ? ( + + ) : null} +
    + ); + })} +
    + : null + } + +
    +
    +
    + ); }; export default ParsedAction; diff --git a/frontend/src/components/Priorities.jsx b/frontend/src/components/Priorities.jsx index ff359168..8965b05d 100644 --- a/frontend/src/components/Priorities.jsx +++ b/frontend/src/components/Priorities.jsx @@ -13,8 +13,11 @@ import { Card, Chip, Switch, - Skeleton, + Autocomplete, + TextField, + MenuItem, } from "@mui/material"; +import { makeStyles } from "@mui/styles"; import { Context } from "../context/ContextApi.jsx"; import { useNavigate, Link } from "react-router-dom"; @@ -22,8 +25,15 @@ import Priority from "../components/Priority.jsx"; import { constrainMatrix } from "reaviz"; //import { useAlert + +const useStyles = makeStyles({ + notchedOutline: { + borderColor: "#f85a3e !important", + }, +}); + const Priorities = memo((props) => { - const { globalUrl, userdata,clickedFromOrgTab, serverside, billingInfo, stripeKey, checkLogin, setAdminTab, setCurTab, notifications, setNotifications, } = props; + const { globalUrl, userdata,clickedFromOrgTab,selectedOrganization, handleEditOrg, serverside, billingInfo, stripeKey, checkLogin, setAdminTab, setCurTab, notifications, setNotifications, } = props; const [showDismissed, setShowDismissed] = React.useState(false); const [showRead, setShowRead] = React.useState(false); @@ -31,8 +41,22 @@ const Priorities = memo((props) => { const [selectedWorkflow, setSelectedWorkflow] = React.useState("NO HIGHLIGHT"); const [selectedExecutionId, setSelectedExecutionId] = React.useState("NO HIGHLIGHT"); const [highlightKMS, setHighlightKMS] = React.useState(false) + + const [workflows, setWorkflows] = React.useState([]) + const [openNotification, setOpenNotification] = React.useState(false); + const [workflow, setWorkflow] = React.useState({}) + const [notificationWorkflow, setNotificationWorkflow] = React.useState( + selectedOrganization.defaults === undefined + ? "" + : selectedOrganization.defaults.notification_workflow === undefined || + selectedOrganization.defaults.notification_workflow.length === 0 + ? "" + : selectedOrganization.defaults.notification_workflow + ); let navigate = useNavigate(); + const classes = useStyles(); + useEffect(() => { getFramework() @@ -60,6 +84,20 @@ const Priorities = memo((props) => { } }, []) + useEffect(() => { + if (selectedOrganization === undefined || selectedOrganization === null || selectedOrganization?.id === undefined || selectedOrganization?.id === null || selectedOrganization?.id.length === 0) { + return + } + + if(workflows?.length === 0) { + getAvailableWorkflows() + } + + if (notificationWorkflow !== selectedOrganization?.defaults?.notification_workflow) { + setNotificationWorkflow(selectedOrganization?.defaults?.notification_workflow) + } + }, [selectedOrganization]) + if (userdata === undefined || userdata === null) { return } @@ -220,11 +258,287 @@ const Priorities = memo((props) => { const imagesize = 22 const boxColor = "#86c142" + + const getAvailableWorkflows = () => { + fetch(globalUrl + "/api/v1/workflows", { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for workflows :O!"); + return; + } + return response.json(); + }) + .then((responseJson) => { + if (responseJson !== undefined) { + + // Add parent notification workflow if it's a child org + // selectedOrganization, + if (selectedOrganization.creator_org !== undefined && selectedOrganization.creator_org !== null && selectedOrganization.creator_org.length > 0) { + + // Add to start of the list + responseJson.unshift({ + "name": "Parent-Org's Notification Workflow", + "id": "parent", + }) + } + + setWorkflows(responseJson) + + if (selectedOrganization.defaults !== undefined && selectedOrganization.defaults.notification_workflow !== undefined) { + + const workflow = responseJson.find((workflow) => workflow.id === selectedOrganization.defaults.notification_workflow) + if (workflow !== undefined && workflow !== null) { + setWorkflow(workflow) + } + } + } + }) + .catch((error) => { + console.log("Error getting workflows: " + error); + }) + } + + const handleWorkflowSelectionUpdate = (e, isUserinput) => { + if (e.target.value === undefined || e.target.value === null || e.target.value.id === undefined) { + console.log("Returning as there's no id") + return null + } + setOpenNotification(false) + setWorkflow(e.target.value) + setNotificationWorkflow(e.target.value.id) + handleEditOrg( + selectedOrganization?.name, + selectedOrganization.description, + selectedOrganization.id, + selectedOrganization.image, + { + app_download_repo: selectedOrganization?.defaults?.app_download_repo, + app_download_branch: selectedOrganization?.defaults?.app_download_branch, + workflow_download_repo: selectedOrganization?.defaults?.workflow_download_repo, + workflow_download_branch: selectedOrganization?.defaults?.workflow_download_branch, + notification_workflow: e.target.value.id, + documentation_reference: selectedOrganization?.defaults?.documentation_reference, + workflow_upload_repo: selectedOrganization?.defaults?.workflow_upload_repo, + workflow_upload_branch: selectedOrganization?.defaults?.workflow_upload_branch, + workflow_upload_username: selectedOrganization?.defaults?.workflow_upload_username, + workflow_upload_token: selectedOrganization?.defaults?.workflow_upload_token, + newsletter: selectedOrganization?.defaults?.newsletter, + weekly_recommendations: selectedOrganization?.defaults?.weekly_recommendations, + }, + { + sso_entrypoint: selectedOrganization?.sso_config?.sso_entrypoint, + sso_certificate: selectedOrganization?.sso_config?.sso_certificate, + client_id: selectedOrganization?.sso_config?.client_id, + client_secret: selectedOrganization?.sso_config?.client_secret, + openid_authorization: selectedOrganization?.sso_config?.openid_authorization, + openid_token: selectedOrganization?.sso_config?.openid_token, + SSORequired: selectedOrganization?.sso_config?.SSORequired, + auto_provision: selectedOrganization?.sso_config?.auto_provision, + } + ) + } + return (
    - Notifications ({ + + Notification Workflow + + + The notification workflow triggers when an error occurs in one of your workflows. Each individual one will only start a workflow once every 2 minutes. You can point child org notifications into the parent org notification by choosing it in the list. + +
    + + {workflows !== undefined && workflows !== null && workflows.length > 0 ? + { + setOpenNotification(true); + }} + onClose={() => { + setOpenNotification(false); + }} + freeSolo + //autoSelect + value={workflows?.find(w => w.id === notificationWorkflow) || null} + classes={{ inputRoot: classes.inputRoot }} + ListboxProps={{ + style: { + backgroundColor: "#212121", + color: "white", + }, + }} + getOptionLabel={(option) => { + if ( + option === undefined || + option === null || + option.name === undefined || + option.name === null + ) { + return "No Workflow Selected"; + } + + const newname = ( + option.name.charAt(0).toUpperCase() + option.name.substring(1) + ).replaceAll("_", " "); + return newname; + }} + options={workflows} + fullWidth + style={{ + backgroundColor: "#212121", + borderRadius: theme.palette?.borderRadius, + height: 35, + marginBottom: 40, + }} + onChange={(event, newValue) => { + console.log("Found value: ", newValue) + + var parsedinput = { target: { value: newValue } } + + // For variables + if (typeof newValue === 'string' && newValue.startsWith("$")) { + parsedinput = { + target: { + value: { + "name": newValue, + "id": newValue, + "actions": [], + "triggers": [], + } + } + } + } + + handleWorkflowSelectionUpdate(parsedinput) + }} + renderOption={(props, data, state) => { + if (data.id === workflow.id) { + data = workflow; + } + + return ( + + {data.image !== undefined && data.image !== null && data.image.length > 0 ? + {data.name} + : null} + + Choose {data.name} + + + } placement="bottom"> + { + props.onMouseDown?.(null); + var parsedinput = { target: { value: data } } + handleWorkflowSelectionUpdate(parsedinput) + }} + > + {data.name} + + + ) + }} + renderInput={(params) => { + return ( + + ); + }} + /> + : + { + setNotificationWorkflow(e.target.value); + }} + /> + } + {/*
    + {orgSaveButton} +
    */} +
    + + Notifications ({ notifications?.filter((notification) => showRead === true || notification.read === false).length }) @@ -261,10 +575,12 @@ const Priorities = memo((props) => { ) : null}
    + {clickedFromOrgTab? null : } -

    Suggestions

    + +

    Suggestions

    Suggestions are tasks identified by Shuffle to help you discover ways to protect your and customers' company.
    These range from simple configurations in Shuffle to Usecases you may have missed.  { return ( { if (item.disabled) { - toast.error("This feature may not work in your environment yet, and is awaiting updates to the Shuffle python execution environment.", { autoClose: 10000 }) + toast.error("This feature may not work in your environment until you update your Shuffle Tools app.", { autoClose: 10000 }) } if (selectedAction.name !== "execute_python") { diff --git a/frontend/src/components/WorkflowTemplatePopup2.jsx b/frontend/src/components/WorkflowTemplatePopup2.jsx index 2e666637..3696e026 100644 --- a/frontend/src/components/WorkflowTemplatePopup2.jsx +++ b/frontend/src/components/WorkflowTemplatePopup2.jsx @@ -26,6 +26,7 @@ import { Close as CloseIcon, East as EastIcon, Interests as InterestsIcon, + OpenInNew as OpenInNewIcon, } from '@mui/icons-material'; import { @@ -35,7 +36,8 @@ import { grey, } from "../views/AngularWorkflow.jsx" -import WorkflowTemplatePopup2 from "./WorkflowTemplatePopup.jsx"; +//import WorkflowTemplatePopup2 from "./WorkflowTemplatePopup2.jsx"; +import WorkflowTemplatePopup2 from "./WorkflowTemplatePopup2.jsx"; import ConfigureWorkflow from "../components/ConfigureWorkflow.jsx"; import WorkflowValidationTimeline from "../components/WorkflowValidationTimeline.jsx"; import FixWorkflowValidationErrors from "../components/FixWorkflowValidationErrors.jsx"; @@ -47,9 +49,11 @@ const WorkflowTemplatePopup = (props) => { isModalOpenDefault, setIsClicked, inputWorkflowId, + inputWorkflow, } = props; - const [isActive, setIsActive] = useState(workflowBuilt === true); + const [isActive, setIsActive] = useState(workflowBuilt === true || (workflowBuilt !== undefined && workflowBuilt !== null && workflowBuilt?.length > 0) || (inputWorkflow !== undefined && inputWorkflow !== null && inputWorkflow.id !== undefined && inputWorkflow.id !== null && inputWorkflow.id !== "") ? true : false) + const [isHovered, setIsHovered] = useState(false); const [modalOpen, setModalOpen] = useState(isModalOpenDefault === true ? true : false) const [errorMessage, setErrorMessage] = useState(""); @@ -65,7 +69,7 @@ const WorkflowTemplatePopup = (props) => { const [showTryitOut, setShowTryitout] = React.useState(showTryit === true ? true : false) const [loadingWorkflow, setLoadingWorkflow] = React.useState(false) - const [workflow, setWorkflow] = useState({}); + const [workflow, setWorkflow] = useState(inputWorkflow !== undefined && inputWorkflow !== null && inputWorkflow.id !== undefined && inputWorkflow.id !== null && inputWorkflow.id !== "" ? inputWorkflow : {}) const [_, setUpdate] = useState(0) const fetchWorkflow = (id) => { @@ -455,7 +459,7 @@ const WorkflowTemplatePopup = (props) => { //console.log("Error in workflow template: ", responseJson.error); setRequestSent(false) - const defaultMessage = "Error: Failed to generate workflow the workflow - the Shuffle team has been notified. Contact support@shuffler.io if you want manual help building this usecase until the AI system is handled." + const defaultMessage = "Error: Failed to generate workflow the workflow - the Shuffle team has been notified. Contact support@shuffler.io if you want manual help building this usecase." if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason !== "") { setErrorMessage(defaultMessage + "\n\n" + responseJson.reason) } else { @@ -535,8 +539,8 @@ const WorkflowTemplatePopup = (props) => { style: { backgroundColor: "black", color: "white", - minWidth: isHomePage ? null : isMobile ? 300 : 850, - maxWidth: isHomePage ? null : isMobile ? 300 : 850, + minWidth: isHomePage ? null : isMobile ? 300 : 750, + maxWidth: isHomePage ? null : isMobile ? 300 : 750, paddingTop: isMobile ? null : 75, itemAlign: "center", }, @@ -564,7 +568,7 @@ const WorkflowTemplatePopup = (props) => { {title === undefined || title === null || title === "" ? null : - Selected Workflow: + Selected Usecase:
    { dstapp={dstapp} title={title} description={description} - visualOnly={true} + visualOnly={true} workflowBuilt={workflowBuilt} + inputWorkflow={workflow} shownColor={shownColor} /> @@ -585,7 +590,7 @@ const WorkflowTemplatePopup = (props) => { } -
    +
    {/* Fix the timeline when errors are fixed.. how? */} {
    {workflowLoading === true ? -
    - Generating the Workflow... +
    + Generating Workflows...
    :
    - {usecaseDetails === undefined ? null : - - {usecaseDetails?.description} + {usecaseDetails === undefined || usecaseDetails === null || workflow.id !== undefined ? null : + + {usecaseDetails?.description} } - - {errorMessage !== "" ? errorMessage : ""} - + {errorMessage !== "" ? + + {errorMessage !== "" ? errorMessage : ""} + + : null} {showLoginButton ? { variant="outlined" style={{ textTransform: "none", + marginTop: 15, }} onClick={() => { //setWorkflowLoading(true) @@ -730,11 +738,11 @@ const WorkflowTemplatePopup = (props) => { const parsedDescription = description !== undefined && description !== null ? description.replaceAll("_", " ") : "" - const boxHeight = 104 + const boxHeight = visualOnly ? 75 : 104 const highlightColor = shownColor !== undefined && shownColor !== null && shownColor !== "" ? shownColor : "#f85a3e" var hasInterest = false - if (userdata.interests !== undefined && userdata.interests !== null && userdata.interests.length > 0) { + if (userdata?.interests !== undefined && userdata?.interests !== null && userdata?.interests?.length > 0) { const comparisonTitle = title === undefined || title === null ? "" : title.trim().toLowerCase().replaceAll(" ", "_") for (var interestkey in userdata.interests) { if (userdata.interests[interestkey].name === undefined || userdata.interests[interestkey].name === null || userdata.interests[interestkey].name === "") { @@ -742,12 +750,12 @@ const WorkflowTemplatePopup = (props) => { } if (modalOpen) { - console.log("COMPARE: ", userdata.interests[interestkey].name.trim().toLowerCase().replaceAll(" ", "_"), comparisonTitle) + //console.log("COMPARE: ", userdata.interests[interestkey].name.trim().toLowerCase().replaceAll(" ", "_"), comparisonTitle) } if (userdata.interests[interestkey].name.trim().toLowerCase().replaceAll(" ", "_") === comparisonTitle) { if (modalOpen) { - console.log("FOUND: ", comparisonTitle) + //console.log("FOUND: ", comparisonTitle) } hasInterest = true @@ -791,7 +799,16 @@ const WorkflowTemplatePopup = (props) => { }} onClick={() => { if (visualOnly === true) { - console.log("Not showing more than visuals.") + console.log("Not showing more than visuals. Workflow built: ", workflowBuilt, workflow) + + if (workflowBuilt !== undefined && workflowBuilt !== null && workflowBuilt?.length > 0) { + window.open("/workflows/" + workflowBuilt, "_blank") + } else if (workflow.id !== undefined && workflow.id !== null && workflow.id !== "") { + window.open("/workflows/" + workflow.id, "_blank") + } else { + toast("Click 'Try this usecase' to generate workflows for this usecase.") + } + return } @@ -822,7 +839,7 @@ const WorkflowTemplatePopup = (props) => { : null}
    -
    +
    {img1 !== undefined && img1 !== "" && srcapp !== undefined && srcapp !== "" ? @@ -849,7 +866,7 @@ const WorkflowTemplatePopup = (props) => { }
    -
    +
    {parsedTitle} @@ -858,13 +875,19 @@ const WorkflowTemplatePopup = (props) => {
    + {isActive === true && errorMessage === "" ? - - - + visualOnly === true ? + + + + : + + + : ""} - {!isActive && hasInterest === true ? + {!isActive && hasInterest === true && !visualOnly ? @@ -872,7 +895,7 @@ const WorkflowTemplatePopup = (props) => {
    - {showTryitOut && !isActive ? + {showTryitOut && !isActive && !visualOnly ?
    " + // Inject HTML at a fixed location? + //const newHtml = "

    Do you want to add this suggestion?

    " - // Find mouse cursor position on screen - console.log("Suggestion html to be added at location: ", event) - /* - const position = { - "top": cy.pan().y, - "left": cy.pan().x, - } - */ + // Find mouse cursor position on screen + console.log("Suggestion html to be added at location: ", event) + /* + const position = { + "top": cy.pan().y, + "left": cy.pan().x, + } + */ - const position = event.target.renderedPosition(); - const container = cy.container(); - const offset = { - left: container.offsetLeft, - top: container.offsetTop - }; - - // Calculate the actual screen position for the box - const screenPosition = { - left: position.x + offset.left - 150, - top: position.y + offset.top, - }; - - // Log the position to the console - console.log('Node screen position:', screenPosition); + const position = event.target.renderedPosition(); + const container = cy.container(); + const offset = { + left: container.offsetLeft, + top: container.offsetTop + }; - const newbox = { - "position": screenPosition, - "node_position": event.target.position(), - "open": true, - "attachedTo": data.attachedTo, - } + // Calculate the actual screen position for the box + const screenPosition = { + left: position.x + offset.left - 150, + top: position.y + offset.top, + }; - console.log("Rendered position: ", newbox.node_position) + // Log the position to the console + console.log('Node screen position:', screenPosition); - setSuggestionBox(newbox) + const newbox = { + "position": screenPosition, + "node_position": event.target.position(), + "open": true, + "attachedTo": data.attachedTo, + } + + console.log("Rendered position: ", newbox.node_position) + + setSuggestionBox(newbox) + + // Unselect + event.target.unselect(); - // Unselect - event.target.unselect(); - } else if (data.buttonType === "delete") { const parentNode = cy.getElementById(data.attachedTo); if (parentNode !== null && parentNode !== undefined) { @@ -5281,9 +5267,9 @@ const releaseToConnectLabel = "Release to Connect" return } else if (data.buttonType === "set_startnode" && data.type !== "TRIGGER") { - //console.log("STARTNODE") - //event.preventDefault() - //event.stopPropagation() + //console.log("STARTNODE") + //event.preventDefault() + //event.stopPropagation() const parentNode = cy.getElementById(data.attachedTo); if (parentNode !== null && parentNode !== undefined) { @@ -5375,46 +5361,46 @@ const releaseToConnectLabel = "Release to Connect" const destinationbranches = workflow.branches.filter((foundbranch) => foundbranch.destination_id === parentNode.data("id")) - - for (var sourceBranchesKey in sourcebranches) { - var newbranch = JSON.parse(JSON.stringify(sourcebranches[sourceBranchesKey])); - newbranch.id = uuidv4() - newbranch.source_id = newNodeData.id + for (var sourceBranchesKey in sourcebranches) { + var newbranch = JSON.parse(JSON.stringify(sourcebranches[sourceBranchesKey])); - newbranch._id = newbranch.id - newbranch.source = newbranch.source_id - newbranch.target = newbranch.destination_id - cy.add({ - group: "edges", - data: newbranch, - }) + newbranch.id = uuidv4() + newbranch.source_id = newNodeData.id + + newbranch._id = newbranch.id + newbranch.source = newbranch.source_id + newbranch.target = newbranch.destination_id + cy.add({ + group: "edges", + data: newbranch, + }) } - for (var destinationBranchesKey in destinationbranches) { - var newbranch = JSON.parse(JSON.stringify(destinationbranches[destinationBranchesKey])) + for (var destinationBranchesKey in destinationbranches) { + var newbranch = JSON.parse(JSON.stringify(destinationbranches[destinationBranchesKey])) - const sourcenode = cy.getElementById(newbranch.source_id) - if (sourcenode !== null && sourcenode !== undefined) { - const sourcedata = sourcenode.data() + const sourcenode = cy.getElementById(newbranch.source_id) + if (sourcenode !== null && sourcenode !== undefined) { + const sourcedata = sourcenode.data() - if (sourcedata.trigger_type !== "SUBFLOW" && sourcedata.trigger_type !== "USERINPUT") { - continue - } + if (sourcedata.trigger_type !== "SUBFLOW" && sourcedata.trigger_type !== "USERINPUT") { + continue + } - } + } - newbranch.id = uuidv4() - newbranch.destination_id = newNodeData.id + newbranch.id = uuidv4() + newbranch.destination_id = newNodeData.id - newbranch._id = newbranch.id - newbranch.source = newbranch.source_id - newbranch.target = newbranch.destination_id - cy.add({ - group: "edges", - data: newbranch, - }) + newbranch._id = newbranch.id + newbranch.source = newbranch.source_id + newbranch.target = newbranch.destination_id + cy.add({ + group: "edges", + data: newbranch, + }) } //event.target.unselect(); @@ -5424,48 +5410,48 @@ const releaseToConnectLabel = "Release to Connect" return; } else if (data.isDescriptor) { - // Find parent + // Find parent event.target.unselect(); - if (data.attachedTo !== undefined && data.attachedTo !== null && data.attachedTo.length > 0) { - const parentNode = cy.getElementById(data.attachedTo) - if (parentNode !== null && parentNode !== undefined) { - setTimeout(() => { - parentNode.select() - }, 100) - } - } + if (data.attachedTo !== undefined && data.attachedTo !== null && data.attachedTo.length > 0) { + const parentNode = cy.getElementById(data.attachedTo) + if (parentNode !== null && parentNode !== undefined) { + setTimeout(() => { + parentNode.select() + }, 100) + } + } //console.log("Can't select descriptor"); - if (data.isTrigger) { - console.log("But maybe we can select trigger descriptor? Maybe open execution tab?") - setExecutionModalOpen(true) - } + if (data.isTrigger) { + console.log("But maybe we can select trigger descriptor? Maybe open execution tab?") + setExecutionModalOpen(true) + } return; } - if (data.type === undefined) { - console.log("No type, automatically setting to action"); - data.type = "ACTION" - } + if (data.type === undefined) { + console.log("No type, automatically setting to action"); + data.type = "ACTION" + } if (data.type === "ACTION") { setSelectedComment({}) - // FIXME: is this what is mapping it an actual action in the workflow? wtf? + // FIXME: is this what is mapping it an actual action in the workflow? wtf? var curactionIndex = workflow.actions.findIndex((a) => a.id === data.id) var curaction = undefined - if (curactionIndex >= 0) { - curaction = workflow.actions[curactionIndex] - } + if (curactionIndex >= 0) { + curaction = workflow.actions[curactionIndex] + } if (!curaction || curaction === undefined) { if (data.id !== undefined && data.app_name !== undefined) { workflow.actions.push(data) setWorkflow(workflow) - // FIXME: Is this necessary? + // FIXME: Is this necessary? //curaction = JSON.parse(JSON.stringify(data)) } else { if (workflow.public !== true) { @@ -5477,15 +5463,15 @@ const releaseToConnectLabel = "Release to Connect" } } - // FIXME: This change may have caused... something - // FIXME: Somehow there is a referencing problem between the action in - // cytoscape and the one in the "workflow.actions" state + // FIXME: This change may have caused... something + // FIXME: Somehow there is a referencing problem between the action in + // cytoscape and the one in the "workflow.actions" state curaction = data - //workflow.actions[curactionIndex] = curaction - - //const data = event.target.data() - //event.target.data(curaction) - //event.target.data(curaction) + //workflow.actions[curactionIndex] = curaction + + //const data = event.target.data() + //event.target.data(curaction) + //event.target.data(curaction) var newapps = apps if (apps === null || apps === undefined || apps.length === 0) { @@ -5516,65 +5502,65 @@ const releaseToConnectLabel = "Release to Connect" (a.loop_versions !== null && a.loop_versions.includes(curaction.app_version))) ) - } + } if (curaction.template === true && curaction.name !== undefined) { //newapps. const parsedname = curaction.name.replaceAll(" ", "_").toLowerCase() console.log("FIND AN ACTION AMONG THE APPS THAT MATCHES NAME: ", parsedname) - curaction.matching_actions = [] - for (var newAppskey in newapps) { - for (let actionsSubkey in newapps[newAppskey].actions) { - const tmpaction = newapps[newAppskey].actions[actionsSubkey] - if (tmpaction.name.replaceAll(" ", "_").toLowerCase() === parsedname) { - console.log("MATCH!: ", newapps[newAppskey]) - curaction.matching_actions.push({ - "app_name": newapps[newAppskey].name, - "app_version": newapps[newAppskey].app_version, - "app_id": newapps[newAppskey].id, - "action": tmpaction, - "large_image": newapps[newAppskey].large_image, - "app_index": newAppskey, - "action_index": actionsSubkey, - }) - } - } - } - } + curaction.matching_actions = [] + for (var newAppskey in newapps) { + for (let actionsSubkey in newapps[newAppskey].actions) { + const tmpaction = newapps[newAppskey].actions[actionsSubkey] + if (tmpaction.name.replaceAll(" ", "_").toLowerCase() === parsedname) { + console.log("MATCH!: ", newapps[newAppskey]) + curaction.matching_actions.push({ + "app_name": newapps[newAppskey].name, + "app_version": newapps[newAppskey].app_version, + "app_id": newapps[newAppskey].id, + "action": tmpaction, + "large_image": newapps[newAppskey].large_image, + "app_index": newAppskey, + "action_index": actionsSubkey, + }) + } + } + } + } - if (!curapp || curapp === undefined) { - // Check local storage has it - const foundapps = localStorage.getItem("apps") - if (foundapps !== null && foundapps !== undefined) { - try { - const parsedapps = JSON.parse(foundapps) - if (parsedapps !== null && parsedapps !== undefined && parsedapps.length > 0) { - for (let appkey in parsedapps) { - if (parsedapps[appkey].name === curaction.app_name) { - curapp = parsedapps[appkey] - break - } - } - } - } catch (e) { - console.log("Problem with parsing apps from local storage", e) - } + if (!curapp || curapp === undefined) { + // Check local storage has it + const foundapps = localStorage.getItem("apps") + if (foundapps !== null && foundapps !== undefined) { + try { + const parsedapps = JSON.parse(foundapps) + if (parsedapps !== null && parsedapps !== undefined && parsedapps.length > 0) { + for (let appkey in parsedapps) { + if (parsedapps[appkey].name === curaction.app_name) { + curapp = parsedapps[appkey] + break + } + } + } + } catch (e) { + console.log("Problem with parsing apps from local storage", e) + } - } else { - console.log("No apps found in local storage") - } - } + } else { + console.log("No apps found in local storage") + } + } - /* - if (curapp && curapp.app_id !== undefined && curapp.app_id !== null && curapp.app_id.length > 0 &&curapp.actions.length <= 1) { - toast(`Side-loading app ${curapp.name} to get actions.`) - } - */ + /* + if (curapp && curapp.app_id !== undefined && curapp.app_id !== null && curapp.app_id.length > 0 &&curapp.actions.length <= 1) { + toast(`Side-loading app ${curapp.name} to get actions.`) + } + */ - if (curapp !== undefined && curapp !== null && curapp.id !== undefined && curapp.id !== null && curapp.id.length > 0) { - loadAppConfig(curapp.id, true) - } + if (curapp !== undefined && curapp !== null && curapp.id !== undefined && curapp.id !== null && curapp.id.length > 0) { + loadAppConfig(curapp.id, true) + } if (!curapp || curapp === undefined) { const tmpapp = { @@ -5591,31 +5577,31 @@ const releaseToConnectLabel = "Release to Connect" curaction.app_id = curapp.id - if (curapp.authentication === undefined || curapp.authentication === null) { - setAuthenticationType({ - type: "", - }) + if (curapp.authentication === undefined || curapp.authentication === null) { + setAuthenticationType({ + type: "", + }) - curapp.authentication = { - type: "", - required: false, - } - } else { - setAuthenticationType( - curapp.authentication.type === "oauth2-app" || (curapp.authentication.type === "oauth2" && curapp.authentication.redirect_uri !== undefined && curapp.authentication.redirect_uri !== null) ? { - type: curapp.authentication.type, - redirect_uri: curapp.authentication.redirect_uri, - refresh_uri: curapp.authentication.refresh_uri, - token_uri: curapp.authentication.token_uri, - scope: curapp.authentication.scope, - client_id: curapp.authentication.client_id, - client_secret: curapp.authentication.client_secret, - grant_type: curapp.authentication.grant_type, - } : { - type: "", - } - ) - } + curapp.authentication = { + type: "", + required: false, + } + } else { + setAuthenticationType( + curapp.authentication.type === "oauth2-app" || (curapp.authentication.type === "oauth2" && curapp.authentication.redirect_uri !== undefined && curapp.authentication.redirect_uri !== null) ? { + type: curapp.authentication.type, + redirect_uri: curapp.authentication.redirect_uri, + refresh_uri: curapp.authentication.refresh_uri, + token_uri: curapp.authentication.token_uri, + scope: curapp.authentication.scope, + client_id: curapp.authentication.client_id, + client_secret: curapp.authentication.client_secret, + grant_type: curapp.authentication.grant_type, + } : { + type: "", + } + ) + } const requiresAuth = curapp.authentication.required; //&& ((curapp.authentication.parameters !== undefined && curapp.authentication.parameters !== null) || (curapp.authentication.type === "oauth2" && curapp.authentication.redirect_uri !== undefined && curapp.authentication.redirect_uri !== null)) setRequiresAuthentication(requiresAuth); @@ -5634,57 +5620,57 @@ const releaseToConnectLabel = "Release to Connect" const tmpAuth = JSON.parse(JSON.stringify(newAppAuth)); - const curappName = curapp.name.toLowerCase() - for (let tmpAuthKey in tmpAuth) { - var item = tmpAuth[tmpAuthKey]; + const curappName = curapp.name.toLowerCase() + for (let tmpAuthKey in tmpAuth) { + var item = tmpAuth[tmpAuthKey]; - const newfields = {}; - if (item.app.name.toLowerCase() !== curappName) { - continue - } + const newfields = {}; + if (item.app.name.toLowerCase() !== curappName) { + continue + } - // Makes list into key:value object - for (let fieldkey in item.fields) { - if (item.fields[fieldkey] === undefined) { - console.log("Problem with filterkey in Node select", fieldkey) - continue - } + // Makes list into key:value object + for (let fieldkey in item.fields) { + if (item.fields[fieldkey] === undefined) { + console.log("Problem with filterkey in Node select", fieldkey) + continue + } - const filterkey = item.fields[fieldkey]["key"] - if (filterkey === null || filterkey === undefined) { - console.log("Problem with filterkey 2. Null or undefined 3") - continue - } + const filterkey = item.fields[fieldkey]["key"] + if (filterkey === null || filterkey === undefined) { + console.log("Problem with filterkey 2. Null or undefined 3") + continue + } - newfields[filterkey] = item.fields[fieldkey]["value"]; - } + newfields[filterkey] = item.fields[fieldkey]["value"]; + } - item.fields = newfields; - if (item.app.name.toLowerCase() === curappName) { - authenticationOptions.push(item); - if (item.id === findAuthId) { - curaction.selectedAuthentication = item; - } - } - } + item.fields = newfields; + if (item.app.name.toLowerCase() === curappName) { + authenticationOptions.push(item); + if (item.id === findAuthId) { + curaction.selectedAuthentication = item; + } + } + } - // Find with authenticationOption (authenticationOptions) has the highest .edited time. In this index, set the "last_modified" to true - - var latesttime = 0 - var latestindex = -1 + // Find with authenticationOption (authenticationOptions) has the highest .edited time. In this index, set the "last_modified" to true - for (var i = 0; i < authenticationOptions.length; i++) { - const authopt = authenticationOptions[i] + var latesttime = 0 + var latestindex = -1 - if (authopt.edited > latesttime) { - latesttime = authopt.edited - latestindex = i - } - } + for (var i = 0; i < authenticationOptions.length; i++) { + const authopt = authenticationOptions[i] - if (latestindex !== -1) { - authenticationOptions[latestindex].last_modified = true - } + if (authopt.edited > latesttime) { + latesttime = authopt.edited + latestindex = i + } + } + + if (latestindex !== -1) { + authenticationOptions[latestindex].last_modified = true + } curaction.authentication = authenticationOptions if ( @@ -5701,77 +5687,77 @@ const releaseToConnectLabel = "Release to Connect" curaction.selectedAuthentication = {}; } - if ( - curaction.parameters !== undefined && - curaction.parameters !== null && - curaction.parameters.length > 0 - ) { - for (var curActionParamKey in curaction.parameters) { - if ( - curaction.parameters[curActionParamKey].options !== undefined && - curaction.parameters[curActionParamKey].options !== null && - curaction.parameters[curActionParamKey].options.length > 0 && - curaction.parameters[curActionParamKey].value === "" - ) { - curaction.parameters[curActionParamKey].value = curaction.parameters[curActionParamKey].options[0]; - } - } + if ( + curaction.parameters !== undefined && + curaction.parameters !== null && + curaction.parameters.length > 0 + ) { + for (var curActionParamKey in curaction.parameters) { + if ( + curaction.parameters[curActionParamKey].options !== undefined && + curaction.parameters[curActionParamKey].options !== null && + curaction.parameters[curActionParamKey].options.length > 0 && + curaction.parameters[curActionParamKey].value === "" + ) { + curaction.parameters[curActionParamKey].value = curaction.parameters[curActionParamKey].options[0]; + } + } - } else { - console.log("Should check APP if it has the same params as ACTION") - for (let actionKey in curapp.actions) { - const tmpaction = curapp.actions[actionKey] - if (tmpaction.name === curaction.name) { - console.log("Found action - needs change?", tmpaction) - if (tmpaction.parameters !== undefined && tmpaction.parameters !== null && tmpaction.parameters.length > 0) { - curaction.parameters = JSON.parse(JSON.stringify(tmpaction.parameters)) - } - break - } - } + } else { + console.log("Should check APP if it has the same params as ACTION") + for (let actionKey in curapp.actions) { + const tmpaction = curapp.actions[actionKey] + if (tmpaction.name === curaction.name) { + console.log("Found action - needs change?", tmpaction) + if (tmpaction.parameters !== undefined && tmpaction.parameters !== null && tmpaction.parameters.length > 0) { + curaction.parameters = JSON.parse(JSON.stringify(tmpaction.parameters)) + } + break + } + } - } + } - // Fix authentication fields that may be missing in the UI - if (curapp.authentication.required && !curapp?.authentication?.type?.includes("oauth")) { - if (curapp.authentication.parameters !== undefined && curapp.authentication.parameters !== null) { - var actionChanged = false - for (let paramKey in curapp.authentication.parameters) { - var param = curapp.authentication.parameters[paramKey] + // Fix authentication fields that may be missing in the UI + if (curapp.authentication.required && !curapp?.authentication?.type?.includes("oauth")) { + if (curapp.authentication.parameters !== undefined && curapp.authentication.parameters !== null) { + var actionChanged = false + for (let paramKey in curapp.authentication.parameters) { + var param = curapp.authentication.parameters[paramKey] - if (curaction.parameters === undefined || curaction.parameters === null) { - curaction.parameters = [] - } + if (curaction.parameters === undefined || curaction.parameters === null) { + curaction.parameters = [] + } - var found = false - for (let actionParamKey in curaction.parameters) { - if (curaction.parameters[actionParamKey].name === param.name) { - found = true - break - } - } + var found = false + for (let actionParamKey in curaction.parameters) { + if (curaction.parameters[actionParamKey].name === param.name) { + found = true + break + } + } - if (!found) { - param.configuration = true - curaction.parameters.push(param) - - actionChanged = true - } - } + if (!found) { + param.configuration = true + curaction.parameters.push(param) - if (actionChanged && workflow.actions !== undefined && workflow.actions !== null) { - // Find it in the workflow and set it - for (let wfActionKey in workflow.actions) { - if (workflow.actions[wfActionKey].id === curaction.id) { - workflow.actions[wfActionKey] = curaction - } - } + actionChanged = true + } + } - setWorkflow(workflow) - - } - } - } + if (actionChanged && workflow.actions !== undefined && workflow.actions !== null) { + // Find it in the workflow and set it + for (let wfActionKey in workflow.actions) { + if (workflow.actions[wfActionKey].id === curaction.id) { + workflow.actions[wfActionKey] = curaction + } + } + + setWorkflow(workflow) + + } + } + } setSelectedApp(curapp) setSelectedAction(curaction) @@ -5814,13 +5800,12 @@ const releaseToConnectLabel = "Release to Connect" if (data.app_name === "Shuffle Workflow" || data.app_name === "User Input") { - // Check if public workflow - if (workflow.public === true) { - setWorkflows([workflow]) - } else { - getAvailableWorkflows(trigger_index); - getSettings(); - } + // Check if public workflow + if (workflow.public === true) { + setWorkflows([workflow]) + } else { + getAvailableWorkflows(trigger_index); + } } else if (data.app_name === "Webhook") { if (workflow.triggers[trigger_index].parameters !== undefined && workflow.triggers[trigger_index].parameters !== null && workflow.triggers[trigger_index].parameters.length > 0) { workflow.triggers[trigger_index].parameters[0] = { @@ -5828,120 +5813,120 @@ const releaseToConnectLabel = "Release to Connect" value: referenceUrl + "webhook_" + workflow.triggers[trigger_index].id, }; - if (workflow.triggers[trigger_index].parameters.length < 5) { - console.log("Adding to webhook params!") - workflow.triggers[trigger_index].parameters.push({ - name: "await_response", - value: "v1," - }) - } + if (workflow.triggers[trigger_index].parameters.length < 5) { + console.log("Adding to webhook params!") + workflow.triggers[trigger_index].parameters.push({ + name: "await_response", + value: "v1," + }) + } } } else if (data.app_name === "Pipeline") { - // Check if environment is set - if (data.environment === undefined || data.environment === null || data.environment === "" || data.environment.toLowerCase() === "cloud") { - for (var envKey in environments) { - if (environments[envKey].archived === true) { - continue - } + // Check if environment is set + if (data.environment === undefined || data.environment === null || data.environment === "" || data.environment.toLowerCase() === "cloud") { + for (var envKey in environments) { + if (environments[envKey].archived === true) { + continue + } - if (environments[envKey].Name.toLowerCase() === "cloud") { - continue - } + if (environments[envKey].Name.toLowerCase() === "cloud") { + continue + } - workflow.triggers[trigger_index].environment = environments[envKey].Name - data.environment = environments[envKey].Name - //setSelectedTrigger(data) - break - } - } - } + workflow.triggers[trigger_index].environment = environments[envKey].Name + data.environment = environments[envKey].Name + //setSelectedTrigger(data) + break + } + } + } setTimeout(() => { - if (trigger_index !== -1) { - const trigger = workflow.triggers[trigger_index] - if (trigger !== undefined && trigger !== null) { + if (trigger_index !== -1) { + const trigger = workflow.triggers[trigger_index] + if (trigger !== undefined && trigger !== null) { - // Autofixer - if (trigger.trigger_type === "USERINPUT") { - const relevantparams = [ - "alertinfo", - "options", - "type", - "email", - "sms", - "subflow", - ] - var foundparams = 0 - for (var paramkey in trigger.parameters) { - if (relevantparams.includes(trigger.parameters[paramkey].name)) { - foundparams++ - } - } + // Autofixer + if (trigger.trigger_type === "USERINPUT") { + const relevantparams = [ + "alertinfo", + "options", + "type", + "email", + "sms", + "subflow", + ] + var foundparams = 0 + for (var paramkey in trigger.parameters) { + if (relevantparams.includes(trigger.parameters[paramkey].name)) { + foundparams++ + } + } - if (foundparams < 6) { - trigger.parameters = [{ - name: "alertinfo", - value: "Do you want to continue the workflow? Start parameters: $exec", - },{ - name: "options", - value: "boolean", - }, - { - name: "type", - value: "subflow", - }, - { - name: "email", - value: "test@test.com", - }, - { - name: "sms", - value: "0000000", - }, - { - name: "subflow", - value: "", - }] + if (foundparams < 6) { + trigger.parameters = [{ + name: "alertinfo", + value: "Do you want to continue the workflow? Start parameters: $exec", + }, { + name: "options", + value: "boolean", + }, + { + name: "type", + value: "subflow", + }, + { + name: "email", + value: "test@test.com", + }, + { + name: "sms", + value: "0000000", + }, + { + name: "subflow", + value: "", + }] - workflow.triggers[trigger_index].parameters = trigger.parameters - } - } - } - } + workflow.triggers[trigger_index].parameters = trigger.parameters + } + } + } + } - if (allTriggers !== undefined && allTriggers !== null) { + if (allTriggers !== undefined && allTriggers !== null) { - // Just checking all three. Could just make a new list, but meh - if (allTriggers.pipelines !== undefined && allTriggers.pipelines !== null) { - for (var pipelineKey in allTriggers.pipelines) { - if (allTriggers.pipelines[pipelineKey].id === data.id) { - data.status = allTriggers.pipelines[pipelineKey].status - } - } - } + // Just checking all three. Could just make a new list, but meh + if (allTriggers.pipelines !== undefined && allTriggers.pipelines !== null) { + for (var pipelineKey in allTriggers.pipelines) { + if (allTriggers.pipelines[pipelineKey].id === data.id) { + data.status = allTriggers.pipelines[pipelineKey].status + } + } + } - if (allTriggers.webhooks !== undefined && allTriggers.webhooks !== null) { - for (var webhookKey in allTriggers.webhooks) { - if (allTriggers.webhooks[webhookKey].id === data.id) { - data.status = allTriggers.webhooks[webhookKey].status - } - } - } + if (allTriggers.webhooks !== undefined && allTriggers.webhooks !== null) { + for (var webhookKey in allTriggers.webhooks) { + if (allTriggers.webhooks[webhookKey].id === data.id) { + data.status = allTriggers.webhooks[webhookKey].status + } + } + } - if (allTriggers.schedules !== undefined && allTriggers.schedules !== null) { - for (var scheduleKey in allTriggers.schedules) { - if (allTriggers.schedules[scheduleKey].id === data.id) { - data.status = allTriggers.schedules[scheduleKey].status - } - } - } - } + if (allTriggers.schedules !== undefined && allTriggers.schedules !== null) { + for (var scheduleKey in allTriggers.schedules) { + if (allTriggers.schedules[scheduleKey].id === data.id) { + data.status = allTriggers.schedules[scheduleKey].status + } + } + } + } - setSelectedTriggerIndex(trigger_index) - setSelectedTrigger(data) - //setSelectedActionEnvironment(data.env) - }, 25) + setSelectedTriggerIndex(trigger_index) + setSelectedTrigger(data) + //setSelectedActionEnvironment(data.env) + }, 25) } else if (data.type === "COMMENT") { setSelectedComment(data); } else { @@ -5957,14 +5942,14 @@ const releaseToConnectLabel = "Release to Connect" selected: "", }); - setSuggestionBox({ - "position": { - "top": 500, - "left": 500, - }, - "open": false, - "attachedTo": "", - }); + setSuggestionBox({ + "position": { + "top": 500, + "left": 500, + }, + "open": false, + "attachedTo": "", + }); sendStreamRequest({ "item": "node", @@ -6000,8 +5985,8 @@ const releaseToConnectLabel = "Release to Connect" toast("Failed to auto-activate the app. Go to /apps and activate it.") } else { if (refresh === true) { - setHighlightedApp(appid) - //toast("App activated for your organisation! Refresh the page to use the app.") + setHighlightedApp(appid) + //toast("App activated for your organisation! Refresh the page to use the app.") getApps() } @@ -6164,7 +6149,7 @@ const releaseToConnectLabel = "Release to Connect" selectedkey = `.${key}`; } - for (let [subitem,subitemval] in Object.entries(value)) { + for (let [subitem, subitemval] in Object.entries(value)) { toreturn = GetParamMatch( paramname, value[subitem], @@ -6251,34 +6236,34 @@ const releaseToConnectLabel = "Release to Connect" : item.label.toLowerCase().trim().replaceAll(" ", "_"); exampledata = GetExampleResult(item); - if (dstdata.parameters !== undefined && dstdata.parameters !== null) { - for (let [paramkey,paramkeyval] in Object.entries(dstdata.parameters)) { - const param = dstdata.parameters[paramkey]; - // Skip authentication params - if (param.configuration) { - continue - } + if (dstdata.parameters !== undefined && dstdata.parameters !== null) { + for (let [paramkey, paramkeyval] in Object.entries(dstdata.parameters)) { + const param = dstdata.parameters[paramkey]; + // Skip authentication params + if (param.configuration) { + continue + } - if (param.options !== undefined && param.options !== null && param.options.length > 0) { - continue - } + if (param.options !== undefined && param.options !== null && param.options.length > 0) { + continue + } - const paramname = param.name - .toLowerCase() - .trim() - .replaceAll("_", " "); + const paramname = param.name + .toLowerCase() + .trim() + .replaceAll("_", " "); - const foundresult = GetParamMatch(paramname, exampledata, ""); - if (foundresult.length > 0) { - if (dstdata.parameters[paramkey].value.length === 0) { - dstdata.parameters[paramkey].value = `$${parentlabel}${foundresult}`; - dstdata.parameters[paramkey].autocompleted = true - } else { - //dstdata.parameters[paramkey].value = `$${parentlabel}${foundresult}`; - } - } + const foundresult = GetParamMatch(paramname, exampledata, ""); + if (foundresult.length > 0) { + if (dstdata.parameters[paramkey].value.length === 0) { + dstdata.parameters[paramkey].value = `$${parentlabel}${foundresult}`; + dstdata.parameters[paramkey].autocompleted = true + } else { + //dstdata.parameters[paramkey].value = `$${parentlabel}${foundresult}`; + } + } } - } + } } } @@ -6291,7 +6276,7 @@ const releaseToConnectLabel = "Release to Connect" const edge = event.target.data(); if (edge.source === undefined && edge.target === undefined) { - //console.log("Edge added without source or target") + //console.log("Edge added without source or target") return } @@ -6307,12 +6292,12 @@ const releaseToConnectLabel = "Release to Connect" const destinationnode = cy.getElementById(edge.target) if (sourcenode === undefined || sourcenode === null || destinationnode === undefined || destinationnode === null) { - console.log("Source or destination node is undefined or null: ", sourcenode, destinationnode) + console.log("Source or destination node is undefined or null: ", sourcenode, destinationnode) } else { - if (sourcenode.data("name") === "switch") { - event.target.remove() - return - } + if (sourcenode.data("name") === "switch") { + event.target.remove() + return + } console.log("Edge added: Is it a trigger? If so, check if it already has a branch and remove it: ", sourcenode.data()) if (sourcenode.data("type") === "TRIGGER") { @@ -6343,8 +6328,8 @@ const releaseToConnectLabel = "Release to Connect" const edgeCurve = calculateEdgeCurve(sourcenode.position(), destinationnode.position()) const currentedge = cy.getElementById(edge.id) if (currentedge !== undefined && currentedge !== null) { - currentedge.style('control-point-distance', edgeCurve.distance) - currentedge.style('control-point-weight', edgeCurve.weight) + currentedge.style('control-point-distance', edgeCurve.distance) + currentedge.style('control-point-weight', edgeCurve.weight) } } @@ -6354,7 +6339,7 @@ const releaseToConnectLabel = "Release to Connect" ) if (targetnode !== -1) { if (workflow.triggers[targetnode].app_name === "User Input" || workflow.triggers[targetnode].app_name === "Shuffle Workflow" || workflow.triggers[targetnode].app_name === "Shuffle Subflow") { - console.log("User Input or Shuffle Workflow") + console.log("User Input or Shuffle Workflow") } else { toast("Can't have triggers as target of branch") event.target.remove() @@ -6400,7 +6385,7 @@ const releaseToConnectLabel = "Release to Connect" // dest == source && source == dest // dest == dest && source == source // backend: check all children? to stop recursion - // + // var found = false; for (let branchkey in workflow.branches) { if (workflow.branches[branchkey].destination_id === edge.source && workflow.branches[branchkey].source_id === edge.target) { @@ -6408,25 +6393,25 @@ const releaseToConnectLabel = "Release to Connect" event.target.remove() found = true break - } + } - if (workflow.branches[branchkey].destination_id === edge.target && workflow.branches[branchkey].source_id === edge.source) { + if (workflow.branches[branchkey].destination_id === edge.target && workflow.branches[branchkey].source_id === edge.source) { - console.log("That branch already exists: ", workflow.branches[branchkey]) - const foundbranch = cy.getElementById(workflow.branches[branchkey].id) - if (foundbranch !== undefined && foundbranch !== null && foundbranch.data() !== undefined && foundbranch.data() !== null) { - console.log("Removing branch: ", foundbranch.data()) + console.log("That branch already exists: ", workflow.branches[branchkey]) + const foundbranch = cy.getElementById(workflow.branches[branchkey].id) + if (foundbranch !== undefined && foundbranch !== null && foundbranch.data() !== undefined && foundbranch.data() !== null) { + console.log("Removing branch: ", foundbranch.data()) - event.target.remove() + event.target.remove() - found = true - break - } else { - //console.log("Old branch didn't exist afterall. Remove.") - } - } + found = true + break + } else { + //console.log("Old branch didn't exist afterall. Remove.") + } + } - if (edge.target === workflow.start) { + if (edge.target === workflow.start) { targetnode = workflow.triggers.findIndex( (data) => data.id === edge.source ); @@ -6439,9 +6424,9 @@ const releaseToConnectLabel = "Release to Connect" found = true; } - } + } - if (edge.source === workflow.branches[branchkey].source_id) { + if (edge.source === workflow.branches[branchkey].source_id) { // FIXME: Verify multi-target for triggers // 1. Check if destination exists // 2. Check if source is a trigger @@ -6545,21 +6530,21 @@ const releaseToConnectLabel = "Release to Connect" setWorkflowAsCode(true); } - if (nodedata.decorator !== true && nodedata.attachedTo === undefined) { - var newdata = JSON.parse(JSON.stringify(nodedata)) - newdata.large_image = "" - sendStreamRequest({ - "item": "node", - "type": "add", - "id": nodedata.id, - "data": nodedata, - "x": node.position("x"), - "y": node.position("y"), - }) - } + if (nodedata.decorator !== true && nodedata.attachedTo === undefined) { + var newdata = JSON.parse(JSON.stringify(nodedata)) + newdata.large_image = "" + sendStreamRequest({ + "item": "node", + "type": "add", + "id": nodedata.id, + "data": nodedata, + "x": node.position("x"), + "y": node.position("y"), + }) + } if (nodedata.type === "ACTION") { - // Should get recommendations to load in for all nodesma + // Should get recommendations to load in for all nodesma if (workflow.actions.length === 1 && workflow.actions[0].id === workflow.start) { const newEdgeUuid = uuidv4(); @@ -6602,7 +6587,7 @@ const releaseToConnectLabel = "Release to Connect" if (nodedata.parameters !== undefined && nodedata.parameters !== null && !nodedata?.label?.endsWith("_copy")) { var newparameters = []; - for (let [subkey,subkeyval] in Object.entries(nodedata.parameters)) { + for (let [subkey, subkeyval] in Object.entries(nodedata.parameters)) { var newparam = JSON.parse(JSON.stringify(nodedata.parameters[subkey])) newparam.id = uuidv4() @@ -6624,13 +6609,13 @@ const releaseToConnectLabel = "Release to Connect" workflow.actions.push(nodedata); } - // 1. Check how many actions there are. If less than three, send a toast notification with suggested workflows - //if (workflow.actions.length < 3) { - // toast("Recommendations to show??") - //} + // 1. Check how many actions there are. If less than three, send a toast notification with suggested workflows + //if (workflow.actions.length < 3) { + // toast("Recommendations to show??") + //} setWorkflow(workflow); - fetchRecommendations(workflow) + fetchRecommendations(workflow) } else if (nodedata.type === "TRIGGER") { if (nodedata.is_valid === false) { toast("This trigger is not available to you"); @@ -6661,15 +6646,15 @@ const releaseToConnectLabel = "Release to Connect" data: newcybranch, }; - if (edgeToBeAdded.data.source !== edgeToBeAdded.data.target && edgeToBeAdded.data.source !== undefined && edgeToBeAdded.data.target !== undefined) { - if (nodedata.name !== "User Input" && nodedata.name !== "Shuffle Workflow") { - console.log("NAME: ", nodedata.name) - if (workflow.actions !== undefined && workflow.actions !== null && workflow.actions.length > 0) { - console.log("Edge handle: ", edgeToBeAdded) - cy.add(edgeToBeAdded); - } - } - } + if (edgeToBeAdded.data.source !== edgeToBeAdded.data.target && edgeToBeAdded.data.source !== undefined && edgeToBeAdded.data.target !== undefined) { + if (nodedata.name !== "User Input" && nodedata.name !== "Shuffle Workflow") { + console.log("NAME: ", nodedata.name) + if (workflow.actions !== undefined && workflow.actions !== null && workflow.actions.length > 0) { + console.log("Edge handle: ", edgeToBeAdded) + cy.add(edgeToBeAdded); + } + } + } setWorkflow(workflow); } @@ -6697,42 +6682,42 @@ const releaseToConnectLabel = "Release to Connect" // Check if the source is trigger and can start //console.log("Removed: ", edge.data()) const allNodes = cy.nodes().jsons() - for (let nodekey in allNodes) { - const curnode = allNodes[nodekey] - if (curnode.data.type !== "TRIGGER") { - continue - } + for (let nodekey in allNodes) { + const curnode = allNodes[nodekey] + if (curnode.data.type !== "TRIGGER") { + continue + } - if (curnode.data.id === edge.data("source")) { - console.log("Found matching trigger source: ", curnode) - if (curnode.data.app_name !== "Shuffle Workflow" && curnode.data.app_name !== "User Input") { + if (curnode.data.id === edge.data("source")) { + console.log("Found matching trigger source: ", curnode) + if (curnode.data.app_name !== "Shuffle Workflow" && curnode.data.app_name !== "User Input") { - // If it's started, READD the edge - if (curnode.data.status === "running") { - //console.log("Edge is running - readd it: ", edge.data()) + // If it's started, READD the edge + if (curnode.data.status === "running") { + //console.log("Edge is running - readd it: ", edge.data()) - // Just making sure it's not running infinitely - var newdata = edge.data() - newdata.readded = true + // Just making sure it's not running infinitely + var newdata = edge.data() + newdata.readded = true - try { - cy.add({ - group: "edges", - data: newdata, - }) + try { + cy.add({ + group: "edges", + data: newdata, + }) - //toast.error("You must STOP the trigger before deleting its branches") - console.log("You must STOP the trigger before deleting its branches") - } catch (e) { - console.log("Failed re-adding edge: ", e) - } - } + //toast.error("You must STOP the trigger before deleting its branches") + console.log("You must STOP the trigger before deleting its branches") + } catch (e) { + console.log("Failed re-adding edge: ", e) + } + } - //status: "uninitialized", - } - } - } + //status: "uninitialized", + } + } + } workflow.branches = workflow.branches.filter( (a) => a.id !== edge.data().id @@ -6765,14 +6750,14 @@ const releaseToConnectLabel = "Release to Connect" const node = event.target; const data = node.data(); - // FIXME: This is still a bit buggy - if (data.decorator !== true && data.attachedTo === undefined) { - sendStreamRequest({ - "item": "node", - "type": "remove", - "id": data.id, - }) - } + // FIXME: This is still a bit buggy + if (data.decorator !== true && data.attachedTo === undefined) { + sendStreamRequest({ + "item": "node", + "type": "remove", + "id": data.id, + }) + } if (data.finished === false) { return @@ -6978,35 +6963,35 @@ const releaseToConnectLabel = "Release to Connect" // try { var parsedjson = JSON.parse(clipboard); - // Check if array - if (!Array.isArray(parsedjson)) { - console.log("Not array! Adding to array.") - parsedjson = [parsedjson] - } + // Check if array + if (!Array.isArray(parsedjson)) { + console.log("Not array! Adding to array.") + parsedjson = [parsedjson] + } for (let jsonkey in parsedjson) { var item = parsedjson[jsonkey]; console.log("Adding: ", item); - if (item.data === undefined || item.data === null) { - console.log("Appending from here") - const newitem = { - "data": item, - "position": { - "x": 0, - "y": 0 - }, - "group": "nodes", - } + if (item.data === undefined || item.data === null) { + console.log("Appending from here") + const newitem = { + "data": item, + "position": { + "x": 0, + "y": 0 + }, + "group": "nodes", + } - item = newitem - item.type = "ACTION" - item.isStartNode = false - item.data.type = "ACTION" - item.data.isStartNode = false - } + item = newitem + item.type = "ACTION" + item.isStartNode = false + item.data.type = "ACTION" + item.data.isStartNode = false + } - item.data.id = uuidv4() + item.data.id = uuidv4() cy.add({ group: item.group, @@ -7026,14 +7011,14 @@ const releaseToConnectLabel = "Release to Connect" }; const getEnvironments = (orgId) => { - var headers = { - "Content-Type": "application/json", - "Accept": "application/json", - } + var headers = { + "Content-Type": "application/json", + "Accept": "application/json", + } - if (orgId !== undefined && orgId !== null && orgId.length > 0) { - headers["Org-Id"] = orgId - } + if (orgId !== undefined && orgId !== null && orgId.length > 0) { + headers["Org-Id"] = orgId + } fetch(globalUrl + "/api/v1/getenvironments", { method: "GET", @@ -7069,7 +7054,7 @@ const releaseToConnectLabel = "Release to Connect" } } - // Always showing for now + // Always showing for now //if (showEnvCnt > 1) { if (showEnvCnt > 0) { setShowEnvironment(true) @@ -7094,22 +7079,22 @@ const releaseToConnectLabel = "Release to Connect" setEnvironments(responseJson) } - /* - setTimeout(() => { - console.log("ACTIONS: ", workflow.actions) - if (workflow.actions !== undefined && workflow.actions !== null && workflow.actions.length > 0) { - for (var actionkey in workflow.actions) { - if (workflow.actions[actionkey].environment !== undefined && workflow.actions[actionkey].environment !== null && workflow.actions[actionkey].environment.length > 0) { - - const env = environments.findIndex((data) => data.Name === workflow.actions[actionkey].environment) - if (env !== -1) { - setSelectedActionEnvironment(environments[env]) - } - } - } - } - }, 2500) - */ + /* + setTimeout(() => { + console.log("ACTIONS: ", workflow.actions) + if (workflow.actions !== undefined && workflow.actions !== null && workflow.actions.length > 0) { + for (var actionkey in workflow.actions) { + if (workflow.actions[actionkey].environment !== undefined && workflow.actions[actionkey].environment !== null && workflow.actions[actionkey].environment.length > 0) { + + const env = environments.findIndex((data) => data.Name === workflow.actions[actionkey].environment) + if (env !== -1) { + setSelectedActionEnvironment(environments[env]) + } + } + } + } + }, 2500) + */ }) .catch((error) => { //toast(error.toString()); @@ -7127,14 +7112,14 @@ const releaseToConnectLabel = "Release to Connect" workflow.id.length > 0 ) { - // Check if - if (distributedFromParent === "" && suborgWorkflows === []) { - toast.info("Redirecting as the workflow ID does not match the URL") + // Check if + if (distributedFromParent === "" && suborgWorkflows === []) { + toast.info("Redirecting as the workflow ID does not match the URL") - setTimeout(() => { - window.location.pathname = "/workflows/" + props.match.params.key; - }, 2500) - } + setTimeout(() => { + window.location.pathname = "/workflows/" + props.match.params.key; + }, 2500) + } } const animationDuration = 150; @@ -7146,37 +7131,37 @@ const releaseToConnectLabel = "Release to Connect" cytoscapeElement.style.cursor = "default" } - if (nodedata.finished === false) { + if (nodedata.finished === false) { - // Should just be 1, so this should be fast enough :3 - const incomingEdges = event.target.incomers("edge").jsons() - if (incomingEdges !== undefined && incomingEdges !== null) { - for (var i = 0; i < incomingEdges.length; i++) { - // Find the actual edge - const edge = cy.getElementById(incomingEdges[i].data.id) - if (edge === undefined || edge === null) { - console.log("edge is null or undefined") - continue - } + // Should just be 1, so this should be fast enough :3 + const incomingEdges = event.target.incomers("edge").jsons() + if (incomingEdges !== undefined && incomingEdges !== null) { + for (var i = 0; i < incomingEdges.length; i++) { + // Find the actual edge + const edge = cy.getElementById(incomingEdges[i].data.id) + if (edge === undefined || edge === null) { + console.log("edge is null or undefined") + continue + } - // Set the edge to be dashed - edge.style("target-arrow-color", "#555555") - edge.style("line-style", "dashed") - edge.style("line-gradient-stop-colors", ["#555555", "#555555"]) - } - } + // Set the edge to be dashed + edge.style("target-arrow-color", "#555555") + edge.style("line-style", "dashed") + edge.style("line-gradient-stop-colors", ["#555555", "#555555"]) + } + } return } - if (nodedata.name === "switch") { - return - } + if (nodedata.name === "switch") { + return + } // console.log("nodedata", nodedata); // console.log("nodedata.app_name: ", nodedata.app_name); if (nodedata.app_name !== undefined) { - + const allNodes = cy.nodes().jsons(); // console.log("allNodes: ", allNodes) for (var nodekey in allNodes) { @@ -7184,9 +7169,9 @@ const releaseToConnectLabel = "Release to Connect" // console.log("Current node: ", currentNode); if (currentNode.data.isButton && currentNode.data.attachedTo !== nodedata.id) { - if (currentNode.data.buttonType === "condition-drag") { - continue - } + if (currentNode.data.buttonType === "condition-drag") { + continue + } cy.getElementById(currentNode.data.id).remove(); } @@ -7286,148 +7271,148 @@ const releaseToConnectLabel = "Release to Connect" }; const addRunCountButton = (event) => { - // Count executions? - // Maybe it shouldn't be onclick? - } + // Count executions? + // Maybe it shouldn't be onclick? + } const addConditionDraggers = (event, allElements, branches) => { - const nodedata = event.target.data() - const position = event.target.position() + const nodedata = event.target.data() + const position = event.target.position() - var conditions = [] - const foundParam = nodedata.parameters.find((param) => param.name.toLowerCase() === "conditions") + var conditions = [] + const foundParam = nodedata.parameters.find((param) => param.name.toLowerCase() === "conditions") - try { - conditions = JSON.parse(foundParam.value) - } catch (e) { - //toast("Failed parsing conditions: ", e) - } + try { + conditions = JSON.parse(foundParam.value) + } catch (e) { + //toast("Failed parsing conditions: ", e) + } - // Test conditions - if (conditions === undefined || conditions === null || typeof conditions !== "object") { - return - } + // Test conditions + if (conditions === undefined || conditions === null || typeof conditions !== "object") { + return + } - // Look for if it has the "Else" condition or not - const elseindex = conditions.findIndex((condition) => condition.name.toLowerCase() === "else") - const parentId = nodedata.id + // Look for if it has the "Else" condition or not + const elseindex = conditions.findIndex((condition) => condition.name.toLowerCase() === "else") + const parentId = nodedata.id - // Force following of Else at the least - const newId = uuidv5(parentId, uuidv5.URL) - if (elseindex === -1) { - conditions.push({ - name: "Else", - check: "Else", - id: newId, - parent_source: parentId, - }) - } else { - conditions[elseindex].id = newId - } + // Force following of Else at the least + const newId = uuidv5(parentId, uuidv5.URL) + if (elseindex === -1) { + conditions.push({ + name: "Else", + check: "Else", + id: newId, + parent_source: parentId, + }) + } else { + conditions[elseindex].id = newId + } - // 4 conditions (with else) = 300px -> 75px each - const parentHeight = (conditions.length*75)*0.75 + // 4 conditions (with else) = 300px -> 75px each + const parentHeight = (conditions.length * 75) * 0.75 - var startheight = -parentHeight/2 - var newnodes = [] - for (let conditionkey in conditions) { - var circleId = conditions[conditionkey].id === undefined ? (newNodeId = uuidv4()) : conditions[conditionkey].id + var startheight = -parentHeight / 2 + var newnodes = [] + for (let conditionkey in conditions) { + var circleId = conditions[conditionkey].id === undefined ? (newNodeId = uuidv4()) : conditions[conditionkey].id - // Check if circleId is a valid uuid or not - if (circleId === undefined || circleId === null) { - circleId = uuidv4() - } + // Check if circleId is a valid uuid or not + if (circleId === undefined || circleId === null) { + circleId = uuidv4() + } - if (!isUUID(circleId)) { - if (conditions[circleId].name !== undefined && conditions[circleId].name !== null) { - circleId = uuidv5(conditions[circleId].name, uuidv5.URL) - } else { - circleId = uuidv4() - conditions[conditionkey].name = circleId - conditions[conditionkey].id = circleId - } - } + if (!isUUID(circleId)) { + if (conditions[circleId].name !== undefined && conditions[circleId].name !== null) { + circleId = uuidv5(conditions[circleId].name, uuidv5.URL) + } else { + circleId = uuidv4() + conditions[conditionkey].name = circleId + conditions[conditionkey].id = circleId + } + } - // Check if circleId already exists as a node - if (cy !== undefined && cy !== null) { - const existingNode = cy.getElementById(circleId) - if (existingNode !== undefined && existingNode !== null && existingNode.length > 0) { - continue - } - } + // Check if circleId already exists as a node + if (cy !== undefined && cy !== null) { + const existingNode = cy.getElementById(circleId) + if (existingNode !== undefined && existingNode !== null && existingNode.length > 0) { + continue + } + } - // 1. Create "small" nodes at each point along the section based on the amount of conditions - // 2. Make these conditions have edgehandles - // 3. Make these conditions have a "drag" handle - const px = position.x + 65 - const py = position.y + startheight + // 1. Create "small" nodes at each point along the section based on the amount of conditions + // 2. Make these conditions have edgehandles + // 3. Make these conditions have a "drag" handle + const px = position.x + 65 + const py = position.y + startheight - console.log("Y height: ", startheight) + console.log("Y height: ", startheight) - const node = { - group: "nodes", - data: { - name: conditions[conditionkey].name, - id: circleId, - buttonType: "condition-drag", - attachedTo: nodedata.id, - is_valid: true, - }, - position: { - x: px, - y: py, - }, - locked: true, - } + const node = { + group: "nodes", + data: { + name: conditions[conditionkey].name, + id: circleId, + buttonType: "condition-drag", + attachedTo: nodedata.id, + is_valid: true, + }, + position: { + x: px, + y: py, + }, + locked: true, + } - newnodes.push(node) + newnodes.push(node) - // Check if ANY of the incoming branches has the id as source - if (branches !== undefined && branches !== null && branches.length > 0) { - for (let branchkey in branches) { - const branch = branches[branchkey] - if (branch.source_id !== circleId) { - continue - } + // Check if ANY of the incoming branches has the id as source + if (branches !== undefined && branches !== null && branches.length > 0) { + for (let branchkey in branches) { + const branch = branches[branchkey] + if (branch.source_id !== circleId) { + continue + } - const branchid = uuidv4() - newnodes.push({ - group: "edges", - data: { - id: branchid, - _id: branchid, + const branchid = uuidv4() + newnodes.push({ + group: "edges", + data: { + id: branchid, + _id: branchid, - source: circleId, - target: branch.destination_id, - label: branch.label, - conditions: branch.conditions, - hasErrors: branch.has_errors, - decorator: false, - parent_source: parentId, - } - }) - } - } + source: circleId, + target: branch.destination_id, + label: branch.label, + conditions: branch.conditions, + hasErrors: branch.has_errors, + decorator: false, + parent_source: parentId, + } + }) + } + } - startheight = startheight + parentHeight/(conditions.length-1) - } + startheight = startheight + parentHeight / (conditions.length - 1) + } - if (cy !== undefined && cy !== null) { - cy.add(newnodes) - } else { - var newelements = elements - if (allElements !== undefined) { - newelements = allElements - } + if (cy !== undefined && cy !== null) { + cy.add(newnodes) + } else { + var newelements = elements + if (allElements !== undefined) { + newelements = allElements + } - for (let nodekey in newnodes) { - newelements.push(newnodes[nodekey]) - } + for (let nodekey in newnodes) { + newelements.push(newnodes[nodekey]) + } - console.log("ELEMENTS: ", newelements) - setElements(newelements) - } + console.log("ELEMENTS: ", newelements) + setElements(newelements) + } } const addCopyButton = (event) => { @@ -7468,288 +7453,288 @@ const releaseToConnectLabel = "Release to Connect" }; const addActionSuggestions = (nodedata, event) => { - if (nodedata.type !== "ACTION") { - return - } + if (nodedata.type !== "ACTION") { + return + } - var parentNode = cy.$("#" + event.target.data("id")) - if (parentNode.data("isButton") || parentNode.data("buttonId")) { - return - } + var parentNode = cy.$("#" + event.target.data("id")) + if (parentNode.data("isButton") || parentNode.data("buttonId")) { + return + } - const px = parentNode.position("x") + 0; - const py = parentNode.position("y") + 100; + const px = parentNode.position("x") + 0; + const py = parentNode.position("y") + 100; - const parentlabel = parentNode.data("label")?.toLowerCase().replace(" ", "_") - const parentname = parentNode.data("app_name")?.toLowerCase().replace(" ", "_") - if (!parentlabel?.startsWith(parentname)+"_") { - return - } + const parentlabel = parentNode.data("label")?.toLowerCase().replace(" ", "_") + const parentname = parentNode.data("app_name")?.toLowerCase().replace(" ", "_") + if (!parentlabel?.startsWith(parentname) + "_") { + return + } - // Check if action has changed - const parentAppId = parentNode.data("app_id") - const parentActionname = parentNode.data("name") - for (var appkey in apps) { - const curapp = apps[appkey] + // Check if action has changed + const parentAppId = parentNode.data("app_id") + const parentActionname = parentNode.data("name") + for (var appkey in apps) { + const curapp = apps[appkey] - if (curapp.id !== parentAppId) { - continue - } + if (curapp.id !== parentAppId) { + continue + } - if (curapp.actions === undefined || curapp.actions === null || curapp.actions.length === 0) { - continue - } + if (curapp.actions === undefined || curapp.actions === null || curapp.actions.length === 0) { + continue + } - var startIndex = curapp.actions.findIndex((action) => action.category_label !== undefined && action.category_label !== null && action.category_label.length > 0) - if (startIndex === -1) { - startIndex = 0 - } + var startIndex = curapp.actions.findIndex((action) => action.category_label !== undefined && action.category_label !== null && action.category_label.length > 0) + if (startIndex === -1) { + startIndex = 0 + } - if (curapp.actions[startIndex].name !== parentActionname) { - console.log("Return 2") - return - } + if (curapp.actions[startIndex].name !== parentActionname) { + console.log("Return 2") + return + } - break - } + break + } - console.log("CONTINUE EVEN WHEN FIELDS ARE FILLED") + console.log("CONTINUE EVEN WHEN FIELDS ARE FILLED") - const iconInfo = { - icon: "M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm-1 4l6 6v10c0 1.1-.9 2-2 2H7.99C6.89 23 6 22.1 6 21l.01-14c0-1.1.89-2 1.99-2h7zm-1 7h5.5L14 6.5V12z", - iconColor: buttonColor, - iconBackgroundColor: buttonBackgroundColor, - }; + const iconInfo = { + icon: "M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm-1 4l6 6v10c0 1.1-.9 2-2 2H7.99C6.89 23 6 22.1 6 21l.01-14c0-1.1.89-2 1.99-2h7zm-1 7h5.5L14 6.5V12z", + iconColor: buttonColor, + iconBackgroundColor: buttonBackgroundColor, + }; - const svg_pin = ``; - const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin); + const svg_pin = ``; + const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin); - // 1. Find the app - // 2. Loop the apps' actions - // 3. Find actions based on category label IF it exists - - var addedLabels = [] - for (let appKey in apps) { - const curapp = apps[appKey] - if (curapp.name.toLowerCase().replace(" ", "_") !== parentname) { - continue - } + // 1. Find the app + // 2. Loop the apps' actions + // 3. Find actions based on category label IF it exists - if (curapp.actions === undefined || curapp.actions === null || curapp.actions.length === 0) { - continue - } + var addedLabels = [] + for (let appKey in apps) { + const curapp = apps[appKey] + if (curapp.name.toLowerCase().replace(" ", "_") !== parentname) { + continue + } - for (let actionKey in curapp.actions) { - const curaction = curapp.actions[actionKey] - - // Check if this is the current action already - if (parentNode.data("name") == curaction.name) { - continue - } + if (curapp.actions === undefined || curapp.actions === null || curapp.actions.length === 0) { + continue + } - if (curaction.category_label !== undefined && curaction.category_label !== null && curaction.category_label.length > 0) { - if (addedLabels.includes(curaction.category_label[0])) { - continue - } + for (let actionKey in curapp.actions) { + const curaction = curapp.actions[actionKey] - if (curaction.category_label[0].replaceAll("_", " ").toLowerCase() === "no label") { - continue - } + // Check if this is the current action already + if (parentNode.data("name") == curaction.name) { + continue + } - cy.add({ - group: "nodes", - data: { - weight: 30, - id: uuidv4(), - label: curaction.category_label[0], - attachedTo: event.target.data("id"), - is_valid: true, - buttonType: "ACTIONSUGGESTION", - }, - position: { - x: px, - y: py + (addedLabels.length * 50), - }, - locked: true, - }) + if (curaction.category_label !== undefined && curaction.category_label !== null && curaction.category_label.length > 0) { + if (addedLabels.includes(curaction.category_label[0])) { + continue + } - addedLabels.push(curaction.category_label[0]) - if (addedLabels.length >= 2) { - break - } - } - } + if (curaction.category_label[0].replaceAll("_", " ").toLowerCase() === "no label") { + continue + } - break - } + cy.add({ + group: "nodes", + data: { + weight: 30, + id: uuidv4(), + label: curaction.category_label[0], + attachedTo: event.target.data("id"), + is_valid: true, + buttonType: "ACTIONSUGGESTION", + }, + position: { + x: px, + y: py + (addedLabels.length * 50), + }, + locked: true, + }) + + addedLabels.push(curaction.category_label[0]) + if (addedLabels.length >= 2) { + break + } + } + } + + break + } } const addSuggestionButtons = (nodedata, event) => { - //console.log("Skipping Adding suggestion buttons") - //return - // Skipping add for now. Should Re-enable + //console.log("Skipping Adding suggestion buttons") + //return + // Skipping add for now. Should Re-enable - // Add a button for autocompletion based on input - if (nodedata.type === "ACTION") { - /* - const color = "#34a853" + // Add a button for autocompletion based on input + if (nodedata.type === "ACTION") { + /* + const color = "#34a853" + + // Fix icon + const iconInfo = { + icon: "M7.5 5.6 10 7 8.6 4.5 10 2 7.5 3.4 5 2l1.4 2.5L5 7zm12 9.8L17 14l1.4 2.5L17 19l2.5-1.4L22 19l-1.4-2.5L22 14zM22 2l-2.5 1.4L17 2l1.4 2.5L17 7l2.5-1.4L22 7l-1.4-2.5zm-7.63 5.29a.9959.9959 0 0 0-1.41 0L1.29 18.96c-.39.39-.39 1.02 0 1.41l2.34 2.34c.39.39 1.02.39 1.41 0L16.7 11.05c.39-.39.39-1.02 0-1.41l-2.33-2.35zm-1.03 5.49-2.12-2.12 2.44-2.44 2.12 2.12-2.44 2.44z", + iconColor: buttonColor, + iconBackgroundColor: buttonBackgroundColor, + }; + + const svg_pin = ``; + const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin); + + const decoratorNode = { + position: { + x: event.target.position().x + 0, + y: event.target.position().y + 65, + }, + locked: true, + data: { + isButton: true, + isValid: true, + is_valid: true, + //label: "+", + attachedTo: nodedata.id, + imageColor: color, + buttonType: "suggestion", + icon: svgpin_Url, + iconBackground: iconInfo.iconBackgroundColor, + }, + }; + + cy.add(decoratorNode); + */ + } - // Fix icon - const iconInfo = { - icon: "M7.5 5.6 10 7 8.6 4.5 10 2 7.5 3.4 5 2l1.4 2.5L5 7zm12 9.8L17 14l1.4 2.5L17 19l2.5-1.4L22 19l-1.4-2.5L22 14zM22 2l-2.5 1.4L17 2l1.4 2.5L17 7l2.5-1.4L22 7l-1.4-2.5zm-7.63 5.29a.9959.9959 0 0 0-1.41 0L1.29 18.96c-.39.39-.39 1.02 0 1.41l2.34 2.34c.39.39 1.02.39 1.41 0L16.7 11.05c.39-.39.39-1.02 0-1.41l-2.33-2.35zm-1.03 5.49-2.12-2.12 2.44-2.44 2.12 2.12-2.44 2.44z", - iconColor: buttonColor, - iconBackgroundColor: buttonBackgroundColor, - }; + if (workflowRecommendations === undefined || workflowRecommendations === null || workflowRecommendations.length === 0) { + return + } - const svg_pin = ``; - const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin); + var parentNode = cy.$("#" + event.target.data("id")); + if (parentNode.data("isButton") || parentNode.data("buttonId")) return; - const decoratorNode = { - position: { - x: event.target.position().x + 0, - y: event.target.position().y + 65, - }, - locked: true, - data: { - isButton: true, - isValid: true, - is_valid: true, - //label: "+", - attachedTo: nodedata.id, - imageColor: color, - buttonType: "suggestion", - icon: svgpin_Url, - iconBackground: iconInfo.iconBackgroundColor, - }, - }; + const px = parentNode.position("x") + 0; + const py = parentNode.position("y") + 200; + const circleId = (newNodeId = uuidv4()); - cy.add(decoratorNode); - */ - } + parentNode.data("circleId", circleId); - if (workflowRecommendations === undefined || workflowRecommendations === null || workflowRecommendations.length === 0) { - return - } + var startHeight = 0 + for (let recKey in workflowRecommendations) { + const rec = workflowRecommendations[recKey] + if (rec.action_id !== nodedata.id) { + continue + } - var parentNode = cy.$("#" + event.target.data("id")); - if (parentNode.data("isButton") || parentNode.data("buttonId")) return; + if (rec.recommendations === undefined || rec.recommendations === null || rec.recommendations.length === 0) { + continue + } - const px = parentNode.position("x") + 0; - const py = parentNode.position("y") + 200; - const circleId = (newNodeId = uuidv4()); + for (let recIndex in rec.recommendations) { + const parsedRec = rec.recommendations[recIndex] + console.log("REC: ", parsedRec) - parentNode.data("circleId", circleId); + const foundVersion = parsedRec.app_version !== undefined && parsedRec.app_version !== null && parsedRec.app_version !== "" ? parsedRec.app_version : "1.1.0" + const foundApp = apps.find((app) => app.app_name === parsedRec.app_name && app.app_version === foundVersion) + // Find out if foundApp is shuffle tools, and if so, add the correct image based on name - var startHeight = 0 - for (let recKey in workflowRecommendations) { - const rec = workflowRecommendations[recKey] - if (rec.action_id !== nodedata.id) { - continue - } + const largeImage = parsedRec.large_image !== undefined && parsedRec.large_image !== null && parsedRec.large_image !== "" ? parsedRec.large_image : foundApp === undefined || foundApp === null ? theme.palette.defaultImage : foundApp.large_image - if (rec.recommendations === undefined || rec.recommendations === null || rec.recommendations.length === 0) { - continue - } + const uuid = uuidv4() + const attachedToId = event.target.data("id") + // Check if parsedRec.app_action exists already as a node under this one + const branches = cy.edges().jsons() + var found = false + for (let branchKey in branches) { + const branch = branches[branchKey] + if (branch.data.source !== attachedToId) { + continue + } - for (let recIndex in rec.recommendations) { - const parsedRec = rec.recommendations[recIndex] - console.log("REC: ", parsedRec) + const targetNode = cy.getElementById(branch.data.target) + if (targetNode === undefined || targetNode === null) { + continue + } - const foundVersion = parsedRec.app_version !== undefined && parsedRec.app_version !== null && parsedRec.app_version !== "" ? parsedRec.app_version : "1.1.0" - const foundApp = apps.find((app) => app.app_name === parsedRec.app_name && app.app_version === foundVersion) - // Find out if foundApp is shuffle tools, and if so, add the correct image based on name + if (targetNode.data("name") === parsedRec.app_action) { + console.log("Found existing node (action name): ", targetNode) + found = true + } - const largeImage = parsedRec.large_image !== undefined && parsedRec.large_image !== null && parsedRec.large_image !== "" ? parsedRec.large_image : foundApp === undefined || foundApp === null ? theme.palette.defaultImage : foundApp.large_image + // FIXME: This could potentially be removed + if (targetNode.data("app_id") === parsedRec.app_id) { + console.log("Found existing node (id): ", targetNode) + found = true + } + } - const uuid = uuidv4() - const attachedToId = event.target.data("id") - // Check if parsedRec.app_action exists already as a node under this one - const branches = cy.edges().jsons() - var found = false - for (let branchKey in branches) { - const branch = branches[branchKey] - if (branch.data.source !== attachedToId) { - continue - } + // Skip the suggestion if it already exists + if (found) { + continue + } - const targetNode = cy.getElementById(branch.data.target) - if (targetNode === undefined || targetNode === null) { - continue - } + // Checks for src/dst (e.g. trigger = src usually) + const isTarget = true - if (targetNode.data("name") === parsedRec.app_action) { - console.log("Found existing node (action name): ", targetNode) - found = true - } + var name = parsedRec.app_action + if (parsedRec.app_action === "subflow") { + name = "Shuffle Workflow" + } else if (parsedRec.app_action === "user_input") { + name = "User Input" + } - // FIXME: This could potentially be removed - if (targetNode.data("app_id") === parsedRec.app_id) { - console.log("Found existing node (id): ", targetNode) - found = true - } - } + const newaction = { + name: name, + label: parsedRec.app_action, + label_replaced: parsedRec.app_action.replace("_", " ", -1), - // Skip the suggestion if it already exists - if (found) { - continue - } + id: uuid, + app_name: parsedRec.app_name, + app_version: foundVersion, + app_id: parsedRec.app_id, + sharing: false, + private_id: "", + isStartNode: false, + large_image: largeImage, + is_valid: true, + isSuggestion: true, + isTarget: isTarget, + attachedTo: attachedToId, - // Checks for src/dst (e.g. trigger = src usually) - const isTarget = true + finished: false, + } - var name = parsedRec.app_action - if (parsedRec.app_action === "subflow") { - name = "Shuffle Workflow" - } else if (parsedRec.app_action === "user_input") { - name = "User Input" - } + cy.add({ + group: "nodes", + data: newaction, + position: { + x: px + startHeight, + y: py, + }, + locked: true, + }); - const newaction = { - name: name, - label: parsedRec.app_action, - label_replaced: parsedRec.app_action.replace("_", " ", -1), + cy.add({ + group: "edges", + data: { + source: event.target.data("id"), + target: uuid, + decorator: true, + } + }) - id: uuid, - app_name: parsedRec.app_name, - app_version: foundVersion, - app_id: parsedRec.app_id, - sharing: false, - private_id: "", - isStartNode: false, - large_image: largeImage, - is_valid: true, - isSuggestion: true, - isTarget: isTarget, - attachedTo: attachedToId, + startHeight += 100 + } - finished: false, - } - - cy.add({ - group: "nodes", - data: newaction, - position: { - x: px+startHeight, - y: py, - }, - locked: true, - }); - - cy.add({ - group: "edges", - data: { - source: event.target.data("id"), - target: uuid, - decorator: true, - } - }) - - startHeight += 100 - } - - console.log("Got Rec: ", rec) - break - } + console.log("Got Rec: ", rec) + break + } } const addDeleteButton2 = (event) => { @@ -7840,23 +7825,23 @@ const releaseToConnectLabel = "Release to Connect" if (nodedata.finished === false) { console.log("NODE UNFINISHED (hover in): ", JSON.parse(JSON.stringify(nodedata))) - // Should just be 1, so this should be fast enough :3 - const incomingEdges = event.target.incomers("edge").jsons() - if (incomingEdges !== undefined && incomingEdges !== null) { - for (var i = 0; i < incomingEdges.length; i++) { - // Find the actual edge - const edge = cy.getElementById(incomingEdges[i].data.id) - if (edge === undefined || edge === null) { - console.log("edge is null or undefined") - continue - } + // Should just be 1, so this should be fast enough :3 + const incomingEdges = event.target.incomers("edge").jsons() + if (incomingEdges !== undefined && incomingEdges !== null) { + for (var i = 0; i < incomingEdges.length; i++) { + // Find the actual edge + const edge = cy.getElementById(incomingEdges[i].data.id) + if (edge === undefined || edge === null) { + console.log("edge is null or undefined") + continue + } - // Set the edge to be dashed - edge.style("target-arrow-color", "white") - edge.style("line-style", "solid") - edge.style("line-gradient-stop-colors", ["white", "white"]) - } - } + // Set the edge to be dashed + edge.style("target-arrow-color", "white") + edge.style("line-style", "solid") + edge.style("line-gradient-stop-colors", ["white", "white"]) + } + } return } @@ -7867,58 +7852,58 @@ const releaseToConnectLabel = "Release to Connect" //if (parentNode.data("isButton") || parentNode.data("buttonId")) return; if (nodedata.app_name !== undefined && !workflow.public === true) { - const allNodes = cy.nodes().jsons(); + const allNodes = cy.nodes().jsons(); - if (nodedata.app_name === "Webhook" || nodedata.app_name === "Schedule" || nodedata.app_name === "Gmail" || nodedata.app_name === "Office365") { - var found = false; - for (let nodekey in allNodes) { - const currentNode = allNodes[nodekey]; - if ( - currentNode.data.attachedTo === nodedata.id && - currentNode.data.isDescriptor - ) { - found = true; - break; - } - } + if (nodedata.app_name === "Webhook" || nodedata.app_name === "Schedule" || nodedata.app_name === "Gmail" || nodedata.app_name === "Office365") { + var found = false; + for (let nodekey in allNodes) { + const currentNode = allNodes[nodekey]; + if ( + currentNode.data.attachedTo === nodedata.id && + currentNode.data.isDescriptor + ) { + found = true; + break; + } + } - if (!found) { - // Find how many executions it has - var executions = 0 - const matchingExecutions = workflowExecutions.filter((execution => execution.execution_source === nodedata.app_name.toLowerCase())) - const color = matchingExecutions.length > 0 ? "#34a853" : "#ea4436" - const decoratorNode = { - position: { - x: event.target.position().x + 44, - y: event.target.position().y + 44, - }, - locked: true, - data: { - isDescriptor: true, - isValid: true, - is_valid: true, - isTrigger: true, - label: `${matchingExecutions.length}`, - attachedTo: nodedata.id, - imageColor: color, - hasExecutions: true, - }, - }; + if (!found) { + // Find how many executions it has + var executions = 0 + const matchingExecutions = workflowExecutions.filter((execution => execution.execution_source === nodedata.app_name.toLowerCase())) + const color = matchingExecutions.length > 0 ? "#34a853" : "#ea4436" + const decoratorNode = { + position: { + x: event.target.position().x + 44, + y: event.target.position().y + 44, + }, + locked: true, + data: { + isDescriptor: true, + isValid: true, + is_valid: true, + isTrigger: true, + label: `${matchingExecutions.length}`, + attachedTo: nodedata.id, + imageColor: color, + hasExecutions: true, + }, + }; - cy.add(decoratorNode) - } - } + cy.add(decoratorNode) + } + } var found = false; for (var _key in allNodes) { const currentNode = allNodes[_key]; // console.log("CURRENT NODE: ", currentNode) - + if ((currentNode.data.buttonType === "ACTIONSUGGESTION" || currentNode.data.isButton || currentNode.data.isSuggestion) && currentNode.data.attachedTo !== nodedata.id) { - if (currentNode.data.buttonType === "condition-drag") { - continue - } + if (currentNode.data.buttonType === "condition-drag") { + continue + } cy.getElementById(currentNode.data.id).remove() } @@ -7931,14 +7916,14 @@ const releaseToConnectLabel = "Release to Connect" }*/ if (currentNode.data.isButton && currentNode.data.attachedTo === nodedata.id) { - found = true; + found = true; } } - if (nodedata.name === "switch") { - addConditionDraggers(event) - return - } + if (nodedata.name === "switch") { + addConditionDraggers(event) + return + } if (!found) { addDeleteButton(event) @@ -7947,31 +7932,31 @@ const releaseToConnectLabel = "Release to Connect" if (nodedata.trigger_type === "SUBFLOW" || nodedata.trigger_type === "USERINPUT") { addCopyButton(event); } else { - // Check how many executions from the source - addRunCountButton(event); - } - } else { + // Check how many executions from the source + addRunCountButton(event); + } + } else { - addCopyButton(event); - addStartnodeButton(event); - } + addCopyButton(event); + addStartnodeButton(event); + } - // autocomplete - // right click - // suggestions - addActionSuggestions(nodedata, event); + // autocomplete + // right click + // suggestions + addActionSuggestions(nodedata, event); - if (workflow.actions.length < 4) { - addSuggestionButtons(nodedata, event); - } else { - //console.log("Too many actions to suggest (for now)") - } - } + if (workflow.actions.length < 4) { + addSuggestionButtons(nodedata, event); + } else { + //console.log("Too many actions to suggest (for now)") + } + } } - if (nodedata.name === "switch") { - return - } + if (nodedata.name === "switch") { + return + } var parsedStyle = { "border-width": "7px", @@ -7980,9 +7965,9 @@ const releaseToConnectLabel = "Release to Connect" //"cursor": "pointer", } - if (nodedata.buttonType === "ACTIONSUGGESTION") { - parsedStyle["font-size"] = "18px" - } + if (nodedata.buttonType === "ACTIONSUGGESTION") { + parsedStyle["font-size"] = "18px" + } const typeIds = cy.elements('node:selected').jsons(); for (var idkey in typeIds) { @@ -7996,7 +7981,7 @@ const releaseToConnectLabel = "Release to Connect" if (nodedata.type !== "COMMENT") { parsedStyle.color = "white"; - } + } if (event.target !== undefined && event.target !== null) { event.target.animate( @@ -8029,10 +8014,10 @@ const releaseToConnectLabel = "Release to Connect" const edgeData = event.target.data(); if (edgeData.decorator === true) { - // Defaults - event.target.style("target-arrow-color", "#555555") - event.target.style("line-style", "dashed") - event.target.style("line-gradient-stop-colors", ["#555555", "#555555"]) + // Defaults + event.target.style("target-arrow-color", "#555555") + event.target.style("line-style", "dashed") + event.target.style("line-gradient-stop-colors", ["#555555", "#555555"]) return; } @@ -8053,15 +8038,15 @@ const releaseToConnectLabel = "Release to Connect" const edgeData = event.target.data(); if (edgeData.decorator === true) { - // Set color of it to white and not stripled - event.target.style("target-arrow-color", "white") - event.target.style("line-style", "solid") - event.target.style("line-gradient-stop-colors", ["white", "white"]) + // Set color of it to white and not stripled + event.target.style("target-arrow-color", "white") + event.target.style("line-style", "solid") + event.target.style("line-gradient-stop-colors", ["white", "white"]) return; } - // FIXME: Color problem. Do later + // FIXME: Color problem. Do later //sendStreamRequest({ // "item": "edge", // "type": "hover", @@ -8118,9 +8103,9 @@ const releaseToConnectLabel = "Release to Connect" if (event.target !== undefined && event.target !== null) { - // If decorator and hovered - // Set color to white - + // If decorator and hovered + // Set color to white + @@ -8188,19 +8173,19 @@ const releaseToConnectLabel = "Release to Connect" } } */ - if (isNaN(controlPointDistance[0])) { - controlPointDistance[0] = 0 - } - if (isNaN(controlPointDistance[1])) { - controlPointDistance[1] = 0 - } + if (isNaN(controlPointDistance[0])) { + controlPointDistance[0] = 0 + } + if (isNaN(controlPointDistance[1])) { + controlPointDistance[1] = 0 + } - if (isNaN(controlPointWeight[0])) { - controlPointWeight[0] = 0 - } - if (isNaN(controlPointWeight[1])) { - controlPointWeight[1] = 0 - } + if (isNaN(controlPointWeight[0])) { + controlPointWeight[0] = 0 + } + if (isNaN(controlPointWeight[1])) { + controlPointWeight[1] = 0 + } return { "distance": controlPointDistance, @@ -8209,32 +8194,32 @@ const releaseToConnectLabel = "Release to Connect" } const setupGraph = (inputworkflow) => { - // Reset cytoscape nodes and branches - if (cy !== undefined && cy !== null) { - if (inputworkflow.actions !== undefined && inputworkflow.actions !== null && inputworkflow.actions.length > 0) { - //cy.remove('*') - } - } + // Reset cytoscape nodes and branches + if (cy !== undefined && cy !== null) { + if (inputworkflow.actions !== undefined && inputworkflow.actions !== null && inputworkflow.actions.length > 0) { + //cy.remove('*') + } + } - if (inputworkflow.actions === undefined || inputworkflow.actions === null) { - inputworkflow.actions = [] - } + if (inputworkflow.actions === undefined || inputworkflow.actions === null) { + inputworkflow.actions = [] + } - if (inputworkflow.branches === undefined || inputworkflow.branches === null) { - inputworkflow.branches = [] - } + if (inputworkflow.branches === undefined || inputworkflow.branches === null) { + inputworkflow.branches = [] + } - if (inputworkflow.triggers === undefined || inputworkflow.triggers === null) { - inputworkflow.triggers = [] - } + if (inputworkflow.triggers === undefined || inputworkflow.triggers === null) { + inputworkflow.triggers = [] + } - if (inputworkflow.comments === undefined || inputworkflow.comments === null) { - inputworkflow.comments = [] - } + if (inputworkflow.comments === undefined || inputworkflow.comments === null) { + inputworkflow.comments = [] + } - if (inputworkflow.visual_branches === undefined || inputworkflow.visual_branches === null) { - inputworkflow.visual_branches = [] - } + if (inputworkflow.visual_branches === undefined || inputworkflow.visual_branches === null) { + inputworkflow.visual_branches = [] + } const actions = inputworkflow.actions.map((action) => { const node = {}; @@ -8256,13 +8241,13 @@ const releaseToConnectLabel = "Release to Connect" action.iconBackground = iconInfo.iconBackgroundColor; } } else if (action.app_name === "Integration Framework" || action.app_name === "Singul") { - const iconInfo = GetIconInfo(action) - if (iconInfo !== undefined && iconInfo !== null) { - action.fillGradient = iconInfo.fillGradient - action.iconBackground = iconInfo.iconBackgroundColor - action.fillstyle = "linear-gradient" - } - } + const iconInfo = GetIconInfo(action) + if (iconInfo !== undefined && iconInfo !== null) { + action.fillGradient = iconInfo.fillGradient + action.iconBackground = iconInfo.iconBackgroundColor + action.fillstyle = "linear-gradient" + } + } node.position = action.position; node.data = action; @@ -8272,10 +8257,10 @@ const releaseToConnectLabel = "Release to Connect" node.data.type = "ACTION"; node.isStartNode = action["id"] === inputworkflow.start; - if (node.data.errors !== undefined && node.data.errors !== null && node.data.errors.length > 0) { - node.data.is_valid = false - node.is_valid = false - } + if (node.data.errors !== undefined && node.data.errors !== null && node.data.errors.length > 0) { + node.data.is_valid = false + node.is_valid = false + } if (inputworkflow.public === true) { node.data.is_valid = true @@ -8294,150 +8279,203 @@ const releaseToConnectLabel = "Release to Connect" node.data.example = example; - if (inputworkflow?.id !== undefined && originalWorkflow?.id !== undefined && inputworkflow?.id !== originalWorkflow?.id && originalWorkflow.actions !== undefined && originalWorkflow.actions !== null && originalWorkflow.actions.length > 0) { - // Find the node in the original workflow - var inParent = false - for (var i = 0; i < originalWorkflow.actions.length; i++) { - const originalAction = originalWorkflow.actions[i] - if (originalAction.id === action.id) { - inParent = true - break - } - } + if (inputworkflow?.id !== undefined && originalWorkflow?.id !== undefined && inputworkflow?.id !== originalWorkflow?.id && originalWorkflow.actions !== undefined && originalWorkflow.actions !== null && originalWorkflow.actions.length > 0) { + // Find the node in the original workflow + var inParent = false + for (var i = 0; i < originalWorkflow.actions.length; i++) { + const originalAction = originalWorkflow.actions[i] + if (originalAction.id === action.id) { + inParent = true + break + } + } - if (inParent === true) { - setTimeout(() => { - const foundnode = cy.getElementById(action.id) - if (foundnode !== undefined && foundnode !== null) { - const parsedStyle = { - "border-width": "3px", - "border-opacity": "1", - "border-color": "#40E0D0", - "opacity": "0.4", - } + if (inParent === true) { + setTimeout(() => { + const foundnode = cy.getElementById(action.id) + if (foundnode !== undefined && foundnode !== null) { + const parsedStyle = { + "border-width": "3px", + "border-opacity": "1", + "border-color": "#40E0D0", + "opacity": "0.4", + } - const animationDuration = 150 - foundnode.animate( - { - style: parsedStyle, - }, - { - duration: animationDuration, - } - ) - } - }, 500) - } - } + const animationDuration = 150 + foundnode.animate( + { + style: parsedStyle, + }, + { + duration: animationDuration, + } + ) + } + }, 500) + } + } return node }) - // What are these again? Where are they used? - const decoratorNodes = [] + // What are these again? Where are they used? + const decoratorNodes = [] - /* - // Removed for now as it wasn't really that helpful - const decoratorNodes = inputworkflow.actions.map((action) => { - if (!action.isStartNode) { - if (action.app_name === "Testing") { - return null - } else if (action.app_name === "Shuffle Tools") { - return null - } else if (action.app_name === "Integration Framework" || action.app_name === "Singul") { - return null + /* + // Removed for now as it wasn't really that helpful + const decoratorNodes = inputworkflow.actions.map((action) => { + if (!action.isStartNode) { + if (action.app_name === "Testing") { + return null + } else if (action.app_name === "Shuffle Tools") { + return null + } else if (action.app_name === "Integration Framework" || action.app_name === "Singul") { + return null + } } + + if (action.id === undefined || action.id === null) { + return null } - - if (action.id === undefined || action.id === null) { - return null - } - - if (action.position === undefined || action.position === null || action.position.x === undefined || action.position.x === null || action.position.y === undefined || action.position.y === null) { - return null - } - - const iconInfo = GetIconInfo(action); - const svg_pin = ``; - const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin); - - const offset = action.isStartNode ? 36 : 44; - - const decoratorNode = { - position: { - x: action.position.x + offset, - y: action.position.y + offset, - }, - locked: true, - data: { - isDescriptor: true, - isValid: true, - is_valid: true, - label: "", - image: svgpin_Url, - imageColor: iconInfo.iconBackgroundColor, - attachedTo: action.id, - }, + + if (action.position === undefined || action.position === null || action.position.x === undefined || action.position.x === null || action.position.y === undefined || action.position.y === null) { + return null } - return decoratorNode - }) - */ + + const iconInfo = GetIconInfo(action); + const svg_pin = ``; + const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin); + + const offset = action.isStartNode ? 36 : 44; + + const decoratorNode = { + position: { + x: action.position.x + offset, + y: action.position.y + offset, + }, + locked: true, + data: { + isDescriptor: true, + isValid: true, + is_valid: true, + label: "", + image: svgpin_Url, + imageColor: iconInfo.iconBackgroundColor, + attachedTo: action.id, + }, + } + return decoratorNode + }) + */ const foundtriggers = inputworkflow.triggers.map((trigger) => { const node = {}; node.position = trigger.position; - if (trigger.large_image === undefined || trigger.large_image === null || trigger.large_image.length === 0) { - - // Search triggers array for it where the name is matching and set image - var foundTrigger = triggers.find((t) => t.name === trigger.name) - if (foundTrigger !== undefined && foundTrigger !== null) { - console.log("Autofilled missing trigger image") - trigger.large_image = foundTrigger.large_image - } - } + // Search triggers array for it where the name is matching and set image + if (trigger.large_image === undefined || trigger.large_image === null || trigger.large_image.length === 0) { + var foundTrigger = triggers.find((t) => t.name === trigger.name) + if (foundTrigger !== undefined && foundTrigger !== null) { + console.log("Autofilled missing trigger image") + trigger.large_image = foundTrigger.large_image + } + } node.data = trigger; node.data._id = trigger["id"]; node.data.id = trigger["id"]; node.data.type = "TRIGGER"; - if (inputworkflow?.id !== undefined && originalWorkflow?.id !== undefined && inputworkflow?.id !== originalWorkflow?.id && originalWorkflow.triggers !== undefined && originalWorkflow.triggers !== null && originalWorkflow.triggers.length > 0) { - // Find the node in the original workflow - var inParent = false - for (var i = 0; i < originalWorkflow.triggers.length; i++) { - const originalAction = originalWorkflow.triggers[i] - if (originalAction.id === trigger.id) { - inParent = true - break - } - } + // Adds the correct branching for same-workflow trigger + if (trigger?.trigger_type === "SUBFLOW" && trigger?.parameters !== undefined && trigger?.parameters !== null && trigger?.parameters.length > 0) { + var foundTargetNode = "" + var sameWorkflow = false + for (var key in trigger.parameters) { + if (trigger.parameters[key].name === "workflow" && trigger.parameters[key].value === inputworkflow.id) { + sameWorkflow = true + } - if (inParent === true) { - setTimeout(() => { - const foundnode = cy.getElementById(trigger.id) - if (foundnode !== undefined && foundnode !== null) { - const parsedStyle = { - "border-width": "3px", - "border-opacity": "1", - "border-color": "#40E0D0", - "opacity": "0.4", - } + if (trigger.parameters[key].name === "startnode" && trigger.parameters[key].value !== "") { + foundTargetNode = trigger.parameters[key].value + } + } - const animationDuration = 150 - foundnode.animate( - { - style: parsedStyle, - }, - { - duration: animationDuration, - } - ) - } - }, 500) - } - } + if (sameWorkflow && foundTargetNode !== "") { + const newid = uuidv4() + const newbranch = { + id: newid, + _id: newid, + source: trigger.id, + source_id: trigger.id, + target: foundTargetNode, + destination_id: foundTargetNode, + + conditions: [], + has_errors: false, + decorator: true, + label: "Subflow", + } + + if (inputworkflow.visual_branches !== undefined) { + if (inputworkflow.visual_branches === null) { + inputworkflow.visual_branches = [newbranch] + } else if (inputworkflow.visual_branches.length === 0) { + inputworkflow.visual_branches.push(newbranch) + } else { + const foundIndex = inputworkflow.visual_branches.findIndex( + (branch) => branch.source_id === newbranch.source_id + ) + + if (foundIndex !== -1) { + //console.log("Already found subflow branch") + } else { + inputworkflow.visual_branches.push(newbranch); + } + } + } else { + inputworkflow.visual_branches = [newbranch] + } + + } + + } + + if (inputworkflow?.id !== undefined && originalWorkflow?.id !== undefined && inputworkflow?.id !== originalWorkflow?.id && originalWorkflow.triggers !== undefined && originalWorkflow.triggers !== null && originalWorkflow.triggers.length > 0) { + // Find the node in the original workflow + var inParent = false + for (var i = 0; i < originalWorkflow.triggers.length; i++) { + const originalAction = originalWorkflow.triggers[i] + if (originalAction.id === trigger.id) { + inParent = true + break + } + } + + if (inParent === true) { + setTimeout(() => { + const foundnode = cy.getElementById(trigger.id) + if (foundnode !== undefined && foundnode !== null) { + const parsedStyle = { + "border-width": "3px", + "border-opacity": "1", + "border-color": "#40E0D0", + "opacity": "0.4", + } + + const animationDuration = 150 + foundnode.animate( + { + style: parsedStyle, + }, + { + duration: animationDuration, + } + ) + } + }, 500) + } + } return node; }); @@ -8477,30 +8515,30 @@ const releaseToConnectLabel = "Release to Connect" label = conditions.length + " conditions"; } - // Verify if branch.source_id and branch.destination_id exists in triggers or actions - /* - var sourceExists = false; - var destinationExists = false; - for (var i = 0; i < insertedNodes.length; i++) { - console.log("Insertednode: ", insertedNodes[i].data); - if (insertedNodes[i].data._id === branch.source_id) { - sourceExists = true; - } - if (insertedNodes[i].data._id === branch.destination_id) { - destinationExists = true; - } - } + // Verify if branch.source_id and branch.destination_id exists in triggers or actions + /* + var sourceExists = false; + var destinationExists = false; + for (var i = 0; i < insertedNodes.length; i++) { + console.log("Insertednode: ", insertedNodes[i].data); + if (insertedNodes[i].data._id === branch.source_id) { + sourceExists = true; + } + if (insertedNodes[i].data._id === branch.destination_id) { + destinationExists = true; + } + } + + if (sourceExists === false || destinationExists === false) { + console.log("Couldn't find source node for branch " + branch.id); + return null; + } + */ - if (sourceExists === false || destinationExists === false) { - console.log("Couldn't find source node for branch " + branch.id); - return null; - } - */ - - var parentcontrolled = false - if (branch.parent_controlled !== undefined && branch.parent_controlled !== null && branch.parent_controlled === true) { - parentcontrolled = true - } + var parentcontrolled = false + if (branch.parent_controlled !== undefined && branch.parent_controlled !== null && branch.parent_controlled === true) { + parentcontrolled = true + } edge.data = { id: branch.id, @@ -8511,7 +8549,7 @@ const releaseToConnectLabel = "Release to Connect" conditions: conditions, hasErrors: branch.has_errors, decorator: false, - parent_controlled: parentcontrolled, + parent_controlled: parentcontrolled, } // This is an attempt at prettier edges. The numbers are weird to work with. @@ -8595,35 +8633,35 @@ const releaseToConnectLabel = "Release to Connect" insertedNodes = insertedNodes.concat(newedges); setWorkflow(inputworkflow); - // Reset view for cytoscape - if (cy !== undefined && cy !== null) { - cy.add(insertedNodes); - cy.fit(null, 400); - } else { - setElements(insertedNodes); - } + // Reset view for cytoscape + if (cy !== undefined && cy !== null) { + cy.add(insertedNodes); + cy.fit(null, 400); + } else { + setElements(insertedNodes); + } - const additionalNodes = inputworkflow.actions.map((action) => { - // Looking for: el.data("name") != "switch" - if (action.name !== "switch") { - return null - } + const additionalNodes = inputworkflow.actions.map((action) => { + // Looking for: el.data("name") != "switch" + if (action.name !== "switch") { + return null + } - addConditionDraggers({ - target: { - // Run data() function - data: function() { - return action - }, - position: function() { - return action.position - } - } - }, - insertedNodes, - inputworkflow.branches, - ) - }) + addConditionDraggers({ + target: { + // Run data() function + data: function () { + return action + }, + position: function () { + return action.position + } + } + }, + insertedNodes, + inputworkflow.branches, + ) + }) } const removeNode = (nodeId) => { @@ -8681,11 +8719,11 @@ const releaseToConnectLabel = "Release to Connect" if (selectedNode.data().decorator === true && selectedNode.data("type") !== "COMMENT") { toast("This node can't be deleted."); } else { - selectedNode.remove(); + selectedNode.remove(); - setSelectedTrigger({}) - setSelectedEdge({}) - setSelectedAction({}) + setSelectedTrigger({}) + setSelectedEdge({}) + setSelectedAction({}) } // An attempt at NOT unselecting when removing @@ -8716,55 +8754,55 @@ const releaseToConnectLabel = "Release to Connect" } const fetchRecommendations = (inputWorkflow) => { - console.log("Disabled recommendations as they were too inaccurate") - return + console.log("Disabled recommendations as they were too inaccurate") + return - const parsedWorkflow = JSON.parse(JSON.stringify(inputWorkflow)) + const parsedWorkflow = JSON.parse(JSON.stringify(inputWorkflow)) fetch(globalUrl + "/api/v1/workflows/recommend", { method: "POST", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify(parsedWorkflow), - credentials: "include", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify(parsedWorkflow), + credentials: "include", }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for usecases"); - } + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for usecases"); + } - return response.json(); - }) - .then((responseJson) => { - if (responseJson.success !== false) { - //console.log("recommendations: ", responseJson); + return response.json(); + }) + .then((responseJson) => { + if (responseJson.success !== false) { + //console.log("recommendations: ", responseJson); - if (responseJson.actions !== undefined && responseJson.actions !== null) { - console.log("Got recommendations: ", responseJson.actions) + if (responseJson.actions !== undefined && responseJson.actions !== null) { + console.log("Got recommendations: ", responseJson.actions) - //if (cy !== undefined && cy !== null) { - // cy.removeListener("mouseover", "node"); - //} + //if (cy !== undefined && cy !== null) { + // cy.removeListener("mouseover", "node"); + //} - setWorkflowRecommendations(responseJson.actions) + setWorkflowRecommendations(responseJson.actions) - //if (cy !== undefined && cy !== null) { - // cy.on("mouseover", "node", (e) => onNodeHover(e)); - //} - } else { - setWorkflowRecommendations([]) - } - } else { - setWorkflowRecommendations([]) - } - }) - .catch((error) => { - //toast("ERROR: " + error.toString()); - setWorkflowRecommendations([]) - console.log("ERROR getting usecases: " + error.toString()); - }) + //if (cy !== undefined && cy !== null) { + // cy.on("mouseover", "node", (e) => onNodeHover(e)); + //} + } else { + setWorkflowRecommendations([]) + } + } else { + setWorkflowRecommendations([]) + } + }) + .catch((error) => { + //toast("ERROR: " + error.toString()); + setWorkflowRecommendations([]) + console.log("ERROR getting usecases: " + error.toString()); + }) } const fetchUsecases = () => { @@ -8795,81 +8833,91 @@ const releaseToConnectLabel = "Release to Connect" }) } - const getRevisionHistory = (workflow_id) => { - fetch(`${globalUrl}/api/v1/workflows/${workflow_id}/revisions`, { - method: "GET", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - }, - credentials: "include", - }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for workflows :O!"); - } - - // Read text from stream - //return response.text(); - return response.json(); - }) - .then((responseJson) => { - if (responseJson === null) { - //console.log("No revisions found") - return - } - - if (responseJson.success === false) { - console.log("Error getting workflow revisions: ", responseJson) - return - } - - setAllRevisions(responseJson) - setSelectedVersion(responseJson[0]) - }) - .catch((error) => { - console.log("Error getting workflow revisions: ", error) - }); + const getRevisionHistory = (workflow_id, revisionCount = 50, turn = 0, orgId = "") => { + let headers = { + "Content-Type": "application/json", + Accept: "application/json", } - const loadTriggers = () => { - const url = `${globalUrl}/api/v1/triggers` - fetch(url, - { - method: "GET", - headers: { "content-type": "application/json" }, - credentials: "include", + if (orgId !== "") { + headers["Org-Id"] = orgId + } + + fetch(`${globalUrl}/api/v1/workflows/${workflow_id}/revisions?count=${revisionCount}`, { + method: "GET", + headers: headers, + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for workflows :O!"); } - ) - .then((response) => { - if (response.status !== 200) { - throw new Error("No folders :o!"); - } - return response.json(); - }) - .then((responseJson) => { - if (responseJson.success !== false) { - setAllTriggers(responseJson) - } - }) - .catch((error) => { - console.log("Get outlook folders error: ", error.toString()); - }); - } + // Read text from stream + //return response.text(); + return response.json(); + }) + .then((responseJson) => { + if (responseJson === null) { + //console.log("No revisions found") + return + } + + if (responseJson.success === false) { + console.log("Error getting workflow revisions: ", responseJson) + return + } + + setAllRevisions(responseJson) + setSelectedVersion(responseJson[0]) + }) + .catch((error) => { + console.log("Error getting workflow revisions: ", error); + ++turn; + if (turn < 2) { + getRevisionHistory(workflow_id, 5, turn, orgId); + } + }); + } + + const loadTriggers = () => { + const url = `${globalUrl}/api/v1/triggers` + fetch(url, + { + method: "GET", + headers: { "content-type": "application/json" }, + credentials: "include", + } + ) + .then((response) => { + if (response.status !== 200) { + throw new Error("No folders :o!"); + } + + return response.json(); + }) + .then((responseJson) => { + if (responseJson.success !== false) { + setAllTriggers(responseJson) + } + }) + .catch((error) => { + console.log("Get outlook folders error: ", error.toString()); + }); + } // eslint-disable-next-line react-hooks/exhaustive-deps //useEffect(() => { if (firstrequest) { setFirstrequest(false); getWorkflow(props.match.params.key, {}); - getChildWorkflows(props.match.params.key) - getRevisionHistory(props.match.params.key) - loadTriggers() + getChildWorkflows(props.match.params.key) + getRevisionHistory(props.match.params.key) + loadTriggers() getApps() fetchUsecases() - setLeftSideBarOpenByClick(false) + setLeftSideBarOpenByClick(false) localStorage.setItem("expandLeftNav", false) const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; @@ -8912,7 +8960,7 @@ const releaseToConnectLabel = "Release to Connect" console.log("In graph setup") // 2nd load - configures cytoscape - //} else if (!established && cy !== undefined && ((apps !== null && apps !== undefined && apps.length > 0) || workflow.public === true) && Object.getOwnPropertyNames(workflow).length > 0 && appAuthentication !== undefined && workflowRecommendations !== undefined) { + //} else if (!established && cy !== undefined && ((apps !== null && apps !== undefined && apps.length > 0) || workflow.public === true) && Object.getOwnPropertyNames(workflow).length > 0 && appAuthentication !== undefined && workflowRecommendations !== undefined) { } else if (!established && cy !== undefined && ((apps !== null && apps !== undefined && apps.length > 0) || workflow.public === true) && Object.getOwnPropertyNames(workflow).length > 0 && appAuthentication !== undefined) { //This part has to load LAST, as it's kind of not async. @@ -8948,10 +8996,10 @@ const releaseToConnectLabel = "Release to Connect" if (cy.edgehandles !== undefined) { cy.edgehandles({ handleNodes: (el) => { - // Check of length of el.data() is 1 - if (el.data() === undefined || Object.keys(el.data()).length === 1) { - return false - } + // Check of length of el.data() is 1 + if (el.data() === undefined || Object.keys(el.data()).length === 1) { + return false + } if (el.isNode() && el.data("buttonType") != "ACTIONSUGGESTION" && @@ -9004,9 +9052,9 @@ const releaseToConnectLabel = "Release to Connect" } }); - cy.on('grab', 'edge', (e) => { - console.log("Edge grabbed: ", e.target.data()) - }) + cy.on('grab', 'edge', (e) => { + console.log("Edge grabbed: ", e.target.data()) + }) cy.on("select", "node", (e) => { onNodeSelect(e, appAuthentication); @@ -9033,7 +9081,7 @@ const releaseToConnectLabel = "Release to Connect" document.title = "Workflow - " + workflow.name; - startWorkflowStream(props.match.params.key); + startWorkflowStream(props.match.params.key); registerKeys(); } @@ -9084,7 +9132,7 @@ const releaseToConnectLabel = "Release to Connect" toast("Error: name can't be empty"); return; } - + var mappedStartnode = ""; const alledges = cy.edges().jsons(); if (alledges !== undefined && alledges !== null && alledges.length > 0) { @@ -9113,7 +9161,7 @@ const releaseToConnectLabel = "Release to Connect" if (response.status !== 200) { console.log("Status not 200 for stream results :O!"); } - + return response.json(); }) .then((responseJson) => { @@ -9123,21 +9171,22 @@ const releaseToConnectLabel = "Release to Connect" if (data.type === "create") { toast("Pipeline will be created!"); } else if (data.type === "stop") { - toast("Pipeline will be stopped!"); + toast("Pipeline will be stopped!"); } else { toast("Pipeline deleted!") return } - if (trigger.parameters){ - trigger.parameters.push({ - name: data.name, - value: data.command, - });} - + if (trigger.parameters) { + trigger.parameters.push({ + name: data.name, + value: data.command, + }); + } + if (data.type === "stop") trigger.status = "stopped"; else trigger.status = "running"; workflow.triggers[triggerindex] = trigger; - + setSelectedTrigger(trigger); setWorkflow(workflow); saveWorkflow(workflow); @@ -9147,27 +9196,27 @@ const releaseToConnectLabel = "Release to Connect" console.log("Get pipeline error: ", error.toString()); }); }; - + const submitSchedule = (trigger, triggerindex) => { if (trigger.name.length <= 0) { toast("Error: name can't be empty"); return; } - var mappedStartnode = "" - const alledges = cy.edges().jsons() + var mappedStartnode = "" + const alledges = cy.edges().jsons() if (alledges !== undefined && alledges !== null && alledges.length > 0) { - for (let edgekey in alledges) { - const tmp = alledges[edgekey] - if (tmp.data.source === trigger.id) { - mappedStartnode = tmp.data.target - break - } - } - } + for (let edgekey in alledges) { + const tmp = alledges[edgekey] + if (tmp.data.source === trigger.id) { + mappedStartnode = tmp.data.target + break + } + } + } - toast("Creating schedule") - var data = { + toast("Creating schedule") + var data = { name: trigger.name, frequency: workflow.triggers[triggerindex].parameters[0].value, execution_argument: workflow.triggers[triggerindex].parameters[1].value, @@ -9176,17 +9225,17 @@ const releaseToConnectLabel = "Release to Connect" start: mappedStartnode, } - if (data.frequency === undefined || data.frequency === null || data.frequency.length === 0) { - if (isCloud || selectedTrigger?.environment === "cloud") { - data.frequency = "*/25 * * * *" - workflow.triggers[triggerindex].parameters[0].value = "*/25 * * * *" - } else { - data.frequency = "60" - workflow.triggers[triggerindex].parameters[0].value = "60" - } + if (data.frequency === undefined || data.frequency === null || data.frequency.length === 0) { + if (isCloud || selectedTrigger?.environment === "cloud") { + data.frequency = "*/25 * * * *" + workflow.triggers[triggerindex].parameters[0].value = "*/25 * * * *" + } else { + data.frequency = "60" + workflow.triggers[triggerindex].parameters[0].value = "60" + } - setWorkflow(workflow) - } + setWorkflow(workflow) + } fetch( `${globalUrl}/api/v1/workflows/${props.match.params.key}/schedule`, @@ -9227,7 +9276,7 @@ const releaseToConnectLabel = "Release to Connect" const getSigmaInfo = () => { const url = globalUrl + "/api/v1/files/detection/sigma_rules"; - + fetch(url, { method: "GET", credentials: "include", @@ -9241,7 +9290,7 @@ const releaseToConnectLabel = "Release to Connect" toast("Failed to get sigma rules"); } else { setRules(responseJson.sigma_info); - + } }) ) @@ -9251,7 +9300,7 @@ const releaseToConnectLabel = "Release to Connect" }); }; - const parsedHeight = isMobile ? bodyHeight - appBarSize * 4 : bodyHeight - 57 + const parsedHeight = isMobile ? bodyHeight - appBarSize * 4 : bodyHeight - 57 const appViewStyle = { marginLeft: 5, marginRight: 5, @@ -9288,7 +9337,7 @@ const releaseToConnectLabel = "Release to Connect" } const VariableItem = (props) => { - const { variable, index, type } = props; + const { variable, index, type } = props; const [open, setOpen] = React.useState(false); const [anchorEl, setAnchorEl] = React.useState(null); @@ -9300,144 +9349,144 @@ const releaseToConnectLabel = "Release to Connect" const deleteVariable = (type, variableIndex) => { - console.log("Delete type: ", type, variableIndex) + console.log("Delete type: ", type, variableIndex) - if (type === "normal") { - if (workflow.workflow_variables !== undefined && workflow.workflow_variables !== null && workflow.workflow_variables.length > variableIndex) { - var vars = JSON.parse(JSON.stringify(workflow.workflow_variables)) - vars.splice(variableIndex, 1) - workflow.workflow_variables = vars + if (type === "normal") { + if (workflow.workflow_variables !== undefined && workflow.workflow_variables !== null && workflow.workflow_variables.length > variableIndex) { + var vars = JSON.parse(JSON.stringify(workflow.workflow_variables)) + vars.splice(variableIndex, 1) + workflow.workflow_variables = vars - console.log("Workflow after del: ", workflow) + console.log("Workflow after del: ", workflow) - setWorkflow(workflow); - setUpdate(Math.random()); - } - } else if (type === "exec") { - if (workflow.execution_variables !== undefined && workflow.execution_variables !== null && workflow.execution_variables.length > variableIndex) { - var vars = JSON.parse(JSON.stringify(workflow.execution_variables)) - vars.splice(variableIndex, 1) - workflow.execution_variables = vars + setWorkflow(workflow); + setUpdate(Math.random()); + } + } else if (type === "exec") { + if (workflow.execution_variables !== undefined && workflow.execution_variables !== null && workflow.execution_variables.length > variableIndex) { + var vars = JSON.parse(JSON.stringify(workflow.execution_variables)) + vars.splice(variableIndex, 1) + workflow.execution_variables = vars - console.log("Workflow after del: ", workflow) + console.log("Workflow after del: ", workflow) - setWorkflow(workflow); - setUpdate(Math.random()); - } - } + setWorkflow(workflow); + setUpdate(Math.random()); + } + } }; - return ( -
    - { }}> -
    -
    -
    { - setVariableInfo({ - "name": variable.name, - "description": variable.description, - "value": variable.value, - "index": index, - }) + return ( +
    + { }}> +
    +
    +
    { + setVariableInfo({ + "name": variable.name, + "description": variable.description, + "value": variable.value, + "index": index, + }) - if (type === "normal") { - setVariablesModalOpen(true); - } else if (type === "exec") { - setExecutionVariablesModalOpen(true); - } else { - console.log("Unknown type: ", type) - } - }} - > - {variable.name} -
    -
    - - - - { - setOpen(false); - setAnchorEl(null); - }} - > - { - setOpen(false); - setVariableInfo({ - "name": variable.name, - "description": variable.description, - "value": variable.value, - "index": index, - }) + if (type === "normal") { + setVariablesModalOpen(true); + } else if (type === "exec") { + setExecutionVariablesModalOpen(true); + } else { + console.log("Unknown type: ", type) + } + }} + > + {variable.name} +
    +
    + + + + { + setOpen(false); + setAnchorEl(null); + }} + > + { + setOpen(false); + setVariableInfo({ + "name": variable.name, + "description": variable.description, + "value": variable.value, + "index": index, + }) - if (type === "normal") { - setVariablesModalOpen(true); - } else if (type === "exec") { - setExecutionVariablesModalOpen(true); - } else { - console.log("Unknown type: ", type) - } - }} - key={"Edit"} - > - {"Edit"} - - { - deleteVariable(type, index); - setOpen(false); - }} - key={"Delete"} - > - {"Delete"} - - -
    -
    - -
    - ) - } + if (type === "normal") { + setVariablesModalOpen(true); + } else if (type === "exec") { + setExecutionVariablesModalOpen(true); + } else { + console.log("Unknown type: ", type) + } + }} + key={"Edit"} + > + {"Edit"} + + { + deleteVariable(type, index); + setOpen(false); + }} + key={"Delete"} + > + {"Delete"} + + +
    +
    + +
    + ) + } const VariablesView = () => { const variableScrollStyle = { @@ -9465,13 +9514,13 @@ const releaseToConnectLabel = "Release to Connect" ? null : workflow.workflow_variables.map((variable, varindex) => { return ( - + ); - })} + })}
    - + + - const executionArgumentModal = - { }} > - + { + e.preventDefault(); + setExecutionArgumentModalOpen(false) + }} > - { - e.preventDefault(); - setExecutionArgumentModalOpen(false) - }} - > - - - - - Provide an execution argument - - + + + + + Provide an execution argument + + - {workflow.input_questions !== undefined && workflow.input_questions !== null && workflow.input_questions.length > 0 ? -
    - {workflow.input_questions.map((question, index) => { + {workflow.input_questions !== undefined && workflow.input_questions !== null && workflow.input_questions.length > 0 ? +
    + {workflow.input_questions.map((question, index) => { - return ( -
    - {question.name} - { - var newtext = {} - if (executionText.length > 0) { - try { - newtext = JSON.parse(executionText) - // Check if list or object, then make it object only - if (Array.isArray(newtext)) { - newtext = {} - } - } catch (e) { - console.log("Error parsing JSON: ", e) - } - } + return ( +
    + {question.name} + { + var newtext = {} + if (executionText.length > 0) { + try { + newtext = JSON.parse(executionText) + // Check if list or object, then make it object only + if (Array.isArray(newtext)) { + newtext = {} + } + } catch (e) { + console.log("Error parsing JSON: ", e) + } + } - newtext[question.value] = e.target.value - setExecutionText(JSON.stringify(newtext)) - }} - /> -
    - ) - })} + newtext[question.value] = e.target.value + setExecutionText(JSON.stringify(newtext)) + }} + /> +
    + ) + })} - -
    - : -
    - - At least one node in this workflow requires an execution argument ($exec). Please select one below, or provide a custom one in the text field next to the run button. - + +
    + : +
    + + At least one node in this workflow requires an execution argument ($exec). Please select one below, or provide a custom one in the text field next to the run button. + - - {availableArguments.length > 0 ? -
    - - Previously used arguments: - - {availableArguments.map((data) => { - return ( - { - setExecutionText(data) - executeWorkflow(data, workflow.start, lastSaved); + + {availableArguments.length > 0 ? +
    + + Previously used arguments: + + {availableArguments.map((data) => { + return ( + { + setExecutionText(data) + executeWorkflow(data, workflow.start, lastSaved); - setExecutionArgumentModalOpen(false) - }} - > -
    - - {data} - - - ) - })} -
    - : null} + setExecutionArgumentModalOpen(false) + }} + > +
    + + {data} + + + ) + })} +
    + : null} - -
    - } - + +
    + } +
    const submitQueryModal = () => { - const changeActionTextfield = document.getElementById("change-action-textfield") - if (changeActionTextfield === undefined || changeActionTextfield === null) { - setAiQueryModalOpen(false) - toast.error("Failed to find textfield") - return - } + const changeActionTextfield = document.getElementById("change-action-textfield") + if (changeActionTextfield === undefined || changeActionTextfield === null) { + setAiQueryModalOpen(false) + toast.error("Failed to find textfield") + return + } - if (changeActionTextfield.value === undefined || changeActionTextfield.value === null || changeActionTextfield.value === "") { - toast("Please provide how you want formatting to happen") - return - } + if (changeActionTextfield.value === undefined || changeActionTextfield.value === null || changeActionTextfield.value === "") { + toast("Please provide how you want formatting to happen") + return + } - setAutocompleting(true) - if (codeEditorModalOpen === true) { - autoFormatCodemodal(changeActionTextfield.value) - } else { - aiSubmit(changeActionTextfield.value, undefined, undefined, selectedAction) - } + setAutocompleting(true) + if (codeEditorModalOpen === true) { + autoFormatCodemodal(changeActionTextfield.value) + } else { + aiSubmit(changeActionTextfield.value, undefined, undefined, selectedAction) + } } - const autoFormatCodemodal = (input) => { - if (codeEditorModalOpen !== true) { - toast.error("Code editor is not open") - return - } + const autoFormatCodemodal = (input) => { + if (codeEditorModalOpen !== true) { + toast.error("Code editor is not open") + return + } - if (editorData.name === undefined || editorData.name === null || editorData.name === "") { - toast.error("Failed to find editor field name") - return - } + if (editorData.name === undefined || editorData.name === null || editorData.name === "") { + toast.error("Failed to find editor field name") + return + } - const codeeditor = document.getElementById("shuffle-codeeditor") - if (codeeditor === undefined || codeeditor === null) { - toast.error("Failed to find code editor html") - return - } + const codeeditor = document.getElementById("shuffle-codeeditor") + if (codeeditor === undefined || codeeditor === null) { + toast.error("Failed to find code editor html") + return + } - const editorInstance = window?.ace?.edit("shuffle-codeeditor") - if (editorInstance === undefined || editorInstance === null) { - toast.error("Failed to find code editor instance") - return - } + const editorInstance = window?.ace?.edit("shuffle-codeeditor") + if (editorInstance === undefined || editorInstance === null) { + toast.error("Failed to find code editor instance") + return + } - //console.log("ACE data: ", editorInstance.getValue()) - //editorInstance.setValue("HELO") + //console.log("ACE data: ", editorInstance.getValue()) + //editorInstance.setValue("HELO") - // Should try to automatically fix this input - console.log("Running AI input fixer: ", selectedResult) - if (aiSubmit === undefined || selectedAction === undefined) { - toast.error("Failed to find AI submit function") - return - } - - // Should remove params from selectedAction that aren't parameterName - var tmpAction = JSON.parse(JSON.stringify(selectedAction)) - var tmpParams = tmpAction.parameters.filter((param) => param.name === editorData.name) - if (tmpParams.length !== 1) { - toast.error("Failed to find correct parameter in action") - return - } + // Should try to automatically fix this input + console.log("Running AI input fixer: ", selectedResult) + if (aiSubmit === undefined || selectedAction === undefined) { + toast.error("Failed to find AI submit function") + return + } - tmpParams[0].value = editorInstance.getValue() - tmpAction.parameters = tmpParams - aiSubmit(input, undefined, undefined, tmpAction) - } + // Should remove params from selectedAction that aren't parameterName + var tmpAction = JSON.parse(JSON.stringify(selectedAction)) + var tmpParams = tmpAction.parameters.filter((param) => param.name === editorData.name) + if (tmpParams.length !== 1) { + toast.error("Failed to find correct parameter in action") + return + } - const aiQueryModal = + tmpParams[0].value = editorInstance.getValue() + tmpAction.parameters = tmpParams + aiSubmit(input, undefined, undefined, tmpAction) + } + + const aiQueryModal = { - setAiQueryModalOpen(false) + setAiQueryModalOpen(false) }} > - + { + }} > - { - }} - > - - - - { - setAiQueryModalOpen(false) - }} - > - - - - Shuffle AI - - - What you write here will be fed to the Shuffle AI to generate a change for the selected action or field. Best used for when you are stuck with formatting. Uses your AI credits (resets monthly). Alpha feature. Please give feedback to support@shuffler.io {"<"}3 + + + + { + setAiQueryModalOpen(false) + }} + > + + + + Shuffle AI + + + What you write here will be fed to the Shuffle AI to generate a change for the selected action or field. Best used for when you are stuck with formatting. Uses your AI credits (resets monthly). Alpha feature. Please give feedback to support@shuffler.io {"<"}3 - - - - - ), - onKeyPress: (e) => { - if (e.key === "Enter" && !e.shiftKey) { - submitQueryModal() - } - }, - }} + + + + + ), + onKeyPress: (e) => { + if (e.key === "Enter" && !e.shiftKey) { + submitQueryModal() + } + }, + }} - /> + /> @@ -12431,8 +12480,8 @@ const releaseToConnectLabel = "Release to Connect" minWidth: isMobile ? "90%" : 800, border: theme.palette.defaultBorder, - borderRadius: theme.palette.borderRadius, - backgroundColor: "black", + borderRadius: theme.palette.borderRadius, + backgroundColor: "black", }, }} onClose={() => { @@ -12444,7 +12493,7 @@ const releaseToConnectLabel = "Release to Connect" bottom: 10, left: 10, color: "rgba(255,255,255,0.6)", - zIndex: 10000, + zIndex: 10000, }} > Conditions can't be used for loops [ .# ]{" "} @@ -12452,10 +12501,10 @@ const releaseToConnectLabel = "Release to Connect" rel="noopener noreferrer" target="_blank" href="/docs/workflows#conditions" - style={{ - textDecoration: "none", - color: "#FF8544", - }} + style={{ + textDecoration: "none", + color: "#FF8544", + }} > Learn more @@ -12923,25 +12972,25 @@ const releaseToConnectLabel = "Release to Connect" }); } - // Startnode = dest node - const conditionsDisabled = false + // Startnode = dest node + const conditionsDisabled = false const conditionId = uuidv4(); return (
    - +
    +

    + Conditions +

    + + What are conditions? + +
    - {/* Check if dest is the same as start */} - {conditionsDisabled ? - - Conditions are unavailable between triggers and the startnode. - - : null} + {/* Check if dest is the same as start */} + {conditionsDisabled ? + + Conditions are unavailable between triggers and the startnode. + + : null} -
    - - - {/* + {/* -
    + +
    ); }; - const handleWorkflowSelectionUpdate = (e, isUserinput) => { + const handleWorkflowSelectionUpdate = (e, isUserinput) => { - if (e.target.value === undefined || e.target.value === null || e.target.value.id === undefined) { - console.log("Returning as there's no id. Value: ", e.target.value); - return null - } + if (e.target.value === undefined || e.target.value === null || e.target.value.id === undefined) { + console.log("Returning as there's no id. Value: ", e.target.value); + return null + } - const paramIndex = isUserinput === true ? 5 : 0 + const paramIndex = isUserinput === true ? 5 : 0 - console.log("USERINPUT: ", paramIndex, workflow.triggers[selectedTriggerIndex]) - if (workflow.triggers[selectedTriggerIndex].parameters[paramIndex] === undefined || workflow.triggers[selectedTriggerIndex].parameters[paramIndex] === null) { - workflow.triggers[selectedTriggerIndex].parameters[paramIndex] = { - "name": "subflow", - "value": "", - } - } + console.log("USERINPUT: ", paramIndex, workflow.triggers[selectedTriggerIndex]) + if (workflow.triggers[selectedTriggerIndex].parameters[paramIndex] === undefined || workflow.triggers[selectedTriggerIndex].parameters[paramIndex] === null) { + workflow.triggers[selectedTriggerIndex].parameters[paramIndex] = { + "name": "subflow", + "value": "", + } + } - setUpdate(Math.random()); - workflow.triggers[selectedTriggerIndex].parameters[paramIndex].value = e.target.value.id; - setSubworkflow(e.target.value); + setUpdate(Math.random()); + workflow.triggers[selectedTriggerIndex].parameters[paramIndex].value = e.target.value.id; + setSubworkflow(e.target.value); - // Sets the startnode - if (e.target.value.id !== workflow.id && e.target.value.id.length > 0 ) { + // Sets the startnode + if (e.target.value.id !== workflow.id && e.target.value.id.length > 0) { - const startnode = e?.target?.value?.actions?.find((action) => action.id === e.target.value.start); - + const startnode = e?.target?.value?.actions?.find((action) => action.id === e.target.value.start); - if (startnode !== undefined && startnode !== null) { - setSubworkflowStartnode(startnode); - if (paramIndex === 0) { - try { - workflow.triggers[selectedTriggerIndex].parameters[3].value = startnode.id; - } catch { - workflow.triggers[selectedTriggerIndex].parameters[3] = { - name: "startnode", - value: startnode.id, - }; - } - } + if (startnode !== undefined && startnode !== null) { + setSubworkflowStartnode(startnode); - //setWorkflow(workflow); - } - } else { - console.log("WORKFLOW: ", workflow); - } + if (paramIndex === 0) { + try { + workflow.triggers[selectedTriggerIndex].parameters[3].value = startnode.id; + } catch { + workflow.triggers[selectedTriggerIndex].parameters[3] = { + name: "startnode", + value: startnode.id, + }; + } + } - setWorkflow(workflow); - } + //setWorkflow(workflow); + } + } else { + console.log("WORKFLOW: ", workflow); + } + + setWorkflow(workflow); + } // Function to transform the data const transformAuthData = (authData) => { const transformedData = {}; @@ -13170,7 +13219,7 @@ const releaseToConnectLabel = "Release to Connect" }) appIdsInWorkflow = [...new Set(appIdsInWorkflow)]; - + // loop through the authData and create transformedData which looks like: // appId: [auth1, auth2, ...] authData.forEach((auth) => { @@ -13189,7 +13238,7 @@ const releaseToConnectLabel = "Release to Connect" }); return transformedData; - + }; const AppAuthSelector = ({ appAuthData }) => { @@ -13214,7 +13263,7 @@ const releaseToConnectLabel = "Release to Connect" if (mappingWithName[appName] !== undefined) { return mappingWithName[appName]; } - + return "no-overrides"; } @@ -13223,10 +13272,10 @@ const releaseToConnectLabel = "Release to Connect" if (authId === "no-override") { // remove the override parameter - let oldValue = workflow.triggers[selectedTriggerIndex].parameters[5].value; + let oldValue = workflow.triggers[selectedTriggerIndex].parameters[5].value; // replace from appName= to the next ; let newValue = oldValue.replace(new RegExp(appName + "=[^;]*;"), ""); - + workflow.triggers[selectedTriggerIndex].parameters[5].value = newValue setSelectedAuth(""); return @@ -13249,19 +13298,19 @@ const releaseToConnectLabel = "Release to Connect" // return; // } // } - - if (workflow.triggers[selectedTriggerIndex].parameters[5] === undefined || workflow.triggers[selectedTriggerIndex].parameters[5] === null) { - workflow.triggers[selectedTriggerIndex].parameters[5] = { - name: "auth_override", - value: "", - }; - } - - let authGroupValue = workflow.triggers[selectedTriggerIndex].parameters[5].value; - if (authGroupValue === undefined || authGroupValue === null || authGroupValue === "") { + if (workflow.triggers[selectedTriggerIndex].parameters[5] === undefined || workflow.triggers[selectedTriggerIndex].parameters[5] === null) { + workflow.triggers[selectedTriggerIndex].parameters[5] = { + name: "auth_override", + value: "", + }; + } + + let authGroupValue = workflow.triggers[selectedTriggerIndex].parameters[5].value; + + if (authGroupValue === undefined || authGroupValue === null || authGroupValue === "") { workflow.triggers[selectedTriggerIndex].parameters[5].value = appName + "=" + auth.id + ";"; - } else { + } else { // check if the app is already in the list if (authGroupValue.includes(appName)) { let oldValue = workflow.triggers[selectedTriggerIndex].parameters[5].value; @@ -13270,7 +13319,7 @@ const releaseToConnectLabel = "Release to Connect" } else { workflow.triggers[selectedTriggerIndex].parameters[5].value += appName + "=" + auth.id + ";"; } - } + } // workflow.triggers[selectedTriggerIndex].parameters.push({ // name: auth.label + "_" + auth.app.id + "_override", @@ -13280,892 +13329,878 @@ const releaseToConnectLabel = "Release to Connect" } return ( -
    - {Object.entries(transformedAuthData).map(([appId, authList]) => { - if (authList === undefined || authList === null || authList.length < 2) { - return null; - } +
    + {Object.entries(transformedAuthData).map(([appId, authList]) => { + if (authList === undefined || authList === null || authList.length < 2) { + return null; + } - return ( -
    - - handleSelectChange(authList[0].app.name, authList[0].app.id, e)} + className="auth-select" style={{ + width: '100%', + padding: '10px', + fontSize: '16px', + borderRadius: '4px', + border: '1px solid #555', backgroundColor: theme.palette.inputColor, - fontSize: "1.2em", + color: '#E8E8E8', + boxShadow: '0 2px 4px rgba(0, 0, 0, 0.2)', + transition: 'border-color 0.2s, box-shadow 0.2s', }} + onFocus={(e) => e.target.style.borderColor = '#007BFF'} + onBlur={(e) => e.target.style.borderColor = '#555'} > - {auth.label} - - )} - -
    - )})} -
    + + {authList.flatMap((auth) => + + )} + +
    + ) + })} +
    ); }; - const iconStyle = { - marginRight: 15, - }; + const iconStyle = { + marginRight: 15, + }; - - if (Object.getOwnPropertyNames(selectedTrigger)?.length > 0) { - if (workflow.triggers[selectedTriggerIndex] === undefined) { - return null; - } - if ( - workflow.triggers[selectedTriggerIndex].parameters === undefined || - workflow.triggers[selectedTriggerIndex].parameters === null || - workflow.triggers[selectedTriggerIndex].parameters.length === 0 - ) { - workflow.triggers[selectedTriggerIndex].parameters = []; - workflow.triggers[selectedTriggerIndex].parameters[0] = { - name: "workflow", - value: "", - }; - workflow.triggers[selectedTriggerIndex].parameters[1] = { - name: "argument", - value: "", - }; - workflow.triggers[selectedTriggerIndex].parameters[2] = { - name: "user_apikey", - value: "", - }; - workflow.triggers[selectedTriggerIndex].parameters[3] = { - name: "startnode", - value: "", - }; - workflow.triggers[selectedTriggerIndex].parameters[4] = { - name: "check_result", - value: "false", - }; - workflow.triggers[selectedTriggerIndex].parameters[5] = { - name: "auth_override", - value: "", - }; - - /* - // API-key has been replaced by auth key for the execution. - // Parents can now automatically execute children without auth from a user, as long as the subflow in question is owned by the same org and the subflow is actually referencing it during checkin. - console.log("SETTINGS: ", userSettings); - if ( - userSettings !== undefined && - userSettings !== null && - userSettings.apikey !== null && - userSettings.apikey !== undefined && - userSettings.apikey.length > 0 - ) { - workflow.triggers[selectedTriggerIndex].parameters[2] = { - name: "user_apikey", - value: userSettings.apikey, - }; - } - */ - } - - var handleSubflowStartnodeSelection = (e) => { - setSubworkflowStartnode(e.target.value); - - if (e.target.value === null || e.target.value === undefined) { - return - } - - const branchId = uuidv4(); - const newbranch = { - source_id: workflow.triggers[selectedTriggerIndex].id, - destination_id: e.target.value.id, - source: workflow.triggers[selectedTriggerIndex].id, - target: e.target.value.id, - has_errors: false, - id: branchId, - _id: branchId, - label: "Subflow", - decorator: true, - }; - - if (workflow.visual_branches !== undefined) { - if (workflow.visual_branches === null) { - workflow.visual_branches = [newbranch]; - } else if (workflow.visual_branches.length === 0) { - workflow.visual_branches.push(newbranch); - } else { - const foundIndex = workflow.visual_branches.findIndex( - (branch) => branch.source_id === newbranch.source_id - ); - if (foundIndex !== -1) { - const currentEdge = cy.getElementById( - workflow.visual_branches[foundIndex].id - ); - if ( - currentEdge !== undefined && - currentEdge !== null - ) { - currentEdge.remove(); - } - } - - workflow.visual_branches.splice(foundIndex, 1); - workflow.visual_branches.push(newbranch); - } - } - - if (workflow.id === subworkflow.id) { - const cybranch = { - group: "edges", - source: newbranch.source_id, - target: newbranch.destination_id, - id: branchId, - data: newbranch, - }; - - cy.add(cybranch); - } - - console.log("Value to be set: ", e.target.value); - try { - workflow.triggers[ - selectedTriggerIndex - ].parameters[3].value = e.target.value.id; - } catch { - workflow.triggers[selectedTriggerIndex].parameters[3] = - { - name: "startnode", - value: e.target.value.id, - }; - } - - setWorkflow(workflow); - } + if (Object.getOwnPropertyNames(selectedTrigger)?.length > 0) { + if (workflow.triggers[selectedTriggerIndex] === undefined) { + return null; } - const handleMenuClose = () => { - setUpdate(Math.random()); - setMenuPosition(null); - }; + if ( + workflow.triggers[selectedTriggerIndex].parameters === undefined || + workflow.triggers[selectedTriggerIndex].parameters === null || + workflow.triggers[selectedTriggerIndex].parameters.length === 0 + ) { + workflow.triggers[selectedTriggerIndex].parameters = []; + workflow.triggers[selectedTriggerIndex].parameters[0] = { + name: "workflow", + value: "", + }; + workflow.triggers[selectedTriggerIndex].parameters[1] = { + name: "argument", + value: "", + }; + workflow.triggers[selectedTriggerIndex].parameters[2] = { + name: "user_apikey", + value: "", + }; + workflow.triggers[selectedTriggerIndex].parameters[3] = { + name: "startnode", + value: "", + }; + workflow.triggers[selectedTriggerIndex].parameters[4] = { + name: "check_result", + value: "false", + }; + workflow.triggers[selectedTriggerIndex].parameters[5] = { + name: "auth_override", + value: "", + }; - const handleItemClick = (values) => { - console.log("VALUES: ", values) - if (values === undefined || values === null || values.length === 0) { - return; - } + } + var handleSubflowStartnodeSelection = (e) => { + setSubworkflowStartnode(e.target.value); - /* - workflow.triggers[selectedTriggerIndex].parameters[1].value - .trim() - .endsWith("$") - ? values[0].autocomplete - : "$" + values[0].autocomplete; - - for (var key in values) { - if (key === 0 || values[key].autocomplete.length === 0) { - continue; - } - - toComplete += values[key].autocomplete - } - */ - - if (selectedTrigger.name === "Shuffle Workflow") { - const toComplete = workflow?.triggers?.[selectedTriggerIndex]?.parameters?.[1]?.value + "$" + values[0]?.autocomplete - // selectedTrigger.parameters[1].value = toComplete - workflow.triggers[selectedTriggerIndex].parameters[1].value = toComplete - const foundfield = document.getElementById("subflow_exec_field") - if (foundfield !== undefined && foundfield !== null) { - foundfield.value = toComplete - } - setWorkflow(workflow) - } - - setUpdate(Math.random()); - setShowDropdown(false); - setMenuPosition(null); - }; - - const subflowtypes = [ - { - name: "Any", - }, - { - name: "Enrich", - } - ] - - const handleSubflowParamChange = (value) => { - - if (!workflow?.triggers || !workflow.triggers[selectedTriggerIndex]?.parameters) { - console.log("Required workflow properties are undefined") + if (e.target.value === null || e.target.value === undefined) { return } - if (!workflow.triggers[selectedTriggerIndex].parameters[1]) { - workflow.triggers[selectedTriggerIndex].parameters[1] = { - name: "execution_argument", - value: "" + const branchId = uuidv4(); + const newbranch = { + source_id: workflow.triggers[selectedTriggerIndex].id, + destination_id: e.target.value.id, + source: workflow.triggers[selectedTriggerIndex].id, + target: e.target.value.id, + has_errors: false, + id: branchId, + _id: branchId, + label: "Subflow", + decorator: true, + }; + + if (workflow.visual_branches !== undefined) { + if (workflow.visual_branches === null) { + workflow.visual_branches = [newbranch]; + } else if (workflow.visual_branches.length === 0) { + workflow.visual_branches.push(newbranch); + } else { + const foundIndex = workflow.visual_branches.findIndex( + (branch) => branch.source_id === newbranch.source_id + ); + + if (foundIndex !== -1) { + const currentEdge = cy.getElementById( + workflow.visual_branches[foundIndex].id + ); + if ( + currentEdge !== undefined && + currentEdge !== null + ) { + currentEdge.remove(); + } + } + + workflow.visual_branches.splice(foundIndex, 1); + workflow.visual_branches.push(newbranch); } } - workflow.triggers[selectedTriggerIndex].parameters[1].value = value - setWorkflow(workflow) - setLastSaved(false) + if (workflow.id === subworkflow.id) { + const cybranch = { + group: "edges", + source: newbranch.source_id, + target: newbranch.destination_id, + id: branchId, + data: newbranch, + }; + + cy.add(cybranch); + } + + console.log("Value to be set: ", e.target.value); + try { + workflow.triggers[ + selectedTriggerIndex + ].parameters[3].value = e.target.value.id; + } catch { + workflow.triggers[selectedTriggerIndex].parameters[3] = + { + name: "startnode", + value: e.target.value.id, + }; + } + + setWorkflow(workflow); + } + } + + const handleMenuClose = () => { + setUpdate(Math.random()); + setMenuPosition(null); + }; + + const handleItemClick = (values) => { + console.log("VALUES: ", values) + if (values === undefined || values === null || values.length === 0) { + return; } - const SubflowSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined || selectedTrigger.trigger_type !== "SUBFLOW" ? null : -
    - -

    - {selectedTrigger.app_name} -

    - - - -
    - - What are subflows? - - { + + if (!workflow?.triggers || !workflow.triggers[selectedTriggerIndex]?.parameters) { + console.log("Required workflow properties are undefined") + return + } + + if (!workflow.triggers[selectedTriggerIndex].parameters[1]) { + workflow.triggers[selectedTriggerIndex].parameters[1] = { + name: "execution_argument", + value: "" + } + } + + workflow.triggers[selectedTriggerIndex].parameters[1].value = value + setWorkflow(workflow) + setLastSaved(false) + } + + const SubflowSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined || selectedTrigger.trigger_type !== "SUBFLOW" ? null : +
    + +

    + {selectedTrigger.app_name} +

    + + + +
    + + What are subflows? + + +
    +
    + Name + +
    +
    +
    + + + Delay + { - if (data.id === workflow.id) { - data = workflow; + InputProps={{ + style: { + color: "white" + } + }} + size="small" + placeholder={selectedTrigger.execution_delay} + defaultValue={selectedTrigger?.execution_delay || 0} + onChange={(event) => { + if (isNaN(event.target.value)) { + console.log("NAN: ", event.target.value) + return } - //key={index} - return ( - - {data.image !== undefined && data.image !== null && data.image.length > 0 ? - {data.name} - : null} - - Choose Subflow '{data.name}' - - - }> - { - getWorkflowApps(data.id); - handleWorkflowSelectionUpdate({ - target: { - value: data - } - }) - document.activeElement.blur(); - }} - > - - {data.name} - - - ) - }} - renderInput={(params) => { - return ( - - ); + const parsedNumber = parseInt(event.target.value) + if (parsedNumber > 86400) { + console.log("Max number is 1 day (86400)") + return + } + + selectedTrigger.execution_delay = parseInt(event.target.value) + setSelectedTrigger(selectedTrigger) }} /> - )} + + +
    +
    +
    + { + const newvalue = workflow.triggers[selectedTriggerIndex].parameters[4] === undefined || workflow.triggers[selectedTriggerIndex].parameters[4].value === "false" ? "true" : "false"; + workflow.triggers[selectedTriggerIndex].parameters[4] = { + name: "check_result", + value: newvalue, + }; - {subworkflow === undefined || - subworkflow === null || - subworkflow.id === undefined || - subworkflow.actions === null || - subworkflow.actions === undefined || - subworkflow.actions.length === 0 ? null : ( - -
    -
    - Select the Startnode -
    -
    - option.id === value.id} - getOptionLabel={(option) => { - if (option === undefined || option === null || option.label === undefined || option.label === null) { - if (option.length === 36) { + setWorkflow(workflow); + setUpdate(Math.random()); + }} + color="primary" + value="Wait for results" + /> + } + style={{ marginTop: 10 }} + label={
    Wait for results
    } + /> +
    +
    +
    +
    +
    + Select a workflow to execute +
    +
    + {workflow.triggers[selectedTriggerIndex].parameters[0].value + .length === 0 ? null : workflow.triggers[selectedTriggerIndex] + .parameters[0].value === props.match.params.key ? null : ( +
    + + + +
    + )} +
    - } + {workflows === undefined || + workflows === null || + workflows.length === 0 ? null : ( - return "Default"; + option.id === value.id} + getOptionLabel={(option) => { + if ( + option === undefined || + option === null || + option.name === undefined || + option.name === null + ) { + return "No Workflow Selected"; + } + + const newname = ( + option.name.charAt(0).toUpperCase() + option.name.substring(1) + ).replaceAll("_", " "); + return newname; + }} + options={workflows} + fullWidth + style={{ + backgroundColor: theme.palette.inputColor, + borderRadius: theme.palette?.borderRadius, + }} + onChange={(event, newValue) => { + setLastSaved(false) + console.log("Found value: ", newValue) + + var parsedinput = { target: { value: newValue } } + + // For variables + if (typeof newValue === 'string' && newValue.startsWith("$")) { + parsedinput = { + target: { + value: { + "name": newValue, + "id": newValue, + "actions": [], + "triggers": [], } + } + } + } - const newname = ( - option.label.charAt(0).toUpperCase() + option.label.substring(1) - ).replaceAll("_", " "); - return newname; - }} - options={subworkflow.actions} - fullWidth - style={{ - backgroundColor: theme.palette.inputColor, - height: 50, - borderRadius: theme.palette?.borderRadius, - }} - onChange={(event, newValue) => { - setLastSaved(false) - handleSubflowStartnodeSelection({ target: { value: newValue } }) - }} - renderOption={(props, action, state) => { - const isParent = getParents(selectedTrigger).find( - (parent) => parent.id === action.id - ) + handleWorkflowSelectionUpdate(parsedinput) + }} + renderOption={(props, data, state) => { + if (data.id === workflow.id) { + data = workflow; + } - return ( - { - if (subworkflow.id === workflow.id) { - handleActionHover(true, action.id) - } - }} - onMouseOut={() => { - if (subworkflow.id === workflow.id) { - handleActionHover(false, action.id) - } - }} - disabled={isCloud && isParent} - onClick={() => { - handleSubflowStartnodeSelection({ - target: { - value: action - } - }) - document.activeElement.blur() - }} - style={{ - backgroundColor: theme.palette.inputColor, - color: isParent ? "red" : "white", - }} - value={action} - > - {action.label} - - ); - }} - renderInput={(params) => { - return ( - - ); - }} + //key={index} + return ( + + {data.image !== undefined && data.image !== null && data.image.length > 0 ? + {data.name} + : null} + + Choose Subflow '{data.name}' + + + }> + { + getWorkflowApps(data.id); + handleWorkflowSelectionUpdate({ + target: { + value: data + } + }) + document.activeElement.blur(); + }} + > + + {data.name} + + + ) + }} + renderInput={(params) => { + return ( + - - )} + ); + }} + /> + )} + + {subworkflow === undefined || + subworkflow === null || + subworkflow.id === undefined || + subworkflow.actions === null || + subworkflow.actions === undefined || + subworkflow.actions.length === 0 ? null : ( +
    -
    - Execution Argument - - { - event.preventDefault() - setCodeEditorModalOpen(true) - setActiveDialog("codeeditor") - var parsedvalue = workflow?.triggers[selectedTriggerIndex]?.parameters[1]?.value - - setEditorData({ - "name": workflow.triggers[selectedTriggerIndex].parameters[1].name, - "value": parsedvalue, - "field_number": 1, - "actionlist": subflowActionList, - "field_id": "subflow_exec_field", - }) - }} - > - - - +
    + Select the Startnode
    - - - { - setMenuPosition({ - top: event.pageY + 10, - left: event.pageX + 10, - }); - //setShowDropdownNumber(3) - setShowDropdown(true); - }} - /> - - - ), }} - rows="6" - multiline + sx={{ + '& .MuiOutlinedInput-root': { + height: 40, // Adjust the input height + }, + '& .MuiAutocomplete-input': { + padding: '8px', // Adjust the text padding + }, + }} + getOptionSelected={(option, value) => option.id === value.id} + getOptionLabel={(option) => { + if (option === undefined || option === null || option.label === undefined || option.label === null) { + if (option.length === 36) { + + } + + return "Default"; + } + + const newname = ( + option.label.charAt(0).toUpperCase() + option.label.substring(1) + ).replaceAll("_", " "); + return newname; + }} + options={subworkflow.actions} fullWidth - color="primary" - placeholder="Some execution data" - defaultValue={ - workflow?.triggers[selectedTriggerIndex]?.parameters[1]?.value - } - onChange={(e) => { - workflow.triggers[selectedTriggerIndex].parameters[1].value = e.target.value - setWorkflow(workflow) + style={{ + backgroundColor: theme.palette.inputColor, + borderRadius: theme.palette?.borderRadius, + }} + onChange={(event, newValue) => { setLastSaved(false) + handleSubflowStartnodeSelection({ target: { value: newValue } }) + }} + renderOption={(props, action, state) => { + const isParent = getParents(selectedTrigger).find( + (parent) => parent.id === action.id + ) + + return ( + { + if (subworkflow.id === workflow.id) { + handleActionHover(true, action.id) + } + }} + onMouseOut={() => { + if (subworkflow.id === workflow.id) { + handleActionHover(false, action.id) + } + }} + disabled={isCloud && isParent} + onClick={() => { + handleSubflowStartnodeSelection({ + target: { + value: action + } + }) + document.activeElement.blur() + }} + style={{ + backgroundColor: theme.palette.inputColor, + color: isParent ? "red" : "white", + }} + value={action} + > + {action.label} + + ); + }} + renderInput={(params) => { + return ( + + ); }} /> - {!showDropdown ? null : - { - handleMenuClose(); - }} - open={!!menuPosition} - style={{ - border: `2px solid #FF8544`, - color: "white", - marginTop: 2, - }} - > - {subflowActionList.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 #FF8544"; - } else { - exec_text_field.style.border = ""; - } - } - - // Also doing arguments - if ( - workflow.triggers !== undefined && - workflow.triggers !== null && - workflow.triggers.length > 0 - ) { - for (let triggerkey in workflow.triggers) { - const item = workflow.triggers[triggerkey]; - - if (cy !== undefined) { - var node = cy.getElementById(item.id); - if (node.length > 0) { - if (inside) { - node.addClass("shuffle-hover-highlight"); - } else { - node.removeClass("shuffle-hover-highlight"); - } - } - } - } - } - } - - const handleActionHover = (inside, actionId) => { - if (cy !== undefined) { - var node = cy.getElementById(actionId); - if (node.length > 0) { - if (inside) { - node.addClass("shuffle-hover-highlight"); - } else { - node.removeClass("shuffle-hover-highlight"); - } - } - } - }; - - 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 = []; + + )} +
    +
    + Execution Argument + + { + event.preventDefault() + setCodeEditorModalOpen(true) + setActiveDialog("codeeditor") + var parsedvalue = workflow?.triggers[selectedTriggerIndex]?.parameters[1]?.value - if (innerdata.type === "workflow_variable") { - // Try to parse the value if it's a string that could be JSON - if (typeof innerdata.value === "string") { - try { - const parsedValue = JSON.parse(innerdata.value) - if (typeof parsedValue === "object") { - parsedPaths = GetParsedPaths(parsedValue, ""); - } - } catch (e) { - // Not valid JSON, use the value directly - parsedPaths = GetParsedPaths(innerdata.value, ""); - } - } else if (typeof innerdata.value === "object") { - parsedPaths = GetParsedPaths(innerdata.value, ""); - } - } else if (typeof innerdata.example === "object") { - parsedPaths = GetParsedPaths(innerdata.example, ""); + setEditorData({ + "name": workflow.triggers[selectedTriggerIndex].parameters[1].name, + "value": parsedvalue, + "field_number": 1, + "actionlist": subflowActionList, + "field_id": "subflow_exec_field", + }) + }} + > + + + +
    +
    + + + { + setMenuPosition({ + top: event.pageY + 10, + left: event.pageX + 10, + }); + //setShowDropdownNumber(3) + setShowDropdown(true); + }} + /> + + + ), + }} + rows="6" + multiline + fullWidth + color="primary" + placeholder="Some execution data" + defaultValue={ + workflow?.triggers[selectedTriggerIndex]?.parameters[1]?.value + } + onChange={(e) => { + workflow.triggers[selectedTriggerIndex].parameters[1].value = e.target.value + setWorkflow(workflow) + setLastSaved(false) + }} + /> + {!showDropdown ? null : + { + handleMenuClose(); + }} + open={!!menuPosition} + style={{ + border: `2px solid #FF8544`, + color: "white", + marginTop: 2, + }} + > + {subflowActionList.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 #FF8544"; + } else { + exec_text_field.style.border = ""; + } } - - const coverColor = "#82ccc3" - - return parsedPaths.length > 0 ? ( - + + // Also doing arguments + if ( + workflow.triggers !== undefined && + workflow.triggers !== null && + workflow.triggers.length > 0 + ) { + for (let triggerkey in workflow.triggers) { + const item = workflow.triggers[triggerkey]; + + if (cy !== undefined) { + var node = cy.getElementById(item.id); + if (node.length > 0) { + if (inside) { + node.addClass("shuffle-hover-highlight"); + } else { + node.removeClass("shuffle-hover-highlight"); + } + } + } + } + } + } + + const handleActionHover = (inside, actionId) => { + if (cy !== undefined) { + var node = cy.getElementById(actionId); + if (node.length > 0) { + if (inside) { + node.addClass("shuffle-hover-highlight"); + } else { + node.removeClass("shuffle-hover-highlight"); + } + } + } + }; + + 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 (innerdata.type === "workflow_variable") { + // Try to parse the value if it's a string that could be JSON + if (typeof innerdata.value === "string") { + try { + const parsedValue = JSON.parse(innerdata.value) + if (typeof parsedValue === "object") { + parsedPaths = GetParsedPaths(parsedValue, ""); + } + } catch (e) { + // Not valid JSON, use the value directly + parsedPaths = GetParsedPaths(innerdata.value, ""); + } + } else if (typeof innerdata.value === "object") { + parsedPaths = GetParsedPaths(innerdata.value, ""); + } + } else if (typeof innerdata.example === "object") { + parsedPaths = GetParsedPaths(innerdata.example, ""); + } + + const coverColor = "#82ccc3" + + return parsedPaths.length > 0 ? ( + {/* */} - + - - + + - + {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 baseIndent =
    + + const indentation_count = (pathdata.name.match(/\./g) || []).length + 1 + const baseIndent =
    //const boxPadding = pathdata.type === "object" ? "10px 0px 0px 0px" : 0 - const boxPadding = 0 + const boxPadding = 0 const namesplit = pathdata.name.split(".") - const newname = namesplit[namesplit.length-1] + const newname = namesplit[namesplit.length - 1] return ( { @@ -14318,9 +14353,9 @@ const releaseToConnectLabel = "Release to Connect" baseIndent ) })} - {icon} {newname} - {pathdata.type === "list" ? { - + {icon} {newname} + {pathdata.type === "list" ? { + }} /> : null}
    @@ -14329,38 +14364,38 @@ const releaseToConnectLabel = "Release to Connect" })} - - ) : ( - handleMouseover()} - onMouseOut={() => { - handleMouseOut(); - }} - onClick={() => { - handleItemClick([innerdata]); - }} + + ) : ( + handleMouseover()} + onMouseOut={() => { + handleMouseOut(); + }} + onClick={() => { + handleItemClick([innerdata]); + }} + > + - -
    - {icon} {innerdata.name} -
    -
    -
    - ); - })} -
    - } - {/* +
    + {icon} {innerdata.name} +
    + + + ); + })} +
    + } + {/*
    */} -
    -
    +
    +
    - {/* + {/*
    @@ -14416,8 +14451,8 @@ const releaseToConnectLabel = "Release to Connect"
    */} -
    - +
    + const CommentSidebar = () => { if (Object.getOwnPropertyNames(selectedComment).length > 0) { @@ -14448,15 +14483,15 @@ const releaseToConnectLabel = "Release to Connect" return (
    -

    Comment

    - - What are comments? - +

    Comment

    + + What are comments? + 0 && workflow?.triggers !== null && workflow?.triggers !== undefined && workflow?.triggers?.length >= selectedTriggerIndex && workflow?.triggers[selectedTriggerIndex] !== undefined ) { - if (selectedTrigger.trigger_type === "SCHEDULE" && workflow.triggers[selectedTriggerIndex].parameters === undefined || workflow.triggers[selectedTriggerIndex].parameters === null) { - console.log("Autofixing schedule") + if (Object.getOwnPropertyNames(selectedTrigger)?.length > 0 && workflow?.triggers !== null && workflow?.triggers !== undefined && workflow?.triggers?.length >= selectedTriggerIndex && workflow?.triggers[selectedTriggerIndex] !== undefined) { + if (selectedTrigger.trigger_type === "SCHEDULE" && workflow.triggers[selectedTriggerIndex].parameters === undefined || workflow.triggers[selectedTriggerIndex].parameters === null) { + console.log("Autofixing schedule") + workflow.triggers[selectedTriggerIndex].parameters = []; + workflow.triggers[selectedTriggerIndex].parameters[0] = { + name: "cron", + value: isCloud ? "*/25 * * * *" : "60", + }; + workflow.triggers[selectedTriggerIndex].parameters[1] = { + name: "execution_argument", + value: '{"name": "value"}', + }; + setWorkflow(workflow); + } else if (selectedTrigger.trigger_type === "WEBHOOK") { + if (workflow.triggers[selectedTriggerIndex] === undefined) { + return null; + } + + if ( + workflow.triggers[selectedTriggerIndex].parameters === undefined || + workflow.triggers[selectedTriggerIndex].parameters === null || + workflow.triggers[selectedTriggerIndex].parameters.length === 0 + ) { workflow.triggers[selectedTriggerIndex].parameters = []; workflow.triggers[selectedTriggerIndex].parameters[0] = { - name: "cron", - value: isCloud ? "*/25 * * * *" : "60", + name: "url", + value: referenceUrl + "webhook_" + selectedTrigger.id, }; workflow.triggers[selectedTriggerIndex].parameters[1] = { - name: "execution_argument", - value: '{"name": "value"}', + name: "tmp", + value: "webhook_" + selectedTrigger.id, + }; + workflow.triggers[selectedTriggerIndex].parameters[2] = { + name: "auth_headers", + value: "", + }; + workflow.triggers[selectedTriggerIndex].parameters[3] = { + name: "custom_response_body", + value: "", + }; + workflow.triggers[selectedTriggerIndex].parameters[4] = { + name: "await_response", + value: "v1", }; setWorkflow(workflow); - } else if (selectedTrigger.trigger_type === "WEBHOOK") { - if (workflow.triggers[selectedTriggerIndex] === undefined) { - return null; - } - - if ( - workflow.triggers[selectedTriggerIndex].parameters === undefined || - workflow.triggers[selectedTriggerIndex].parameters === null || - workflow.triggers[selectedTriggerIndex].parameters.length === 0 - ) { - workflow.triggers[selectedTriggerIndex].parameters = []; - workflow.triggers[selectedTriggerIndex].parameters[0] = { - name: "url", - value: referenceUrl + "webhook_" + selectedTrigger.id, - }; - workflow.triggers[selectedTriggerIndex].parameters[1] = { - name: "tmp", - value: "webhook_" + selectedTrigger.id, - }; - workflow.triggers[selectedTriggerIndex].parameters[2] = { - name: "auth_headers", - value: "", - }; - workflow.triggers[selectedTriggerIndex].parameters[3] = { - name: "custom_response_body", - value: "", - }; - workflow.triggers[selectedTriggerIndex].parameters[4] = { - name: "await_response", - value: "v1", - }; - setWorkflow(workflow); - } else { - // Always update - const newUrl = referenceUrl + "webhook_" + selectedTrigger.id; - //console.log("Validating webhook url: ", newUrl); - if (selectedTrigger.environment !== "cloud") { - if (newUrl !== workflow.triggers[selectedTriggerIndex].parameters[0].value) { - console.log("Url is wrong. NOT updating because of hybrid."); - //workflow.triggers[selectedTriggerIndex].parameters[0].value = newUrl; - //setWorkflow(workflow); - } - } - } - - trigger_header_auth = - workflow.triggers[selectedTriggerIndex].parameters.length > 2 - ? workflow.triggers[selectedTriggerIndex].parameters[2].value - : ""; - }else if( - selectedTrigger.trigger_type === "USERINPUT" - ){ - if ( - workflow.triggers[selectedTriggerIndex].parameters === undefined || - workflow.triggers[selectedTriggerIndex].parameters === null || - workflow?.triggers[selectedTriggerIndex]?.parameters?.length === 0 - ) { - workflow.triggers[selectedTriggerIndex].parameters = []; - workflow.triggers[selectedTriggerIndex].parameters[0] = { - name: "alertinfo", - value: "Do you want to continue the workflow? Start parameters: $exec", - }; - - // boolean, - workflow.triggers[selectedTriggerIndex].parameters[1] = { - name: "options", - value: "boolean", - }; - - // email,sms,app ... - workflow.triggers[selectedTriggerIndex].parameters[2] = { - name: "type", - value: "subflow", - }; - - workflow.triggers[selectedTriggerIndex].parameters[3] = { - name: "email", - value: "test@test.com", - }; - workflow.triggers[selectedTriggerIndex].parameters[4] = { - name: "sms", - value: "0000000", - }; - workflow.triggers[selectedTriggerIndex].parameters[5] = { - name: "subflow", - value: "", - }; - - setWorkflow(workflow); + } else { + // Always update + const newUrl = referenceUrl + "webhook_" + selectedTrigger.id; + //console.log("Validating webhook url: ", newUrl); + if (selectedTrigger.environment !== "cloud") { + if (newUrl !== workflow.triggers[selectedTriggerIndex].parameters[0].value) { + console.log("Url is wrong. NOT updating because of hybrid."); + //workflow.triggers[selectedTriggerIndex].parameters[0].value = newUrl; + //setWorkflow(workflow); + } } } + + trigger_header_auth = + workflow.triggers[selectedTriggerIndex].parameters.length > 2 + ? workflow.triggers[selectedTriggerIndex].parameters[2].value + : ""; + } else if ( + selectedTrigger.trigger_type === "USERINPUT" + ) { + if ( + workflow.triggers[selectedTriggerIndex].parameters === undefined || + workflow.triggers[selectedTriggerIndex].parameters === null || + workflow?.triggers[selectedTriggerIndex]?.parameters?.length === 0 + ) { + workflow.triggers[selectedTriggerIndex].parameters = []; + workflow.triggers[selectedTriggerIndex].parameters[0] = { + name: "alertinfo", + value: "Do you want to continue the workflow? Start parameters: $exec", + }; + + // boolean, + workflow.triggers[selectedTriggerIndex].parameters[1] = { + name: "options", + value: "boolean", + }; + + // email,sms,app ... + workflow.triggers[selectedTriggerIndex].parameters[2] = { + name: "type", + value: "subflow", + }; + + workflow.triggers[selectedTriggerIndex].parameters[3] = { + name: "email", + value: "test@test.com", + }; + workflow.triggers[selectedTriggerIndex].parameters[4] = { + name: "sms", + value: "0000000", + }; + workflow.triggers[selectedTriggerIndex].parameters[5] = { + name: "subflow", + value: "", + }; + + setWorkflow(workflow); + } + } } - const WebhookSidebar =!selectedTrigger || Object.getOwnPropertyNames(selectedTrigger)?.length === 0 || !workflow?.triggers || workflow?.triggers[selectedTriggerIndex] === undefined || selectedTrigger?.trigger_type !== "WEBHOOK" ? null : -
    -

    - {selectedTrigger.app_name}: {selectedTrigger.status} -

    - - What are webhooks? - - +

    + {selectedTrigger.app_name}: {selectedTrigger.status} +

    + + What are webhooks? + + +
    Name
    + + {apps !== undefined && apps !== null && apps.length > 0 ? +
    + { + const lowercaseValue = inputValue.toLowerCase() + options = options.filter(x => x.name.replaceAll("_", " ").toLowerCase().includes(lowercaseValue) || x.description.toLowerCase().includes(lowercaseValue)) + + return options + }} + getOptionLabel={(option) => { + if ( + option === undefined || + option === null || + option.name === undefined || + option.name === null + ) { + return null; + } + + const newname = ( + option.name.charAt(0).toUpperCase() + option.name.substring(1) + ).replaceAll("_", " "); + + return newname; + }} + options={sortByKey(apps, "name")} + fullWidth style={{ - marginBottom: "10px", - marginTop: "10px", - height: "1px", - width: "100%", - backgroundColor: "rgb(91, 96, 100)", + backgroundColor: theme.palette.inputColor, + borderRadius: theme.palette?.borderRadius, + }} + onChange={(event, newValue) => { + // Workaround with event lol + if (newValue !== undefined && newValue !== null) { + var parsedvalue = JSON.parse(JSON.stringify(newValue)) + parsedvalue.actions = [] + parsedvalue.authentication = {} + selectedTrigger.app_association = parsedvalue + setUpdate(Math.random()); + } + }} + renderOption={(props, app, state) => { + var appname = app.name.replaceAll("_", " ") + appname = appname.charAt(0).toUpperCase() + appname.substring(1) + + return ( + + { + const newValue = app + + if (newValue !== undefined && newValue !== null) { + var parsedvalue = JSON.parse(JSON.stringify(newValue)) + parsedvalue.actions = [] + parsedvalue.authentication = {} + selectedTrigger.app_association = parsedvalue + selectedTrigger.large_image = app.large_image + + if (cy !== undefined && cy !== null) { + const foundnode = cy.getElementById(selectedTrigger.id) + if (foundnode !== undefined && foundnode !== null) { + foundnode.data("large_image", app.large_image) + } + } + + setUpdate(Math.random()); + } + document.activeElement.blur(); + }} + > +
    + + {appname} + + + {appname} + +
    +
    +
    + ) + }} + renderInput={(params) => { + return ( + + ); }} /> -
    Name
    - + : null} + + {selectedTrigger.status === "running" ? null : +
    + Environment + +
    + } + +
    +
    + Parameters +
    +
    +
    + Webhook URI +
    +
    + { + }} + helperText={ + workflow.triggers[selectedTriggerIndex].parameters[0].value !== undefined && + workflow.triggers[selectedTriggerIndex].parameters[0].value !== null && + (workflow.triggers[ + selectedTriggerIndex + ].parameters[0].value.includes("localhost") || + workflow.triggers[ + selectedTriggerIndex + ].parameters[0].value.includes("127.0.0.1")) ? ( + + PS: This does NOT work with localhost. Use your local IP + instead. + + ) : null + } + InputProps={{ + style: { + }, + endAdornment: + + { + var copyText = document.getElementById("webhook_uri_field"); + if (copyText !== undefined && copyText !== null) { + console.log("NAVIGATOR: ", navigator); + const clipboard = navigator.clipboard; + if (clipboard === undefined) { + toast("Can only copy over HTTPS (port 3443)"); + return; + } + + navigator.clipboard.writeText(copyText.value); + copyText.select(); + copyText.setSelectionRange( + 0, + 99999 + ); /* For mobile devices */ + + /* Copy the text inside the text field */ + document.execCommand("copy"); + toast("Copied Webhook URL"); + } else { + console.log("Couldn't find webhook URI field: ", copyText); + } + }} + edge="end" + > + + + + }} + fullWidth + disabled + value={ + workflow.triggers[selectedTriggerIndex].parameters[0].value + } color="primary" - placeholder={selectedTrigger.label} - onChange={selectedTriggerChange} + placeholder="10" + onBlur={(e) => { + setTriggerCronWrapper(e.target.value); + }} /> - {apps !== undefined && apps !== null && apps.length > 0 ? -
    - { - const lowercaseValue = inputValue.toLowerCase() - options = options.filter(x => x.name.replaceAll("_", " ").toLowerCase().includes(lowercaseValue) || x.description.toLowerCase().includes(lowercaseValue)) - - return options - }} - getOptionLabel={(option) => { - if ( - option === undefined || - option === null || - option.name === undefined || - option.name === null - ) { - return null; - } - - const newname = ( - option.name.charAt(0).toUpperCase() + option.name.substring(1) - ).replaceAll("_", " "); - - return newname; - }} - options={sortByKey(apps, "name")} - fullWidth - style={{ - backgroundColor: theme.palette.inputColor, - height: 50, - borderRadius: theme.palette?.borderRadius, - }} - onChange={(event, newValue) => { - // Workaround with event lol - console.log("CHANGE: ", event, newValue) - if (newValue !== undefined && newValue !== null) { - var parsedvalue = JSON.parse(JSON.stringify(newValue)) - parsedvalue.actions = [] - parsedvalue.authentication = {} - selectedTrigger.app_association = parsedvalue - setUpdate(Math.random()); - } - }} - renderOption={(props, app, state) => { - var appname = app.name.replaceAll("_", " ") - appname = appname.charAt(0).toUpperCase() + appname.substring(1) - - return ( - - { - const newValue = app - - if (newValue !== undefined && newValue !== null) { - var parsedvalue = JSON.parse(JSON.stringify(newValue)) - parsedvalue.actions = [] - parsedvalue.authentication = {} - selectedTrigger.app_association = parsedvalue - selectedTrigger.large_image = app.large_image - - if (cy !== undefined && cy !== null) { - const foundnode = cy.getElementById(selectedTrigger.id) - if (foundnode !== undefined && foundnode !== null) { - foundnode.data("large_image", app.large_image) - } - } - - setUpdate(Math.random()); - } - document.activeElement.blur(); - }} - > -
    - - {appname} - - - {appname} - -
    -
    -
    - ) - }} - renderInput={(params) => { - return ( - - ); - }} - /> - -
    - : null} - {selectedTrigger.status === "running" ? null : -
    - Environment - -
    - } +
    + + +
    -
    -
    - Parameters -
    -
    -
    - Webhook URI -
    -
    - { - }} - helperText={ - workflow.triggers[selectedTriggerIndex].parameters[0].value !== undefined && - workflow.triggers[selectedTriggerIndex].parameters[0].value !== null && - (workflow.triggers[ - selectedTriggerIndex - ].parameters[0].value.includes("localhost") || - workflow.triggers[ - selectedTriggerIndex - ].parameters[0].value.includes("127.0.0.1")) ? ( - - PS: This does NOT work with localhost. Use your local IP - instead. - - ) : null - } - InputProps={{ - style: { - }, - endAdornment: - - { - var copyText = document.getElementById("webhook_uri_field"); - if (copyText !== undefined && copyText !== null) { - console.log("NAVIGATOR: ", navigator); - const clipboard = navigator.clipboard; - if (clipboard === undefined) { - toast("Can only copy over HTTPS (port 3443)"); - return; - } - - navigator.clipboard.writeText(copyText.value); - copyText.select(); - copyText.setSelectionRange( - 0, - 99999 - ); /* For mobile devices */ - - /* Copy the text inside the text field */ - document.execCommand("copy"); - toast("Copied Webhook URL"); - } else { - console.log("Couldn't find webhook URI field: ", copyText); - } - }} - edge="end" - > - - - - }} - fullWidth - disabled - value={ - workflow.triggers[selectedTriggerIndex].parameters[0].value - } - color="primary" - placeholder="10" - onBlur={(e) => { - setTriggerCronWrapper(e.target.value); - }} - /> -
    - - -
    - -
    -
    -
    - Authentication headers -
    -
    -
    - { }} - InputProps={{ - style: { - }, - }} - fullWidth - multiline - rows="4" - defaultValue={trigger_header_auth} - color="primary" - disabled={selectedTrigger.status === "running"} - placeholder={"AUTH_HEADER=AUTH_VALUE1"} - onBlur={(e) => { - const value = e.target.value; - if (selectedTrigger.parameters === null) { - selectedTrigger.parameters = []; - } - - workflow.triggers[selectedTriggerIndex].parameters[2] = { - value: value, - name: "auth_headers", - }; - setWorkflow(workflow); - }} - /> -
    -
    -
    -
    - Custom Response -
    -
    -
    - { }} - InputProps={{ - style: { - }, - }} - fullWidth - multiline - rows="2" - color="primary" - disabled={selectedTrigger.status === "running"} - placeholder={"OK"} - onBlur={(e) => { - const value = e.target.value; - if (selectedTrigger.parameters === null) { - selectedTrigger.parameters = []; - } - - workflow.triggers[selectedTriggerIndex].parameters[3] = { - value: value, - name: "custom_response_body", - }; - setWorkflow(workflow); - }} - /> -
    - {workflow.triggers[selectedTriggerIndex].parameters.length > 4 ? - - { - if (selectedTrigger.parameters === null) { - selectedTrigger.parameters = []; - } - - // Sets the webhook to run as version 2.. kinda - var value = "v2" - if (workflow.triggers[selectedTriggerIndex].parameters[4].value.includes("v2")) { - value = "v1" - } - - workflow.triggers[selectedTriggerIndex].parameters[4] = { - name: "await_response", - value: value - } - - setWorkflow(workflow) - setUpdate(Math.random()) - }} - color="primary" - value="await_response" - /> - } - label={
    Wait For Response
    } - /> -
    - : null} -
    +
    +
    +
    + Authentication headers +
    +
    + { }} + InputProps={{ + style: { + }, + }} + fullWidth + multiline + rows="4" + defaultValue={trigger_header_auth} + color="primary" + disabled={selectedTrigger.status === "running"} + placeholder={"AUTH_HEADER=AUTH_VALUE1"} + onBlur={(e) => { + const value = e.target.value; + if (selectedTrigger.parameters === null) { + selectedTrigger.parameters = []; + } + + workflow.triggers[selectedTriggerIndex].parameters[2] = { + value: value, + name: "auth_headers", + }; + setWorkflow(workflow); + }} + /> +
    +
    +
    +
    + Custom Response +
    +
    +
    + { }} + InputProps={{ + style: { + }, + }} + fullWidth + multiline + rows="2" + color="primary" + disabled={selectedTrigger.status === "running"} + placeholder={"OK"} + onBlur={(e) => { + const value = e.target.value; + if (selectedTrigger.parameters === null) { + selectedTrigger.parameters = []; + } + + workflow.triggers[selectedTriggerIndex].parameters[3] = { + value: value, + name: "custom_response_body", + }; + setWorkflow(workflow); + }} + /> +
    + {workflow.triggers[selectedTriggerIndex].parameters.length > 4 ? + + { + if (selectedTrigger.parameters === null) { + selectedTrigger.parameters = []; + } + + // Sets the webhook to run as version 2.. kinda + var value = "v2" + if (workflow.triggers[selectedTriggerIndex].parameters[4].value.includes("v2")) { + value = "v1" + } + + workflow.triggers[selectedTriggerIndex].parameters[4] = { + name: "await_response", + value: value + } + + setWorkflow(workflow) + setUpdate(Math.random()) + }} + color="primary" + value="await_response" + /> + } + label={
    Wait For Response
    } + /> +
    + : null}
    +
    +
    const stopMailSub = (trigger, triggerindex) => { // DELETE @@ -15310,7 +15344,7 @@ const releaseToConnectLabel = "Release to Connect" } - // Version: v2 = await response for 30 sec + // Version: v2 = await response for 30 sec const await_resp = trigger.parameters.find((param) => param.name === "await_response"); var version = ""; if (await_resp !== undefined && await_resp !== null) { @@ -15334,11 +15368,11 @@ const releaseToConnectLabel = "Release to Connect" environment: trigger.environment, auth: auth, custom_response: custom_response, - version: version, - version_timeout: 15, + version: version, + version_timeout: 15, }; - console.log("Trigger data: ", data) + console.log("Trigger data: ", data) fetch(globalUrl + "/api/v1/hooks/new", { method: "POST", @@ -15370,7 +15404,7 @@ const releaseToConnectLabel = "Release to Connect" if (trigger.id === undefined) { return; } - + fetch(globalUrl + "/api/v1/hooks/" + trigger.id + "/delete", { method: "DELETE", headers: { @@ -15383,7 +15417,7 @@ const releaseToConnectLabel = "Release to Connect" if (response.status !== 200) { console.log("Status not 200 for stream results :O!"); } - + return response.json(); }) .then((responseJson) => { @@ -15402,7 +15436,7 @@ const releaseToConnectLabel = "Release to Connect" setWorkflow(workflow); saveWorkflow(workflow); setSelectedTrigger({}) - + }) .catch((error) => { //toast(error.toString()); @@ -15411,76 +15445,76 @@ const releaseToConnectLabel = "Release to Connect" ); }); }; - + // POST to /api/v1/workflows const createWorkflow = (workflow, trigger_index) => { - fetch(globalUrl + "/api/v1/workflows", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(workflow), - credentials: "include", - }) - .then((response) => { - if (response.status === 200) { - getAvailableWorkflows(trigger_index) - } + fetch(globalUrl + "/api/v1/workflows", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(workflow), + credentials: "include", + }) + .then((response) => { + if (response.status === 200) { + getAvailableWorkflows(trigger_index) + } - return response.json(); - }) - .then((responseJson) => { - if (responseJson.id !== undefined && responseJson.id !== null && responseJson.id.length > 0) { - toast("Successfully created workflow"); + return response.json(); + }) + .then((responseJson) => { + if (responseJson.id !== undefined && responseJson.id !== null && responseJson.id.length > 0) { + toast("Successfully created workflow"); - handleWorkflowSelectionUpdate({ target: { value: responseJson } }, true) - } - }) - .catch((error) => { - console.log("Create workflow error: ", error.toString()) - }) + handleWorkflowSelectionUpdate({ target: { value: responseJson } }, true) + } + }) + .catch((error) => { + console.log("Create workflow error: ", error.toString()) + }) } - const UserinputSidebar = !selectedTrigger || Object.getOwnPropertyNames(selectedTrigger)?.length === 0 || !workflow?.triggers || !workflow?.triggers[selectedTriggerIndex] || !selectedTrigger.trigger_type || selectedTrigger.trigger_type !== "USERINPUT" ? null : -
    -

    - {selectedTrigger.app_name} -

    - - What is the user input trigger? - - -
    Name
    - + const UserinputSidebar = !selectedTrigger || Object.getOwnPropertyNames(selectedTrigger)?.length === 0 || !workflow?.triggers || !workflow?.triggers[selectedTriggerIndex] || !selectedTrigger.trigger_type || selectedTrigger.trigger_type !== "USERINPUT" ? null : +
    +

    + {selectedTrigger.app_name} +

    + + What is the user input trigger? + + +
    Name
    + - {/*
    + {/*
    Environment:
    */} -
    -
    -
    - Information - - The information you want to show the user. Supports variables. Supports Markdown & HTML. - -
    +
    +
    +
    + Information + + The information you want to show the user. Supports variables. Supports Markdown & HTML. + +
    +
    + 0 && workflow.triggers[selectedTriggerIndex].parameters[0] !== undefined && workflow.triggers[selectedTriggerIndex].parameters[0].value !== undefined ? workflow.triggers[selectedTriggerIndex].parameters[0].value : "" + } + color="primary" + placeholder="" + onBlur={(e) => { + setTriggerTextInformationWrapper(e.target.value); + }} + /> +
    +
    + Input options + + Use subflows to connect to any app you want, or use the default email and sms options + +
    +
    + + { + setTriggerOptionsWrapper("subflow"); + }} + color="primary" + value="subflow" + /> + } + label={
    Subflow
    } + /> + { + setTriggerOptionsWrapper("email"); + }} + color="primary" + value="email" + /> + } + label={
    Email
    } + /> + 0 && workflow.triggers[selectedTriggerIndex].parameters[2] !== undefined && workflow.triggers[selectedTriggerIndex].parameters[2].value !== undefined ? workflow.triggers[selectedTriggerIndex].parameters[2].value.includes("sms") : false} + onChange={() => { + setTriggerOptionsWrapper("sms"); + }} + color="primary" + value="sms" + disabled={true} + /> + } + label={
    SMS
    } + /> +
    + {workflow?.triggers && + workflow?.triggers[selectedTriggerIndex] && + workflow?.triggers[selectedTriggerIndex].parameters && + workflow?.triggers[selectedTriggerIndex].parameters[2] && + workflow?.triggers[selectedTriggerIndex].parameters[2].value && + workflow?.triggers[selectedTriggerIndex].parameters[2].value.includes("subflow") + ? ( +
    + {workflows === undefined || + workflows === null || + workflows.length === 0 ? null : ( + option.id === value.id} + getOptionLabel={(option) => { + if (option === undefined || option === null || option.name === undefined || option.name === null) { + return "No Workflow Selected"; + } + + const newname = (option.name.charAt(0).toUpperCase() + option.name.substring(1)).replaceAll("_", " "); + return newname; + }} + options={ + [{ + "id": "", + "name": "No Workflow Selected", + }].concat(workflows) + } + fullWidth + style={{ + backgroundColor: theme.palette.inputColor, + height: 50, + borderRadius: theme.palette?.borderRadius, + marginTop: 15, + marginBottom: 15, + }} + onChange={(event, newValue) => { + console.log("Changed autocomplete!") + handleWorkflowSelectionUpdate({ target: { value: newValue } }, true) + event.target.blur(); + }} + renderOption={(props, data, state) => { + if (data.id === workflow.id) { + data = workflow; + } + + return ( + + {data.image !== undefined && data.image !== null && data.image.length > 0 ? + {data.name} + : null} + + Choose Trigger '{data.name}' + + + }> + { + handleWorkflowSelectionUpdate({ + target: { + value: data, + } + }, + true) + document.activeElement.blur(); + }} + > + + {data.name} + + + ) + }} + renderInput={(params) => { + return ( + + ); + }} + /> + )} + + {/* Button for making a new workflow to attach */} + +
    + ) : null} + + {workflow?.triggers && + workflow?.triggers[selectedTriggerIndex] && + workflow?.triggers[selectedTriggerIndex].parameters && + workflow?.triggers[selectedTriggerIndex].parameters[2] && + workflow?.triggers[selectedTriggerIndex].parameters[2].value && + workflow?.triggers[selectedTriggerIndex].parameters[2].value.includes("email") + ? ( 0 && workflow.triggers[selectedTriggerIndex].parameters[0] !== undefined && workflow.triggers[selectedTriggerIndex].parameters[0].value !== undefined ? workflow.triggers[selectedTriggerIndex].parameters[0].value : "" - } + label="Email" color="primary" - placeholder="" - onBlur={(e) => { - setTriggerTextInformationWrapper(e.target.value); + required + placeholder={"mail1@company.com,mail2@company.com"} + defaultValue={ + workflow.triggers[selectedTriggerIndex].parameters[3].value + } + onBlur={(event) => { + workflow.triggers[selectedTriggerIndex].parameters[3].value = + event.target.value; + setWorkflow(workflow); + setUpdate(Math.random()); }} /> -
    -
    - Input options - - Use subflows to connect to any app you want, or use the default email and sms options - -
    -
    - - { + workflow.triggers[selectedTriggerIndex].parameters[4].value = + event.target.value; + setWorkflow(workflow); + setUpdate(Math.random()); + }} + /> + ) : null} + + +
    + Required Input-Questions + {workflow.input_questions !== undefined && workflow.input_questions !== null && workflow.input_questions.length > 0 ? +
    + {workflow.input_questions.map((question, index) => { + var foundParamIndex = workflow.triggers[selectedTriggerIndex].parameters.findIndex((param) => param.name === "input_questions") + + const selectionClick = () => { + if (foundParamIndex === -1) { + workflow.triggers[selectedTriggerIndex].parameters.push({ + "name": "input_questions", + "value": [], + }) + + foundParamIndex = workflow.triggers[selectedTriggerIndex].parameters.length - 1 + } else { + try { + workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value = JSON.parse(workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value) + } catch (e) { + console.log("Couldn't parse input questions: ", e) + workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value = [] + } + } + + if (workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value.includes(question.name)) { + workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value = workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value.filter((item) => item !== question.name) + } else { + workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value.push(question.name) + } + + // Make it back to a string + workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value = JSON.stringify(workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value) + setWorkflow(workflow) + setUpdate(Math.random()) + } + + return ( +
    { + selectionClick() + }}> { - setTriggerOptionsWrapper("subflow"); - }} - color="primary" - value="subflow" + checked={foundParamIndex !== -1 ? workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value.includes(question.name) : false} /> - } - label={
    Subflow
    } - /> - { - setTriggerOptionsWrapper("email"); - }} - color="primary" - value="email" - /> - } - label={
    Email
    } - /> - 0 && workflow.triggers[selectedTriggerIndex].parameters[2] !== undefined && workflow.triggers[selectedTriggerIndex].parameters[2].value !== undefined ? workflow.triggers[selectedTriggerIndex].parameters[2].value.includes("sms") : false} - onChange={() => { - setTriggerOptionsWrapper("sms"); - }} - color="primary" - value="sms" - disabled={true} - /> - } - label={
    SMS
    } - /> - - {workflow?.triggers && - workflow?.triggers[selectedTriggerIndex] && - workflow?.triggers[selectedTriggerIndex].parameters && - workflow?.triggers[selectedTriggerIndex].parameters[2] && - workflow?.triggers[selectedTriggerIndex].parameters[2].value && - workflow?.triggers[selectedTriggerIndex].parameters[2].value.includes("subflow") - ? ( -
    - {workflows === undefined || - workflows === null || - workflows.length === 0 ? null : ( - option.id === value.id} - getOptionLabel={(option) => { - if (option === undefined || option === null || option.name === undefined || option.name === null) { - return "No Workflow Selected"; - } - - const newname = (option.name.charAt(0).toUpperCase() + option.name.substring(1)).replaceAll("_", " "); - return newname; - }} - options={ - [{ - "id": "", - "name": "No Workflow Selected", - }].concat(workflows) - } - fullWidth - style={{ - backgroundColor: theme.palette.inputColor, - height: 50, - borderRadius: theme.palette?.borderRadius, - marginTop: 15, - marginBottom: 15, - }} - onChange={(event, newValue) => { - console.log("Changed autocomplete!") - handleWorkflowSelectionUpdate({ target: { value: newValue } }, true) - event.target.blur(); - }} - renderOption={(props, data, state) => { - if (data.id === workflow.id) { - data = workflow; - } - - return ( - - {data.image !== undefined && data.image !== null && data.image.length > 0 ? - {data.name} - : null} - - Choose Trigger '{data.name}' - - - }> - { - handleWorkflowSelectionUpdate({ - target: { - value: data, - }}, - true) - document.activeElement.blur(); - }} - > - - {data.name} - - - ) - }} - renderInput={(params) => { - return ( - - ); - }} - /> - )} - - {/* Button for making a new workflow to attach */} - - -
    - ) : null} - - {workflow?.triggers && - workflow?.triggers[selectedTriggerIndex] && - workflow?.triggers[selectedTriggerIndex].parameters && - workflow?.triggers[selectedTriggerIndex].parameters[2] && - workflow?.triggers[selectedTriggerIndex].parameters[2].value && - workflow?.triggers[selectedTriggerIndex].parameters[2].value.includes("email") - ? ( - { - workflow.triggers[selectedTriggerIndex].parameters[3].value = - event.target.value; - setWorkflow(workflow); - setUpdate(Math.random()); - }} - /> - ) : null} - - {workflow?.triggers && - workflow?.triggers[selectedTriggerIndex] && - workflow?.triggers[selectedTriggerIndex].parameters && - workflow?.triggers[selectedTriggerIndex].parameters[2] && - workflow?.triggers[selectedTriggerIndex].parameters[2].value && - ( - workflow?.triggers[selectedTriggerIndex].parameters[2].value.includes("email") || - workflow?.triggers[selectedTriggerIndex].parameters[2].value.includes("sms") - ) ? ( - { - workflow.triggers[selectedTriggerIndex].parameters[4].value = - event.target.value; - setWorkflow(workflow); - setUpdate(Math.random()); - }} - /> - ) : null} - - -
    - Required Input-Questions - {workflow.input_questions !== undefined && workflow.input_questions !== null && workflow.input_questions.length > 0 ? -
    - {workflow.input_questions.map((question, index) => { - var foundParamIndex = workflow.triggers[selectedTriggerIndex].parameters.findIndex((param) => param.name === "input_questions") - - const selectionClick = () => { - if (foundParamIndex === -1) { - workflow.triggers[selectedTriggerIndex].parameters.push({ - "name": "input_questions", - "value": [], - }) - - foundParamIndex = workflow.triggers[selectedTriggerIndex].parameters.length - 1 - } else { - try { - workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value = JSON.parse(workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value) - } catch (e) { - console.log("Couldn't parse input questions: ", e) - workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value = [] - } - } - - if (workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value.includes(question.name)) { - workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value = workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value.filter((item) => item !== question.name) - } else { - workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value.push(question.name) - } - - // Make it back to a string - workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value = JSON.stringify(workflow.triggers[selectedTriggerIndex].parameters[foundParamIndex].value) - setWorkflow(workflow) - setUpdate(Math.random()) - } - - return ( -
    { - selectionClick() - }}> - - - {question.name} - -
    - ) - })} -
    - : -
    { - setEditWorkflowModalOpen(true) - toast.info("Expand and scroll down to add input-questions") - }}> - No Input-Questions found. Click to add them! -
    - } + + {question.name} + +
    + ) + })}
    + : +
    { + setEditWorkflowModalOpen(true) + toast.info("Expand and scroll down to add input-questions") + }}> + No Input-Questions found. Click to add them! +
    + } +
    -
    +
    const defaultEnvironment = environments.find( (env) => env.default && env.Name.toLowerCase() !== "cloud" ); if (selectedTrigger.trigger_type === "PIPELINE" && selectedTrigger.environment === "onprem" && defaultEnvironment !== undefined) { - selectedTrigger.environment = defaultEnvironment.Name - setSelectedTrigger(selectedTrigger) } + selectedTrigger.environment = defaultEnvironment.Name + setSelectedTrigger(selectedTrigger) + } - const PipelineSidebar = !selectedTrigger || Object.getOwnPropertyNames(selectedTrigger)?.length === 0 || !workflow?.triggers || !workflow?.triggers[selectedTriggerIndex] || !selectedTrigger.trigger_type || selectedTrigger.trigger_type !== "SCHEDULE" ? null : -
    -

    - {selectedTrigger.app_name}: {selectedTrigger.status} -

    - - What are pipelines? - - -
    Name
    - + const PipelineSidebar = !selectedTrigger || Object.getOwnPropertyNames(selectedTrigger)?.length === 0 || !workflow?.triggers || !workflow?.triggers[selectedTriggerIndex] || !selectedTrigger.trigger_type || selectedTrigger.trigger_type !== "SCHEDULE" ? null : +
    +

    + {selectedTrigger.app_name}: {selectedTrigger.status} +

    + + What are pipelines? + + +
    Name
    + -
    - Environment - { + selectedTrigger.environment = e.target.value; + setSelectedTrigger(selectedTrigger); - setWorkflow(workflow); - setUpdate(Math.random()); - }} + setWorkflow(workflow); + setUpdate(Math.random()); + }} + style={{ + backgroundColor: theme.palette.inputColor, + color: "white", + height: 50, + }} + > + {environments.map((data) => { + if (data.archived) { + return null; + } + + if (data.Name.toLowerCase() === "cloud") { + return null; + } + + return ( + - {environments.map((data) => { - if (data.archived) { - return null; - } - - if (data.Name.toLowerCase() === "cloud") { - return null; - } - - return ( - - {data.Name} - - ); - })} - -
    - -
    -
    - What would you like to do? - {/* + {data.Name} + + ); + })} + +
    + +
    +
    + What would you like to do? + {/*
    { @@ -16075,94 +16111,192 @@ const releaseToConnectLabel = "Release to Connect" */} -
    { - if (selectedTrigger.status === "running"){ - toast("please stop the trigger to edit the configuration"); - return; - } else { - setSelectedOption("Kafka Queue"); - setTenzirConfigModalOpen(true); - } - }} - style={{ - border: "1px solid rgba(255,255,255,0.3)", - borderRadius: theme.palette?.borderRadius, - padding: 10, - cursor: "pointer", - marginTop: 5, - display: "flex", - alignItems: "center", - }} - > - { - if (selectedTrigger.status !== "running") { - setSelectedOption("Kafka Queue") +
    { + if (selectedTrigger.status === "running") { + toast("please stop the trigger to edit the configuration"); + return; + } else { + setSelectedOption("Kafka Queue"); + setTenzirConfigModalOpen(true); + } + }} + style={{ + border: "1px solid rgba(255,255,255,0.3)", + borderRadius: theme.palette?.borderRadius, + padding: 10, + cursor: "pointer", + marginTop: 5, + display: "flex", + alignItems: "center", + }} + > + { + if (selectedTrigger.status !== "running") { + setSelectedOption("Kafka Queue") - } - }} - - value={"Kafka Queue"} - name="option" - /> } - label="Subscribe to a Kafka Queue" - /> -
    + }} -
    - -
    -
    -
    + value={"Kafka Queue"} + name="option" + /> + } + label="Subscribe to a Kafka Queue" + />
    - const ScheduleSidebar = !selectedTrigger || Object.getOwnPropertyNames(selectedTrigger)?.length === 0 || !workflow?.triggers || !workflow?.triggers[selectedTriggerIndex] && (!selectedTrigger.trigger_type || selectedTrigger.trigger_type !== "SCHEDULE") ? null : -
    -

    - {selectedTrigger.app_name}: {selectedTrigger.status} -

    - - What are schedules? - - + +
    +
    +
    +
    + + const ScheduleSidebar = !selectedTrigger || Object.getOwnPropertyNames(selectedTrigger)?.length === 0 || !workflow?.triggers || !workflow?.triggers[selectedTriggerIndex] && (!selectedTrigger.trigger_type || selectedTrigger.trigger_type !== "SCHEDULE") ? null : +
    +

    + {selectedTrigger.app_name}: {selectedTrigger.status} +

    + + What are schedules? + + +
    Name
    + +
    + Environment + +
    + +
    +
    + Parameters +
    -
    Name
    + > +
    +
    + When to start: {isCloud || selectedTrigger?.environment === "cloud" ? Cron formatting : "every X second"} +
    +
    { + setTriggerCronWrapper(e.target.value); + }} /> -
    - Environment - + /> +
    + Runtime Argument: +
    + 1 ? workflow.triggers[selectedTriggerIndex].parameters[1].value : "" + } + placeholder='{"key": "value"}' + onBlur={(e) => { + setTriggerBodyWrapper(e.target.value); + }} + /> -
    -
    - Parameters -
    -
    -
    - When to start: {isCloud || selectedTrigger?.environment === "cloud" ? Cron formatting : "every X second"} -
    -
    - { - setTriggerCronWrapper(e.target.value); - }} - /> - {/*selectedTrigger.environment === "cloud" ? - - : - null - */} -
    -
    -
    - Runtime Argument: -
    -
    - 1 ? workflow.triggers[selectedTriggerIndex].parameters[1].value : "" - } - placeholder='{"key": "value"}' - onBlur={(e) => { - setTriggerBodyWrapper(e.target.value); - }} - /> - -
    - - -
    -
    +
    + +
    +
    +
    const cytoscapeViewWidths = isMobile ? 50 : 950; const bottomBarStyle = { @@ -16386,24 +16422,24 @@ const releaseToConnectLabel = "Release to Connect" marginLeft: 20, marginBottom: 30, zIndex: 10, - transform: isMobile - ? `translateX(20px)` - : `translateX(${leftBarSize}px)`, - top: isMobile ? appBarSize + 55 : undefined, + transform: isMobile + ? `translateX(20px)` + : `translateX(${leftBarSize}px)`, + top: isMobile ? appBarSize + 55 : undefined, bottom: isMobile ? undefined : 0, -}; + }; const topBarStyle = { position: "absolute", top: isMobile ? 30 : 25, - transform: isMobile ? "translateX(20px)" : `translateX(${leftBarSize}px)`, + transform: isMobile ? "translateX(20px)" : `translateX(${leftBarSize}px)`, transition: "all 0.3s ease", - zoom: 0.9, + zoom: 0.9, } const TopCytoscapeBar = (props) => { - const [hovered, setHovered] = useState(false) + const [hovered, setHovered] = useState(false) if (workflow.public === true) { return null @@ -16413,37 +16449,37 @@ const releaseToConnectLabel = "Release to Connect" return null } - const isCorrectOrg = workflow.public === true || userdata.active_org.id === undefined || userdata.active_org.id === null || workflow.org_id === null || workflow.org_id === undefined || workflow.org_id.length === 0 || userdata.active_org.id === workflow.org_id + const isCorrectOrg = workflow.public === true || userdata.active_org.id === undefined || userdata.active_org.id === null || workflow.org_id === null || workflow.org_id === undefined || workflow.org_id.length === 0 || userdata.active_org.id === workflow.org_id return (
    -
    - { - setHovered(true) - }} - onMouseLeave={() => { - setHovered(false) - }} - onClick={() => { - setEditWorkflowModalOpen(true) - setLastSaved(false) - }} - > - - {workflow.name} - +
    + { + setHovered(true) + }} + onMouseLeave={() => { + setHovered(false) + }} + onClick={() => { + setEditWorkflowModalOpen(true) + setLastSaved(false) + }} + > + + {workflow.name} + {workflowAsCode && (
    + + {showEnvironment === true && environments.length > 0 && selectedActionEnvironment !== undefined && selectedActionEnvironment !== null && selectedActionEnvironment.Name !== undefined && selectedActionEnvironment.Name !== null ? + - Select an Org + Runtime Location - { + getEnvironments(workflow.org_id) + }} + onChange={(e) => { + setLastSaved(false) + const env = environments.find((a) => a.Name === e.target.value); + setSelectedActionEnvironment(env) + selectedAction.environment = env.Name + setSelectedAction(selectedAction) - navigate(`?org_id=${e.target.value}`) + for (let actionkey in workflow.actions) { + workflow.actions[actionkey].environment = env.Name + } - // Unselect in cy - if (cy !== undefined && cy !== null) { - cy.nodes().unselect() - cy.edges().unselect() - } + setWorkflow(workflow) + //toast.success("Set execution location for ALL actions to " + env.Name) + }} + style={{ + pointerEvents: "auto", + color: "white", + maxWidth: 250, + minWidth: 250, + borderRadius: theme.palette?.borderRadius, + marginLeft: 35, - ReactDOM.unstable_batchedUpdates(() => { - getEnvironments(e.target.value) - getAppAuthentication(undefined, undefined, undefined, e.target.value) - getFiles(e.target.value) - listOrgCache(e.target.value) + backgroundColor: theme.palette.inputColor, + height: 40, + }} + > + {environments.map((data, index) => { + if (data.archived === true) { + return null + } - // FIXME: There is a timing problem here. - // For events to have the data they need, they - // need to be registered with setupGraph() - // AFTER all the APIs are done + const isRunning = data.running_ip !== "" - // Should look through childorg workflow - setTimeout(() => { - if (e.target.value === originalWorkflow.org_id) { - console.log("Original org selected. No change.") + return ( + - updateCurrentWorkflow(originalWorkflow) - return - } else { - // Load environments, auth, auth groups - //toast("Loading correct info for suborg") - } + {data.Name === "cloud" || data.Name === "Cloud" ? null : !isRunning ? - if (originalWorkflow.childorg_workflow_ids === undefined || originalWorkflow.childorg_workflow_ids === null || originalWorkflow.childorg_workflow_ids.length === 0) { - //console.log("Childorg doesn't exist (?). Suborgworkflows: ", suborgWorkflows) + + + { + e.preventDefault() + e.stopPropagation() - if (suborgWorkflows !== undefined && suborgWorkflows !== null && suborgWorkflows.length > 0) { - var found = false - for (var suborgkey in suborgWorkflows) { - const suborgWorkflow = suborgWorkflows[suborgkey] - if (suborgWorkflow.org_id === e.target.value) { - found = true - updateCurrentWorkflow(suborgWorkflow) - break - } - } - - if (!found) { - toast("(3) Creating new workflow for this org. Please wait a second while we duplicate.") - //console.log("No workflow found out of suborg workflows.") - - //saveWorkflow(originalWorkflow, undefined, undefined, e.target.value) - } - } else { - console.log("Suborgworkflows: ", suborgWorkflows) - toast("(1) Loading NEW workflow for this org (?). Please wait a second.") - saveWorkflow(originalWorkflow, undefined, undefined, e.target.value) - } - } else { - console.log("In childorg EXIST!") - - var workflowFound = false - for (var childorgidkey in originalWorkflow.childorg_workflow_ids) { - const childworkflowid = originalWorkflow.childorg_workflow_ids[childorgidkey] - for (var suborgWorkflowKey in suborgWorkflows) { - const suborgWorkflow = suborgWorkflows[suborgWorkflowKey] - if (suborgWorkflow.org_id === e.target.value) { - workflowFound = true - - updateCurrentWorkflow(suborgWorkflow) - break - } - } - - if (workflowFound) { - break - } - } - - if (!workflowFound) { - console.log("No workflow found.") - toast("(2) Creating new workflow for this org. Please wait a few seconds while we prepare it for you.") - //saveWorkflow(originalWorkflow, undefined, undefined, e.target.value) - } - } - }, 500) - }) - }} - label="Suborg Distribution" - fullWidth - > - - Parent: {userdata.active_org.large_image}{" "} - - {userdata.active_org.name} - - - - - - {originalWorkflow.suborg_distribution.map((org_id, index) => { - var data = {} - for (var key in userdata.orgs) { - if (userdata.orgs[key].id === org_id) { - data = userdata.orgs[key] - break - } - } - - if (data.id === undefined || data.id === null) { - //toast("No org found for id: " + org_id) - return null - } - - var skipOrg = false; - - const imagesize = 22 - const imageStyle = { - width: imagesize, - height: imagesize, - pointerEvents: "none", - marginRight: 10, - marginLeft: - data.creator_org !== undefined && - data.creator_org !== null && - data.creator_org.length > 0 - ? data.id === userdata.active_org.id - ? 0 - : 0 - : 0, - } - - const image = - data.image === "" ? ( - {data.name} - ) : ( - {data.name} - ) + window.open(`/admin?tab=locations&env=${data.Name}`, "_blank", "noopener,noreferrer") + }} - return ( - - {image}{" "} - - {data.name} - - - ) - })} - - - } -
    + /> + + + : + { + //handleChipClick + }} + variant="outlined" + color="primary" + /> + } - {showEnvironment === true && environments.length > 0 && selectedActionEnvironment !== undefined && selectedActionEnvironment !== null && selectedActionEnvironment.Name !== undefined && selectedActionEnvironment.Name !== null ? - + {data.default === true ? + + : null} - - Runtime Location - - + + : null} - /> - - - : - { - //handleChipClick - }} - variant="outlined" - color="primary" - /> - } + {parentWorkflows === undefined || parentWorkflows === null || parentWorkflows.length === 0 ? null : + + }
    ); @@ -17119,163 +17155,163 @@ const releaseToConnectLabel = "Release to Connect" }; const BottomAvatars = () => { - const connectedUsers = [{ - "user": "Anonymous", - "user_id": "user_id", - "color": "blue", - }] - + const connectedUsers = [{ + "user": "Anonymous", + "user_id": "user_id", + "color": "blue", + }] - if (connectedUsers === undefined || connectedUsers === null || connectedUsers.length < 2) { - return null - } - const avatarStyle = { - position: "fixed", - display: "flex", - right: isMobile ? 20 : 20, - top: isMobile ? appBarSize-100 : undefined, - bottom: isMobile ? undefined : 0, - left: isMobile ? undefined : leftBarSize, - minWidth: cytoscapeViewWidths, - maxWidth: cytoscapeViewWidths, - marginLeft: 20, - marginBottom: 20, - zIndex: 50, - } + if (connectedUsers === undefined || connectedUsers === null || connectedUsers.length < 2) { + return null + } - const HandleAvatar = (props) => { - const {user} = props - console.log("Clicked avatar: ", user) + const avatarStyle = { + position: "fixed", + display: "flex", + right: isMobile ? 20 : 20, + top: isMobile ? appBarSize - 100 : undefined, + bottom: isMobile ? undefined : 0, + left: isMobile ? undefined : leftBarSize, + minWidth: cytoscapeViewWidths, + maxWidth: cytoscapeViewWidths, + marginLeft: 20, + marginBottom: 20, + zIndex: 50, + } - const userTitle = user.user[0].toUpperCase() - return ( - - - {userTitle} - - - ) - } + const HandleAvatar = (props) => { + const { user } = props + console.log("Clicked avatar: ", user) + const userTitle = user.user[0].toUpperCase() return ( -
    - {connectedUsers.map((user) => { - return ( - - ) - })} -
    - ) + + + {userTitle} + + + ) + } + + return ( +
    + {connectedUsers.map((user) => { + return ( + + ) + })} +
    + ) } - const shownErrors = !distributedFromParent && !isMobile && workflow.errors !== undefined && workflow.errors !== null && workflow.errors.length > 0 && showErrors && (!workflow.public || userdata.support === true) ? -
    0 && showErrors && (!workflow.public || userdata.support === true) ? +
    + color: "white", + padding: 10, + borderRadius: theme.palette?.borderRadius, + transition: "left 0.3s ease, top 0.3s ease", + }} + > - + { + e.preventDefault(); + + // A temporary hider thing + setShowErrors(false) + }} > - { - e.preventDefault(); + + + - // A temporary hider thing - setShowErrors(false) - }} - > - - - + + {/**/} + {workflow.errors.length} Workflow Issue{workflow.errors.length > 1 ? "s" : ""} + + + {workflow.errors.slice(0, 3).map((error) => { + // Loop through each word, and if it matches "Action " then replace it with a link to the action + var colornext = false + const newerror = error === undefined || error == null ? "" : error.split(" ").map((word) => { + if (colornext) { + colornext = false + return ( + { + // Find it in cytoscape + if (cy === undefined || cy === null) { + return + } - - {/**/} - {workflow.errors.length} Workflow Issue{workflow.errors.length > 1 ? "s" : ""} - - - {workflow.errors.slice(0,3).map((error) => { - // Loop through each word, and if it matches "Action " then replace it with a link to the action - var colornext = false - const newerror = error === undefined || error == null ? "" : error.split(" ").map((word) => { - if (colornext) { - colornext = false - return ( - { - // Find it in cytoscape - if (cy === undefined || cy === null) { - return - } + const foundnode = cy.nodes().filter((node) => { + const nodelabel = node.data("label") + if (nodelabel === undefined || nodelabel === null) { + return false + } - const foundnode = cy.nodes().filter((node) => { - const nodelabel = node.data("label") - if (nodelabel === undefined || nodelabel === null) { - return false - } + return nodelabel.toLowerCase() === word.toLowerCase() + }) - return nodelabel.toLowerCase() === word.toLowerCase() - }) + if (foundnode === undefined || foundnode === null || foundnode.length === 0) { + return + } - if (foundnode === undefined || foundnode === null || foundnode.length === 0) { - return - } + cy.elements().unselect() + foundnode[0].select() + }} + > + {word}  + + ) + } - cy.elements().unselect() - foundnode[0].select() - }} - > - {word}  - - ) - } + if (word.toLowerCase() === "action") { + colornext = true + } - if (word.toLowerCase() === "action") { - colornext = true - } + return word + " " + }) - return word + " " - }) + if (newerror === undefined || newerror === null || newerror === "") { + return null + } - if (newerror === undefined || newerror === null || newerror === "") { - return null - } - - return ( -
    - - {newerror} -
    - ) - })} -
    -
    - : null + return ( +
    + - {newerror} +
    + ) + })} + +
    + : null const RightsideBar = () => { - const [hovered, setHovered] = useState(false) + const [hovered, setHovered] = useState(false) useEffect(() => { const handleKeyDown = (event) => { @@ -17303,33 +17339,33 @@ const releaseToConnectLabel = "Release to Connect" } } - if (( event.ctrlKey || event.metaKey ) && event.key === ";") { + if ((event.ctrlKey || event.metaKey) && event.key === ";") { if (!workflow.public && executionModalOpen) { getWorkflowExecution(props.match.params.key, ""); } } - /* - if (( event.ctrlKey || event.metaKey ) && event.shiftKey) { - console.log("Shift key pressed") - if (!workflow.public && executionModalOpen) { - setExecutionRunning(false); - stop() - const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; - const newitem = removeParam("execution_id", cursearch); - navigate(curpath + newitem) - setExecutionModalView(0); - } - } - */ + /* + if (( event.ctrlKey || event.metaKey ) && event.shiftKey) { + console.log("Shift key pressed") + if (!workflow.public && executionModalOpen) { + setExecutionRunning(false); + stop() + const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; + const newitem = removeParam("execution_id", cursearch); + navigate(curpath + newitem) + setExecutionModalView(0); + } + } + */ }; - + document.addEventListener('keydown', handleKeyDown); - + return () => { document.removeEventListener('keydown', handleKeyDown); } - }, [executeWorkflow, executionText, workflow, lastSaved, executionRequestStarted]) + }, [executeWorkflow, executionText, workflow, lastSaved, executionRequestStarted]) useEffect(() => { const handleKeyDown = (event) => { @@ -17356,147 +17392,154 @@ const releaseToConnectLabel = "Release to Connect" } } - if (( event.ctrlKey || event.metaKey ) && event.key === ";") { + if ((event.ctrlKey || event.metaKey) && event.key === ";") { if (!workflow.public && executionModalOpen) { getWorkflowExecution(props.match.params.key, ""); } } - /* - if (( event.ctrlKey || event.metaKey ) && event.shiftKey) { - console.log("Shift key pressed") - if (!workflow.public && executionModalOpen) { - setExecutionRunning(false); - stop() - const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; - const newitem = removeParam("execution_id", cursearch); - navigate(curpath + newitem) - setExecutionModalView(0); - } - } - */ + /* + if (( event.ctrlKey || event.metaKey ) && event.shiftKey) { + console.log("Shift key pressed") + if (!workflow.public && executionModalOpen) { + setExecutionRunning(false); + stop() + const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; + const newitem = removeParam("execution_id", cursearch); + navigate(curpath + newitem) + setExecutionModalView(0); + } + } + */ }; - + document.addEventListener('keydown', handleKeyDown); - + return () => { document.removeEventListener('keydown', handleKeyDown); }; - }, [executeWorkflow, executionText, workflow, lastSaved, executionRequestStarted]); + }, [executeWorkflow, executionText, workflow, lastSaved, executionRequestStarted]); - if (isMobile) { - return null - } + if (isMobile) { + return null + } - return ( -
    setHovered(true)} - onMouseLeave={() => setHovered(false)} - onClick={() => { - setExecutionModalOpen(true); - getWorkflowExecution(props.match.params.key, ""); - }} - > - - - Explore runs - -
    - ) + if (workflow.public === true) { + return null + } + + return ( +
    setHovered(true)} + onMouseLeave={() => setHovered(false)} + onClick={() => { + setExecutionModalOpen(true); + getWorkflowExecution(props.match.params.key, ""); + }} + > + + + Explore runs + +
    + ) } // Used for handling suborg workflow distribution management const updateCurrentWorkflow = (inputworkflow) => { - //setLastSaved(false) - setSelectedAction({}); - setSelectedApp({}) - setWorkflow(inputworkflow) - if (inputworkflow !== undefined && inputworkflow !== null && inputworkflow.id !== undefined && inputworkflow.id !== null) { - getRevisionHistory(inputworkflow.id) - getWorkflowExecution(inputworkflow.id) - } + setCurrentWorkflow(inputworkflow) - // Update props match key - if (inputworkflow.parentorg_workflow !== undefined && inputworkflow.parentorg_workflow !== null && inputworkflow.parentorg_workflow !== "") { - setDistributedFromParent(inputworkflow.parentorg_workflow) - } else { - setDistributedFromParent("") - } + //setLastSaved(false) + setSelectedAction({}); + setSelectedApp({}) + setWorkflow(inputworkflow) - if (cy !== undefined) { - cy.removeListener("select"); - cy.removeListener("unselect"); + if (inputworkflow !== undefined && inputworkflow !== null && inputworkflow.id !== undefined && inputworkflow.id !== null) { + getRevisionHistory(inputworkflow.id, 50, 0, inputworkflow.org_id) + getWorkflowExecution(inputworkflow.id, "", "") + } - cy.removeListener("add"); - cy.removeListener("remove"); + // Update props match key + if (inputworkflow.parentorg_workflow !== undefined && inputworkflow.parentorg_workflow !== null && inputworkflow.parentorg_workflow !== "") { + setDistributedFromParent(inputworkflow.parentorg_workflow) + } else { + setDistributedFromParent("") + } - cy.removeListener("mouseover"); - cy.removeListener("mouseout"); + if (cy !== undefined) { + cy.removeListener("select"); + cy.removeListener("unselect"); - cy.removeListener("drag"); - cy.removeListener("free"); - cy.removeListener("cxttap"); + cy.removeListener("add"); + cy.removeListener("remove"); - setElements([]) + cy.removeListener("mouseover"); + cy.removeListener("mouseout"); - // Remove all edges - cy.edges().remove() - cy.nodes().remove() - } + cy.removeListener("drag"); + cy.removeListener("free"); + cy.removeListener("cxttap"); + + setElements([]) + + // Remove all edges + cy.edges().remove() + cy.nodes().remove() + } } // Uses Org-Id referencing header to create a workflow while getting it in realtime // This further ensures the user needs access to GET the workflow properly const duplicateParentWorkflow = (inputWorkflow, org_id, setWorkflow) => { - fetch(`${globalUrl}/api/v1/workflows/${inputWorkflow.id}`, { - method: "GET", - headers: { - "Org-Id": org_id, - "Content-Type": "application/json", - }, - credentials: "include", - }) - .then((response) => { - if (response.status === 200) { - getChildWorkflows(inputWorkflow.id) - } + fetch(`${globalUrl}/api/v1/workflows/${inputWorkflow.id}`, { + method: "GET", + headers: { + "Org-Id": org_id, + "Content-Type": "application/json", + }, + credentials: "include", + }) + .then((response) => { + if (response.status === 200) { + getChildWorkflows(inputWorkflow.id) + } - return response.json(); - }) - .then((responseJson) => { - if (responseJson.success === false) { - //toast("Failed to duplicate workflow") - } else { - //toast("Successfully duplicated workflow. Reloading child workflows.") - if (setWorkflow === true) { - updateCurrentWorkflow(responseJson) - } - } - }) - .catch((error) => { - console.log("Dupe workflow for suborg error: ", error.toString()) - }) + return response.json(); + }) + .then((responseJson) => { + if (responseJson.success === false) { + //toast("Failed to duplicate workflow") + } else { + //toast("Successfully duplicated workflow. Reloading child workflows.") + if (setWorkflow === true) { + updateCurrentWorkflow(responseJson) + } + } + }) + .catch((error) => { + console.log("Dupe workflow for suborg error: ", error.toString()) + }) } const BottomCytoscapeBar = () => { @@ -17504,13 +17547,13 @@ const releaseToConnectLabel = "Release to Connect" return null; } - const buttonHeights = 45 + const buttonHeights = 45 const boxSize = buttonHeights const executionButton = executionRunning ? ( - + + + ) return ( @@ -17555,32 +17598,32 @@ const releaseToConnectLabel = "Release to Connect" flexDirection: isMobile ? "column" : "row", }} > - - {executionButton} - - - + + {executionButton} + + + { setExecutionText(e.target.value); }} - // Start adornment + // Start adornment /> - + {/*userdata.avatar === creatorProfile.github_avatar ? null :*/} - - - - - - - {workflow.public || userdata.support == true ? - + maxHeight: buttonHeights, + }} + > + - : null} + {workflow.public || userdata.support == true ? + + + + + + : null} + + {/* */} - - - - - - - - + + + + + - - - - - - - - + removeNode(selectedNode.data("id")) + }} + > + + + + - {workflow.configuration !== null && - workflow.configuration !== undefined && - workflow.configuration.exit_on_error !== undefined ? ( - - ) : null} + + + + + - {/* + {workflow.configuration !== null && + workflow.configuration !== undefined && + workflow.configuration.exit_on_error !== undefined ? ( + + ) : null} + + {/* */} - - - - - - + + + + + + + -
    ); @@ -17880,12 +17923,12 @@ const releaseToConnectLabel = "Release to Connect" // defaultReturn = return null; } else { - /* - console.log( - "Unable to handle invalid trigger type " + - selectedTrigger.trigger_type - ); - */ + /* + console.log( + "Unable to handle invalid trigger type " + + selectedTrigger.trigger_type + ); + */ return null; } } else if (Object.getOwnPropertyNames(selectedEdge).length > 0) { @@ -17925,32 +17968,32 @@ const releaseToConnectLabel = "Release to Connect" {defaultReturn} : - - {/**/} + + {/**/}
    {defaultReturn}
    -
    +
    ); //return null; }; const unPublishWorkflow = (data) => { - data.id = props.match.params.key - if (!isCloud) { - toast("Function only supported on cloud") - return - } + data.id = props.match.params.key + if (!isCloud) { + toast("Function only supported on cloud") + return + } - if (data.public !== true) { - toast("Workflow is not public. Can't unpublish"); - return - } + if (data.public !== true) { + toast("Workflow is not public. Can't unpublish"); + return + } // This ALWAYS talks to Shuffle cloud data = JSON.parse(JSON.stringify(data)); - const url = `${globalUrl}/api/v1/workflows/${props.match.params.key}/unpublish`; + const url = `${globalUrl}/api/v1/workflows/${props.match.params.key}/unpublish`; fetch(url, { method: "POST", headers: { @@ -17960,27 +18003,27 @@ const releaseToConnectLabel = "Release to Connect" body: JSON.stringify(data), credentials: "include", }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for workflow publish :O!"); - } + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for workflow publish :O!"); + } - return response.json(); - }) - .then((responseJson) => { - if (responseJson.reason !== undefined) { - toast("Unpublishing: "+responseJson.reason) - } + return response.json(); + }) + .then((responseJson) => { + if (responseJson.reason !== undefined) { + toast("Unpublishing: " + responseJson.reason) + } - if (responseJson.success === true) { - workflow.public = false - setWorkflow(workflow) - } - }) - .catch((error) => { - toast("Failed publishing: is the workflow valid? Remember to save the workflow first.") - console.log(error.toString()) - }) + if (responseJson.success === true) { + workflow.public = false + setWorkflow(workflow) + } + }) + .catch((error) => { + toast("Failed publishing: is the workflow valid? Remember to save the workflow first.") + console.log(error.toString()) + }) } // This can execute a workflow with firestore. Used for test, as datastore is old and stuff @@ -17996,20 +18039,20 @@ const releaseToConnectLabel = "Release to Connect" // console.log(allowList, userdata.public_username) const leftView = workflow.public === true ? -
    +
    - - - {workflow.name} - - {workflow.validated === true ? - - - - : null} - + + + {workflow.name} + + {workflow.validated === true ? + + + + : null} + This workflow is public and { saveWorkflow(workflow) @@ -18193,7 +18236,7 @@ const releaseToConnectLabel = "Release to Connect"
    : null} - {/* + {/*
    - {userdata.support === true ? - - - Manual Verification: {workflow.validated === undefined || workflow.validated === null || workflow.validated === false ? "Not valided" : "Validated"} - -
    - - Validate Workflow: - - { - workflow.validated = event.target.checked - workflow.user_editing = true - //setUserediting(true) + {userdata.support === true ? + + + Manual Verification: {workflow.validated === undefined || workflow.validated === null || workflow.validated === false ? "Not valided" : "Validated"} + +
    + + Validate Workflow: + + { + workflow.validated = event.target.checked + workflow.user_editing = true + //setUserediting(true) - saveWorkflow(workflow) - }} - /> -
    -
    - : null} + saveWorkflow(workflow) + }} + /> +
    +
    + : null}
    : null} @@ -18335,7 +18377,7 @@ const releaseToConnectLabel = "Release to Connect" marginBottom: 10, padding: 5, backgroundColor: theme.palette.backgroundColor, - borderRadius: theme.palette.borderRadius, + borderRadius: theme.palette.borderRadius, cursor: "pointer", display: "flex", minHeight: 45, @@ -18407,12 +18449,12 @@ const releaseToConnectLabel = "Release to Connect" theme={theme.palette.jsonTheme} style={theme.palette.reactJsonStyle} collapsed={false} - shouldCollapse={(jsonField) => { - return collapseField(jsonField) - }} - iconStyle={theme.palette.jsonIconStyle} - collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength} - displayArrayKey={false} + shouldCollapse={(jsonField) => { + return collapseField(jsonField) + }} + iconStyle={theme.palette.jsonIconStyle} + collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength} + displayArrayKey={false} enableClipboard={(copy) => { handleReactJsonClipboard(copy); }} @@ -18443,42 +18485,42 @@ const releaseToConnectLabel = "Release to Connect" "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAACOCAMAAADkWgEmAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAWlBMVEX4Wj69TDgmKCvkVTwlJyskJiokJikkJSkjJSn4Ykf+6+f5h3L////8xLr5alH/9fT7nYz4Wz/919H5cVn/+vr8qpv4XUL94d35e2X//v38t6v4YUbkVDy8SzcVIzHLAAAAAWJLR0QMgbNRYwAAAAlwSFlzAAARsAAAEbAByCf1VAAAAAd0SU1FB+QGGgsvBZ/GkmwAAAFKSURBVHja7dlrTgMxDEXhFgpTiukL2vLc/zbZQH5N7MmReu4KPmlGN4m9WgGzfhgtaOZxM1rQztNoQDvPowHtTKMB7WxHA2TJkiVLlixIZMmSRYgsWbIIkSVLFiGyZMkiRNZirBcma/eKZEW87ZGsOBxPRFbE+R3Jio/LlciKuH0iWfH1/UNkRSR3RRYruSvyWKldkcjK7IpUVl5X5LLSuiKbldQV6aycrihgZXRFCau/K2pY3V1RxersijJWX1cUsnq6opLV0RW1rNldUc2a2RXlrHldsQBrTlfcLwv5EZm/PLIgkHXKPHyQRzXzYoO8BjIvzcgnBvJBxny+Ih/7zNEIcpDEHLshh5TIkS5zAI5cFzCXK8hVFHNxh1xzQpfC0BV6XWTJkkWILFmyCJElSxYhsmTJIkSWLFmEyJIlixBZsmQB8stk/U3/Yb49pVcDMg4AAAAldEVYdGRhdGU6Y3JlYXRlADIwMjAtMDYtMjZUMTE6NDc6MDUrMDI6MDD8QCPmAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIwLTA2LTI2VDExOjQ3OjA1KzAyOjAwjR2bWgAAAABJRU5ErkJggg==" const size = 40; - const borderRadius = 5 + const borderRadius = 5 if (execution.execution_source === undefined || execution.execution_source === null || execution.execution_source.length === 0) { return ( default ) } if (execution.execution_source === "authgroups") { - const iconMargin = 7 - return ( -
    - -
    + const iconMargin = 7 + return ( +
    + +
    ) - } else if (execution.execution_source === "webhook") { + } else if (execution.execution_source === "webhook") { return ( {"webhook"} trigger.trigger_type === "WEBHOOK") .large_image } - style={{ - width: size, - height: size, - borderRadius: borderRadius, - }} + style={{ + width: size, + height: size, + borderRadius: borderRadius, + }} /> ); } else if (execution.execution_source === "outlook") { @@ -18501,11 +18543,11 @@ const releaseToConnectLabel = "Release to Connect" triggers.find((trigger) => trigger.trigger_type === "EMAIL") .large_image } - style={{ - width: size, - height: size, - borderRadius: borderRadius, - }} + style={{ + width: size, + height: size, + borderRadius: borderRadius, + }} /> ); } else if (execution.execution_source === "schedule") { @@ -18516,11 +18558,11 @@ const releaseToConnectLabel = "Release to Connect" triggers.find((trigger) => trigger.trigger_type === "SCHEDULE") .large_image } - style={{ - width: size, - height: size, - borderRadius: borderRadius, - }} + style={{ + width: size, + height: size, + borderRadius: borderRadius, + }} /> ); } else if (execution.execution_source === "EMAIL") { @@ -18531,19 +18573,19 @@ const releaseToConnectLabel = "Release to Connect" triggers.find((trigger) => trigger.trigger_type === "EMAIL") .large_image } - style={{ - width: size, - height: size, - borderRadius: borderRadius, - }} + style={{ + width: size, + height: size, + borderRadius: borderRadius, + }} /> ); - } else if (execution.execution_source === "ShuffleGPT") { + } else if (execution.execution_source === "ShuffleGPT") { return ( - + ); } else if (execution.execution_source === "pipeline") { return ( @@ -18556,7 +18598,7 @@ const releaseToConnectLabel = "Release to Connect" style={{ width: size, height: size }} /> ); - } + } if ( execution.execution_parent !== null && @@ -18570,11 +18612,11 @@ const releaseToConnectLabel = "Release to Connect" triggers.find((trigger) => trigger.trigger_type === "SUBFLOW") .large_image } - style={{ - width: size, - height: size, - borderRadius: borderRadius, - }} + style={{ + width: size, + height: size, + borderRadius: borderRadius, + }} /> ); } @@ -18583,11 +18625,11 @@ const releaseToConnectLabel = "Release to Connect" {execution.execution_source} ); }; @@ -18732,7 +18774,7 @@ const releaseToConnectLabel = "Release to Connect" console.log("IN useeffectt (2)" + collapsed) return; } - },[]) + }, []) /* componentWillUpdate = (nextProps, nextState) => { console.log(nextProps, nextState) @@ -18750,12 +18792,12 @@ const releaseToConnectLabel = "Release to Connect" theme={theme.palette.jsonTheme} style={theme.palette.reactJsonStyle} collapsed={parsedCollapse} - shouldCollapse={(jsonField) => { - return collapseField(jsonField) - }} - iconStyle={theme.palette.jsonIconStyle} - collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength} - displayArrayKey={false} + shouldCollapse={(jsonField) => { + return collapseField(jsonField) + }} + iconStyle={theme.palette.jsonIconStyle} + collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength} + displayArrayKey={false} enableClipboard={(copy) => { handleReactJsonClipboard(copy); }} @@ -18812,70 +18854,70 @@ const releaseToConnectLabel = "Release to Connect" ) } - const changeExecution = (data) => { - if ((data.result === undefined || data.result === null || data.result.length === 0) && data.status !== "FINISHED" && data.status !== "ABORTED") { - start() - setExecutionRunning(true) - setExecutionRequestStarted(false) - } + const changeExecution = (data) => { + if ((data.result === undefined || data.result === null || data.result.length === 0) && data.status !== "FINISHED" && data.status !== "ABORTED") { + start() + setExecutionRunning(true) + setExecutionRequestStarted(false) + } - var checkStarted = false - if (data.results !== undefined && data.results !== null && data.results.length > 0) { - if (data.execution_argument !== undefined && data.execution_argument !== null && data.execution_argument.includes("too large")) { - setExecutionData({}); - checkStarted = true - start(); - setExecutionRunning(true); - setExecutionRequestStarted(false); - } else { - if (data.results !== undefined && data.results !== null) { - for (let resultkey in data.results) { - if (data.results[resultkey].status !== "SUCCESS") { - continue - } + var checkStarted = false + if (data.results !== undefined && data.results !== null && data.results.length > 0) { + if (data.execution_argument !== undefined && data.execution_argument !== null && data.execution_argument.includes("too large")) { + setExecutionData({}); + checkStarted = true + start(); + setExecutionRunning(true); + setExecutionRequestStarted(false); + } else { + if (data.results !== undefined && data.results !== null) { + for (let resultkey in data.results) { + if (data.results[resultkey].status !== "SUCCESS") { + continue + } - if (data.results[resultkey].result.includes("too large")) { - setExecutionData({}); - checkStarted = true - start(); - setExecutionRunning(true); - setExecutionRequestStarted(false); - break - } - } - } - } - } + if (data.results[resultkey].result.includes("too large")) { + setExecutionData({}); + checkStarted = true + start(); + setExecutionRunning(true); + setExecutionRequestStarted(false); + break + } + } + } + } + } - const cur_execution = { - execution_id: data.execution_id, - authorization: data.authorization, - } + const cur_execution = { + execution_id: data.execution_id, + authorization: data.authorization, + } - setExecutionRequest(cur_execution) - setExecutionModalView(1) + setExecutionRequest(cur_execution) + setExecutionModalView(1) - if (!checkStarted) { - handleUpdateResults(data, cur_execution) + if (!checkStarted) { + handleUpdateResults(data, cur_execution) - if (cy !== undefined && cy !== null) { - cy.elements().removeClass("success-highlight failure-highlight executing-highlight"); - for (let actionKey in data.workflow.actions) { - var actionitem = data.workflow.actions[actionKey] + if (cy !== undefined && cy !== null) { + cy.elements().removeClass("success-highlight failure-highlight executing-highlight"); + for (let actionKey in data.workflow.actions) { + var actionitem = data.workflow.actions[actionKey] - handleColoring(actionitem.id, "", actionitem.label) - } + handleColoring(actionitem.id, "", actionitem.label) + } - for (let resultKey in data.results) { - var item = data.results[resultKey] + for (let resultKey in data.results) { + var item = data.results[resultKey] - handleColoring(item.action.id, item.status, item.action.label) - } - } + handleColoring(item.action.id, item.status, item.action.label) + } + } - setExecutionData(data) - } - } + setExecutionData(data) + } + } const ShowCopyingTooltip = () => { const [showCopying, setShowCopying] = React.useState(true) @@ -18909,14 +18951,14 @@ const releaseToConnectLabel = "Release to Connect" onClose={() => { setExecutionModalOpen(false) - const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; - const newitem = removeParam("execution_id", cursearch); - navigate(curpath + newitem) + const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; + const newitem = removeParam("execution_id", cursearch); + navigate(curpath + newitem) + }} + style={{ + resize: "both", + overflow: "auto", }} - style={{ - resize: "both", - overflow: "auto", - }} hideBackdrop={false} variant="temporary" BackdropProps={{ @@ -18934,8 +18976,8 @@ const releaseToConnectLabel = "Release to Connect" fontSize: 18, borderLeft: theme.palette.defaultBorder, - borderRadius: theme.palette.borderRadius, - backgroundColor: "black", + borderRadius: theme.palette.borderRadius, + backgroundColor: "black", }, }} > @@ -18958,91 +19000,92 @@ const releaseToConnectLabel = "Release to Connect" : null} {executionModalView === 0 ? (
    -
    - -

    - - All Workflow Runs -

    -
    - - - - - -
    - - + + +
    + + + + { - getWorkflowExecution(props.match.params.key, "", executionFilter) - }} - color="secondary" - > - - Refresh Runs - - - + style={{ marginTop: 5, maxHeight: 50, overflow: "hidden", }}> > - - - - - + + + + +
    result.status === "SKIPPED").length - : 0 + data.results.filter((result) => result.status === "SKIPPED").length + : 0 const timestamp = new Date(data.started_at * 1000) .toLocaleString("en-GB") @@ -19081,25 +19124,25 @@ const releaseToConnectLabel = "Release to Connect" ? data.workflow.actions.length : 0; - if (data.workflow.triggers !== undefined && data.workflow.triggers !== null) { - for (let triggerkey in data.workflow.triggers) { - const trigger = data.workflow.triggers[triggerkey]; - if ( - (trigger.app_name === "User Input" && - trigger.trigger_type === "USERINPUT") || - (trigger.app_name === "Shuffle Workflow" && - trigger.trigger_type === "SUBFLOW") - ) { - calculatedResult += 1; - } - } - } + if (data.workflow.triggers !== undefined && data.workflow.triggers !== null) { + for (let triggerkey in data.workflow.triggers) { + const trigger = data.workflow.triggers[triggerkey]; + if ( + (trigger.app_name === "User Input" && + trigger.trigger_type === "USERINPUT") || + (trigger.app_name === "Shuffle Workflow" && + trigger.trigger_type === "SUBFLOW") + ) { + calculatedResult += 1; + } + } + } - const foundnotifications = data.notifications_created === undefined || data.notifications_created === null ? 0 : data.notifications_created + const foundnotifications = data.notifications_created === undefined || data.notifications_created === null ? 0 : data.notifications_created return ( - - {/**/} + + {/**/}
    1 Mb in cloud var checkStarted = false if (data.results !== undefined && data.results !== null && data.results.length > 0) { - if (data.execution_argument !== undefined && data.execution_argument !== null && data.execution_argument.includes("too large")) { - setExecutionData({}); - checkStarted = true - start(); - setExecutionRunning(true); - setExecutionRequestStarted(false); - } else { - if (data.results !== undefined && data.results !== null) { - for (let resultkey in data.results) { - if (data.results[resultkey].status !== "SUCCESS") { - continue - } + if (data.execution_argument !== undefined && data.execution_argument !== null && data.execution_argument.includes("too large")) { + setExecutionData({}); + checkStarted = true + start(); + setExecutionRunning(true); + setExecutionRequestStarted(false); + } else { + if (data.results !== undefined && data.results !== null) { + for (let resultkey in data.results) { + if (data.results[resultkey].status !== "SUCCESS") { + continue + } - if (data.results[resultkey].result.includes("too large")) { - setExecutionData({}); - checkStarted = true - start(); - setExecutionRunning(true); - setExecutionRequestStarted(false); - break - } - } - } - } - } + if (data.results[resultkey].result.includes("too large")) { + setExecutionData({}); + checkStarted = true + start(); + setExecutionRunning(true); + setExecutionRequestStarted(false); + break + } + } + } + } + } const cur_execution = { execution_id: data.execution_id, @@ -19164,20 +19207,20 @@ const releaseToConnectLabel = "Release to Connect" if (!checkStarted) { handleUpdateResults(data, cur_execution) - if (cy !== undefined && cy !== null) { - cy.elements().removeClass("success-highlight failure-highlight executing-highlight"); - for (let actionKey in data.workflow.actions) { - var actionitem = data.workflow.actions[actionKey] + if (cy !== undefined && cy !== null) { + cy.elements().removeClass("success-highlight failure-highlight executing-highlight"); + for (let actionKey in data.workflow.actions) { + var actionitem = data.workflow.actions[actionKey] - handleColoring(actionitem.id, "", actionitem.label) - } + handleColoring(actionitem.id, "", actionitem.label) + } - for (let resultKey in data.results) { - var item = data.results[resultKey] + for (let resultKey in data.results) { + var item = data.results[resultKey] - handleColoring(item.action.id, item.status, item.action.label) - } - } + handleColoring(item.action.id, item.status, item.action.label) + } + } setExecutionData(data) } @@ -19190,32 +19233,32 @@ const releaseToConnectLabel = "Release to Connect" width: lastExecution === data.execution_id ? 4 : 2, backgroundColor: statusColor, marginRight: 5, - maxHeight: 40, + maxHeight: 40, }} /> - 0 ? ` Authgroup: ${data.authgroup}` : '')} - placement="left" - > -
    - {getExecutionSourceImage(data)} -
    -
    + 0 ? ` Authgroup: ${data.authgroup}` : '')} + placement="left" + > +
    + {getExecutionSourceImage(data)} +
    +
    {timestamp} @@ -19229,29 +19272,30 @@ const releaseToConnectLabel = "Release to Connect"
    - {successActions} + {skippedActions > 0 ? skippedActions : {skippedActions}} = {calculatedResult} + {successActions} + {skippedActions > 0 ? skippedActions : {skippedActions}} = {calculatedResult}
    ) : null}
    - - {foundnotifications > 0 ? - - { - e.preventDefault() - e.stopPropagation() - window.open(`/admin?admin_tab=notifications&workflow=${data.workflow.id}&execution_id=${data.execution_id}`, "_blank") - }} - /> - - : null} + + {foundnotifications > 0 ? + + { + e.preventDefault() + e.stopPropagation() + window.open(`/admin?admin_tab=notifications&workflow=${data.workflow.id}&execution_id=${data.execution_id}`, "_blank") + }} + /> + + : null} {lastExecution === data.execution_id ? ( @@ -19271,84 +19315,85 @@ const releaseToConnectLabel = "Release to Connect"
    -
    +
    ); })}
    ) : ( - -
    - - No executions found for the '{executionFilter}' filter. - + +
    + + No executions found for the '{executionFilter}' filter. + - -
    -
    + +
    +
    )}
    ) : (
    - - + { + setExecutionRunning(false); + stop(); + // getWorkflowExecution(currentWorkflow.id, ""); + getWorkflowExecution(props.match.params.key, ""); + setExecutionModalView(0); + setLastExecution(executionData.execution_id); + }} > - { + setExecutionRunning(false); + stop() + }} + > + + + +

    { - setExecutionRunning(false); - stop(); - getWorkflowExecution(props.match.params.key, ""); - setExecutionModalView(0); - setLastExecution(executionData.execution_id); - }} - > - { - setExecutionRunning(false); - stop() - }} - > - - - -

    { const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; const newitem = removeParam("execution_id", cursearch); navigate(curpath + newitem) setExecutionRunning(false); stop() }} - > - See more runs -

    -
    - - + > + See more runs +

    +
    +
    +
    { - const skip_popup = true + const skip_popup = true executeWorkflow( executionData.execution_argument, executionData.start, lastSaved, - skip_popup, + skip_popup, ) if (executionText === undefined || executionText === null || executionText.length === 0) { @@ -19389,77 +19434,77 @@ const releaseToConnectLabel = "Release to Connect" - - - - - + changeExecution(data) + }} + > + + + + - - - - - + changeExecution(data) + }} + > + + + + {executionData.status === "EXECUTING" ? ( - ) : + ) : - { - e.preventDefault() - e.stopPropagation() - window.open(`/admin?admin_tab=notifications&workflow=${executionData.workflow.id}&execution_id=${executionData.execution_id}`, "_blank") - }} - /> + { + e.preventDefault() + e.stopPropagation() + window.open(`/admin?admin_tab=notifications&workflow=${executionData.workflow.id}&execution_id=${executionData.execution_id}`, "_blank") + }} + /> - } + } - {isCloud ? + {isCloud ? { - toast("Opening logs in a new tab") + toast("Opening logs in a new tab") - setTimeout(() => { - window.open(`/api/v1/workflows/search/${executionData.execution_id}`, "_blank") - }, 250) + setTimeout(() => { + window.open(`/api/v1/workflows/search/${executionData.execution_id}`, "_blank") + }, 250) }} > - + - : null} + : null}
    - {executionData.workflow !== undefined && executionData.workflow !== null && executionData.workflow.actions !== undefined && executionData.workflow.actions !== null && executionData.workflow.actions.length > 0 ? -
    - - - {/*envStatus === "success" ? - - - - : envStatus === "failure" ? - - - - : null*/} - - Env      - - - { - window.open("/admin?tab=locations", "_blank") - }}> - {executionData.workflow.actions[0].environment} - - -
    - : null} {executionData.status !== undefined && executionData.status.length > 0 ? (
    @@ -19576,7 +19596,7 @@ const releaseToConnectLabel = "Release to Connect" executionData.execution_source !== null && executionData.execution_source.length > 0 && executionData.execution_source !== "default" || - (executionData.authgroup !== undefined && executionData.authgroup !== null && executionData.authgroup.length > 0) ? ( + (executionData.authgroup !== undefined && executionData.authgroup !== null && executionData.authgroup.length > 0) ? (
    Source    @@ -19584,53 +19604,53 @@ const releaseToConnectLabel = "Release to Connect" - {executionData.execution_source === "authgroups" || (executionData.authgroup !== undefined && executionData.authgroup !== null && executionData.authgroup.length > 0) ? - - Auth Group '{executionData.authgroup !== undefined && executionData.authgroup !== null && executionData.authgroup.length > 0 ? `${executionData.authgroup}` : null}' - - : - executionData.execution_parent !== null && - executionData.execution_parent !== undefined && - executionData.execution_parent.length > 0 ? ( - executionData.execution_source === props.match.params.key ? - { - getWorkflowExecution( - props.match.params.key, - executionData.execution_parent - ); - }} - > - Parent Execution - - : - - Parent Workflow - + {executionData.execution_source === "authgroups" || (executionData.authgroup !== undefined && executionData.authgroup !== null && executionData.authgroup.length > 0) ? + + Auth Group '{executionData.authgroup !== undefined && executionData.authgroup !== null && executionData.authgroup.length > 0 ? `${executionData.authgroup}` : null}' + + : + executionData.execution_parent !== null && + executionData.execution_parent !== undefined && + executionData.execution_parent.length > 0 ? ( + executionData.execution_source === props.match.params.key ? + { + getWorkflowExecution( + props.match.params.key, + executionData.execution_parent + ); + }} + > + Parent Execution + + : + + Parent Workflow + ) - : - executionData.execution_source === "questions" || executionData.execution_source === "web" || executionData.execution_source === "form" || executionData.execution_source === "forms" ? - - Form - - : - executionData.execution_source + : + executionData.execution_source === "questions" || executionData.execution_source === "web" || executionData.execution_source === "form" || executionData.execution_source === "forms" ? + + Form + + : + executionData.execution_source }
    @@ -19661,27 +19681,53 @@ const releaseToConnectLabel = "Release to Connect" ) : null} - {userdata.support === true && executionData.workflow !== undefined && executionData.workflow !== null && executionData.status !== "EXECUTING" ? -
    - 0 ? +
    + - apps={apps} - workflow={executionData.workflow} - getParents={getParents} + {/*envStatus === "success" ? + + + + : envStatus === "failure" ? + + + + : null*/} - execution={executionData} - /> -
    - : null} + Location   + + + { + window.open("/admin?tab=locations", "_blank") + }}> + {executionData.workflow.actions[0].environment} + + +
    + : null} + + {userdata.support === true && executionData.workflow !== undefined && executionData.workflow !== null && executionData.status !== "EXECUTING" ? +
    + +
    + : null}
    - {executionData.execution_argument !== undefined && executionData.execution_argument !== null && + {executionData.execution_argument !== undefined && executionData.execution_argument !== null && executionData.execution_argument.length > 1 ? parsedExecutionArgument() - : - null} + : + null}
    {executionData.status !== undefined && - executionData.status !== "ABORTED" && - executionData.status !== "FINISHED" && - executionData.status !== "FAILURE" && - executionData.status !== "WAITING" && - !(executionData.results === undefined || executionData.results === null || (executionData.results.length === 0 && executionData.status === "EXECUTING")) ? ( + executionData.status !== "ABORTED" && + executionData.status !== "FINISHED" && + executionData.status !== "FAILURE" && + executionData.status !== "WAITING" && + !(executionData.results === undefined || executionData.results === null || (executionData.results.length === 0 && executionData.status === "EXECUTING")) ? (
    - { - console.log(environments, defaultEnvironmentIndex, nonskippedResults) - }} /> + { + console.log(environments, defaultEnvironmentIndex, nonskippedResults) + }} /> {environments.length > 0 && defaultEnvironmentIndex < environments.length && nonskippedResults.length === 0 && environments[defaultEnvironmentIndex].Name !== "Cloud" ? @@ -19738,93 +19784,76 @@ const releaseToConnectLabel = "Release to Connect"
    { - executionData.results === undefined || - executionData.results === null || - (executionData.results.length === 0 && executionData.status === "EXECUTING") ? ( + executionData.results === undefined || + executionData.results === null || + (executionData.results.length === 0 && executionData.status === "EXECUTING") ? ( -
    - - {environments.length > 0 && defaultEnvironmentIndex < environments.length && nonskippedResults.length === 0 && environments[defaultEnvironmentIndex].Name !== "Cloud" ? - - No results yet. Is Orborus running for the "{environments[defaultEnvironmentIndex].Name}" environment? Learn more. If the Workflow doesn't start within 30 seconds with Orborus running, contact support: support@shuffler.io - - : - null} -
    - ) : ( - executionData.results.map((data, index) => { - if (executionData.results.length !== 1 && !showSkippedActions && (data.status === "SKIPPED")) { - return null; - } - - // FIXME: The latter replace doens't really work if ' is used in a string - var showResult = data.result.trim(); - const validate = validateJson(showResult); - - const curapp = apps.find( - (a) => - a.name === data.action.app_name && - a.app_version === data.action.app_version - ); - const imgsize = 50; - const statusColor = - data.status === "FINISHED" || data.status === "SUCCESS" - ? green - : data.status === "ABORTED" || data.status === "FAILURE" - ? "red" - : yellow; - - var imgSrc = curapp === undefined ? "" : curapp.large_image; - if (imgSrc.length === 0 && workflow.actions !== undefined && workflow.actions !== null) { - // Look for the node in the workflow - const action = workflow.actions.find( - (action) => action.id === data.action.id - ) - if (action !== undefined && action !== null) { - imgSrc = action.large_image; +
    + + {environments.length > 0 && defaultEnvironmentIndex < environments.length && nonskippedResults.length === 0 && environments[defaultEnvironmentIndex].Name !== "Cloud" ? + + No results yet. Is Orborus running for the "{environments[defaultEnvironmentIndex].Name}" environment? Learn more. If the Workflow doesn't start within 30 seconds with Orborus running, contact support: support@shuffler.io + + : + null} +
    + ) : ( + executionData.results.map((data, index) => { + if (executionData.results.length !== 1 && !showSkippedActions && (data.status === "SKIPPED")) { + return null; } - } - if ((imgSrc === undefined || imgSrc === null || imgSrc.length === 0) && cy !== undefined && cy !== null) { - const foundnode = cy.getElementById(data.action.id) - if (foundnode !== undefined && foundnode !== null && foundnode.length > 0) { - // FIXME: Find image from cytoscape action - } else { - for (let actionkey in workflow.actions) { - if (workflow.actions[actionkey].app_name === data.action.app_name || workflow.actions[actionkey].id === data.action.id || workflow.actions[actionkey].label === data.action.label || workflow.actions[actionkey].name === data.action.name) { + // FIXME: The latter replace doens't really work if ' is used in a string + var showResult = data.result.trim(); + const validate = validateJson(showResult); - if (workflow.actions[actionkey].large_image !== undefined && workflow.actions[actionkey].large_image !== null && workflow.actions[actionkey].large_image.length > 0) { - imgSrc = workflow.actions[actionkey].large_image - break - } - } - } - } - } - - - var actionimg = - curapp === null ? null : ( - {data.action.app_name} + const curapp = apps.find( + (a) => + a.name === data.action.app_name && + a.app_version === data.action.app_version ); + const imgsize = 50; + const statusColor = + data.status === "FINISHED" || data.status === "SUCCESS" + ? green + : data.status === "ABORTED" || data.status === "FAILURE" + ? "red" + : yellow; - if (triggers.length > 2) { - if (data.action.app_name === "shuffle-subflow") { - const parsedImage = triggers[3].large_image; - actionimg = ( + var imgSrc = curapp === undefined ? "" : curapp.large_image; + if (imgSrc.length === 0 && workflow.actions !== undefined && workflow.actions !== null) { + // Look for the node in the workflow + const action = workflow.actions.find( + (action) => action.id === data.action.id + ) + if (action !== undefined && action !== null) { + imgSrc = action.large_image; + } + } + + if ((imgSrc === undefined || imgSrc === null || imgSrc.length === 0) && cy !== undefined && cy !== null) { + const foundnode = cy.getElementById(data.action.id) + if (foundnode !== undefined && foundnode !== null && foundnode.length > 0) { + // FIXME: Find image from cytoscape action + } else { + for (let actionkey in workflow.actions) { + if (workflow.actions[actionkey].app_name === data.action.app_name || workflow.actions[actionkey].id === data.action.id || workflow.actions[actionkey].label === data.action.label || workflow.actions[actionkey].name === data.action.name) { + + if (workflow.actions[actionkey].large_image !== undefined && workflow.actions[actionkey].large_image !== null && workflow.actions[actionkey].large_image.length > 0) { + imgSrc = workflow.actions[actionkey].large_image + break + } + } + } + } + } + + + var actionimg = + curapp === null ? null : ( {"Shuffle ); - } - if (data.action.app_name === "User Input") { - actionimg = ( - {"Shuffle - ); - } - } + if (triggers.length > 2) { + if (data.action.app_name === "shuffle-subflow") { + const parsedImage = triggers[3].large_image; + actionimg = ( + {"Shuffle + ); + } - if (data.action.app_name === "Shuffle Tools" && data.action.id !== undefined && cy !== undefined) { - const nodedata = cy.getElementById(data.action.id).data(); - //if (nodedata !== undefined && nodedata !== null && nodedata.fillstyle === "linear-gradient") { - if (nodedata !== undefined && nodedata !== null) { - var imgStyle = { - marginRight: 20, - width: imgsize, - height: imgsize, - border: `2px solid ${statusColor}`, - borderRadius: executionData.start === data.action.id ? 25 : 5, - background: `linear-gradient(to right, ${nodedata.fillGradient})`, - }; - - actionimg = ( - {nodedata.label} - ); - } else { - //console.log("Node not found: ", nodedata) - actionimg = ( - {data.action.app_name} - ) - } - } - - if (validate.valid && typeof validate.result === "string") { - validate.result = JSON.parse(validate.result); - } - - if (validate.valid && typeof validate.result === "object") { - if ( - validate.result.result !== undefined && - validate.result.result !== null - ) { - try { - validate.result.result = JSON.parse(validate.result.result); - } catch (e) { - //console.log("ERROR PARSING: ", e) + if (data.action.app_name === "User Input") { + actionimg = ( + {"Shuffle + ); } } - } + if (data.action.app_name === "Shuffle Tools" && data.action.id !== undefined && cy !== undefined) { + const nodedata = cy.getElementById(data.action.id).data(); + //if (nodedata !== undefined && nodedata !== null && nodedata.fillstyle === "linear-gradient") { + if (nodedata !== undefined && nodedata !== null) { + var imgStyle = { + marginRight: 20, + width: imgsize, + height: imgsize, + border: `2px solid ${statusColor}`, + borderRadius: executionData.start === data.action.id ? 25 : 5, + background: `linear-gradient(to right, ${nodedata.fillGradient})`, + }; - var similarActionsView = null - if (data.similar_actions !== undefined && data.similar_actions !== null) { - var minimumMatch = 85 - var matching_executions = [] - if (data.similar_actions !== undefined && data.similar_actions !== null) { - for (let [k,kval] in Object.entries(data.similar_actions)){ - if (data.similar_actions.hasOwnProperty(k)) { - if (data.similar_actions[k].similarity > minimumMatch) { - matching_executions.push(data.similar_actions[k].execution_id) - } - } - } - } - - if (matching_executions.length !== 0) { - var parsed_url = matching_executions.join(",") - - similarActionsView = - - + ); + } else { + //console.log("Node not found: ", nodedata) + actionimg = ( + {data.action.app_name} { - navigate(`?execution_highlight=${parsed_url}`) - }} - > - - - + /> + ) + } } - } - const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; - const chosenNodeId = new URLSearchParams(cursearch).get("node"); - const highlightNode = chosenNodeId !== null && chosenNodeId !== undefined && chosenNodeId !== "" && chosenNodeId === data.action.id + if (validate.valid && typeof validate.result === "string") { + validate.result = JSON.parse(validate.result); + } - return ( -
    { - if (cy == undefined || cy == null) { - return - } - - var currentnode = cy.getElementById(data.action.id); - if (currentnode !== undefined && currentnode !== null && currentnode.length !== 0) { - currentnode.addClass("shuffle-hover-highlight"); + if (validate.valid && typeof validate.result === "object") { + if ( + validate.result.result !== undefined && + validate.result.result !== null + ) { + try { + validate.result.result = JSON.parse(validate.result.result); + } catch (e) { + //console.log("ERROR PARSING: ", e) } + } + } - // Add a hover highlight - //var copyText = document.getElementById( - // "copy_element_shuffle" - //) - }} - onMouseOut={() => { - if (cy == undefined || cy == null) { - return - } - - var currentnode = cy.getElementById(data.action.id); - if (currentnode.length !== 0) { - currentnode.removeClass("shuffle-hover-highlight"); + var similarActionsView = null + if (data.similar_actions !== undefined && data.similar_actions !== null) { + var minimumMatch = 85 + var matching_executions = [] + if (data.similar_actions !== undefined && data.similar_actions !== null) { + for (let [k, kval] in Object.entries(data.similar_actions)) { + if (data.similar_actions.hasOwnProperty(k)) { + if (data.similar_actions[k].similarity > minimumMatch) { + matching_executions.push(data.similar_actions[k].execution_id) + } + } } - }} - > -
    -
    - { - if (cy !== undefined) { - const oldstartnode = cy.getElementById(data.action.id); - //console.log("FOUND NODe: ", oldstartnode) - if (oldstartnode !== undefined && oldstartnode !== null) { - const foundname = oldstartnode.data("label") - if (foundname !== undefined && foundname !== null) { - data.action.label = foundname - } - } + } - //console.log("Click data: ", data) - //data.action.label = "" - setSelectedResult(data); - setActiveDialog("result") - setCodeModalOpen(true); - } else { - toast("Please wait until the workflow is loaded and try again") - setCodeModalOpen(true) - setSelectedResult(data) + if (matching_executions.length !== 0) { + var parsed_url = matching_executions.join(",") - } - }} + similarActionsView = + - - - - - {actionimg} -
    -
    { + navigate(`?execution_highlight=${parsed_url}`) }} > - {data.action.label === undefined || data.action.label === null || data.action.label === "" ? data.action.label : data.action.label.replaceAll("_", " ")} - -
    -
    - - {data.action.name} - + + + + } + } + + const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search; + const chosenNodeId = new URLSearchParams(cursearch).get("node"); + const highlightNode = chosenNodeId !== null && chosenNodeId !== undefined && chosenNodeId !== "" && chosenNodeId === data.action.id + + return ( +
    { + if (cy == undefined || cy == null) { + return + } + + var currentnode = cy.getElementById(data.action.id); + if (currentnode !== undefined && currentnode !== null && currentnode.length !== 0) { + currentnode.addClass("shuffle-hover-highlight"); + } + + // Add a hover highlight + + //var copyText = document.getElementById( + // "copy_element_shuffle" + //) + }} + onMouseOut={() => { + if (cy == undefined || cy == null) { + return + } + + var currentnode = cy.getElementById(data.action.id); + if (currentnode.length !== 0) { + currentnode.removeClass("shuffle-hover-highlight"); + } + }} + > +
    +
    + { + if (cy !== undefined) { + const oldstartnode = cy.getElementById(data.action.id); + //console.log("FOUND NODe: ", oldstartnode) + if (oldstartnode !== undefined && oldstartnode !== null) { + const foundname = oldstartnode.data("label") + if (foundname !== undefined && foundname !== null) { + data.action.label = foundname + } + } + + //console.log("Click data: ", data) + //data.action.label = "" + setSelectedResult(data); + setActiveDialog("result") + setCodeModalOpen(true); + } else { + toast("Please wait until the workflow is loaded and try again") + setCodeModalOpen(true) + setSelectedResult(data) + + } + }} + > + + + + + {actionimg} +
    +
    + {data.action.label === undefined || data.action.label === null || data.action.label === "" ? data.action.label : data.action.label.replaceAll("_", " ")} + +
    +
    + + {data.action.name} + +
    -
    - {data.action.app_name === "shuffle-subflow" && - validate.result.success !== undefined && - validate.result.success === true ? ( - - {validate.valid && - data.action.parameters !== undefined && - data.action.parameters !== null && - data.action.parameters.length > 0 ? ( - data.action.parameters[0].value === - props.match.params.key ? ( - { - getWorkflowExecution( - props.match.params.key, - validate.result.execution_id - ); - }} - > - - + {data.action.app_name === "shuffle-subflow" && + validate.result.success !== undefined && + validate.result.success === true ? ( + + {validate.valid && + data.action.parameters !== undefined && + data.action.parameters !== null && + data.action.parameters.length > 0 ? ( + data.action.parameters[0].value === + props.match.params.key ? ( + { + getWorkflowExecution( + props.match.params.key, + validate.result.execution_id + ); + }} + > + + + ) : ( + { }} + > + + + ) ) : ( - { }} - > - - - ) - ) : ( - "" - )} - - ) : null} -
    - - { data.status !== "SUCCESS" ? -
    - - Status  - - - {data.status} - - {similarActionsView} -
    - : null} - - {validate.valid ? ( - - { - return collapseField(jsonField) - }} - iconStyle={theme.palette.jsonIconStyle} - collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength} - displayArrayKey={false} - enableClipboard={(copy) => { - handleReactJsonClipboard(copy); - }} - displayDataTypes={false} - onSelect={(select) => { - HandleJsonCopy(showResult, select, data.action.label); - console.log("SELECTED!: ", select); - }} - name={"Results for " + data.action.label} - /> - - - ) : ( -
    - - Result  - - - {data.result} - + "" + )} + + ) : null}
    - )} -
    - ); - }) - )} + + {data.status !== "SUCCESS" ? +
    + + Status  + + + {data.status} + + {similarActionsView} +
    + : null} + + {validate.valid ? ( + + { + return collapseField(jsonField) + }} + iconStyle={theme.palette.jsonIconStyle} + collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength} + displayArrayKey={false} + enableClipboard={(copy) => { + handleReactJsonClipboard(copy); + }} + displayDataTypes={false} + onSelect={(select) => { + HandleJsonCopy(showResult, select, data.action.label); + console.log("SELECTED!: ", select); + }} + name={"Results for " + data.action.label} + /> + + + ) : ( +
    + + Result  + + + {data.result} + +
    + )} +
    + ); + }) + )}
    )} @@ -20203,45 +20249,45 @@ const releaseToConnectLabel = "Release to Connect" const [open, setOpen] = React.useState(false) const showVariable = data.value.length < 60 - // Check if it's valid JSON - const checked = validateJson(data.value.trim()) + // Check if it's valid JSON + const checked = validateJson(data.value.trim()) - if (data.name === "shuffle_action_logs" && data.value !== undefined && data.value !== null && data.value.length > 0 && data.value.includes("add env SHUFFLE_LOGS_DISABLED")) { - return ( -
    - - Action Logs - - - Logs for an action are not available without an onprem environment with the SHUFFLE_LOGS_DISABLED environment variable set to false: SHUFFLE_LOGS_DISABLED=false. Logs are enabled by default, except in scale mode. - -
    - ) - } + if (data.name === "shuffle_action_logs" && data.value !== undefined && data.value !== null && data.value.length > 0 && data.value.includes("add env SHUFFLE_LOGS_DISABLED")) { + return ( +
    + + Action Logs + + + Logs for an action are not available without an onprem environment with the SHUFFLE_LOGS_DISABLED environment variable set to false: SHUFFLE_LOGS_DISABLED=false. Logs are enabled by default, except in scale mode. + +
    + ) + } - var showlink = false - if (data.name.endsWith("-Url")) { - //data.name = data.name.toLowerCase().replaceAll("-", "_") - if (data.value.startsWith(", ")) { - data.value = data.value.substring(2) - } + var showlink = false + if (data.name.endsWith("-Url")) { + //data.name = data.name.toLowerCase().replaceAll("-", "_") + if (data.value.startsWith(", ")) { + data.value = data.value.substring(2) + } - if (data.value.startsWith("http") || (data.value.startsWith("/") && data.value.includes("?"))) { - showlink = true - } - } + if (data.value.startsWith("http") || (data.value.startsWith("/") && data.value.includes("?"))) { + showlink = true + } + } return (
    {data.value.length > 60 || checked.valid ? {data.name} - {checked.valid ? - - : null} - {showVariable ? data.value : null} + {checked.valid ? + + : null} + {showVariable ? data.value : null} : @@ -20277,40 +20323,40 @@ const releaseToConnectLabel = "Release to Connect" } {open ? - checked.valid ? - { - return collapseField(jsonField) - }} - iconStyle={theme.palette.jsonIconStyle} - collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength} - displayArrayKey={false} - displayDataTypes={false} - name={"Parsed data for variable " + data.name} - /> - : - { - if (showlink) { - e.preventDefault() - e.stopPropagation() - window.open(data.value, "_blank") - } - }} - color={showlink ? "inherit" : "textSecondary"} - > - {data.value} - + checked.valid ? + { + return collapseField(jsonField) + }} + iconStyle={theme.palette.jsonIconStyle} + collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength} + displayArrayKey={false} + displayDataTypes={false} + name={"Parsed data for variable " + data.name} + /> + : + { + if (showlink) { + e.preventDefault() + e.stopPropagation() + window.open(data.value, "_blank") + } + }} + color={showlink ? "inherit" : "textSecondary"} + > + {data.value} + : null}
    ) @@ -20320,258 +20366,258 @@ const releaseToConnectLabel = "Release to Connect" // Should probably put this on the backend instead when notifications are made :)) const getErrorSuggestion = (result) => { - if (result === undefined || result === null) { - return "" - } + if (result === undefined || result === null) { + return "" + } - // Check if array with json inside to handle one item at a time~ - if (typeof result === "object" && result.length !== undefined) { - if (result.length > 0) { - // Check type inside - if (typeof result[0] === "object") { - result = result[0] - } - } - } + // Check if array with json inside to handle one item at a time~ + if (typeof result === "object" && result.length !== undefined) { + if (result.length > 0) { + // Check type inside + if (typeof result[0] === "object") { + result = result[0] + } + } + } - if (result.success === true && result.status === 200) { - if (result.body !== undefined && result.body !== null) { - const stringbody = result.body.toString() - if ((stringbody.startsWith("{") && stringbody.endsWith("}")) || (stringbody.startsWith("[") && stringbody.endsWith("]"))) { - return "" - } + if (result.success === true && result.status === 200) { + if (result.body !== undefined && result.body !== null) { + const stringbody = result.body.toString() + if ((stringbody.startsWith("{") && stringbody.endsWith("}")) || (stringbody.startsWith("[") && stringbody.endsWith("]"))) { + return "" + } - if (stringbody.length > 1000) { - return "Body looks to be big in a standard format. Consider using the 'To File' parameter to automatically make it into a file." - } - } - } + if (stringbody.length > 1000) { + return "Body looks to be big in a standard format. Consider using the 'To File' parameter to automatically make it into a file." + } + } + } - if (result.status === 429) { - return "Rate limit exceeded. Consider using a different API key or wait a bit before trying again." - } + if (result.status === 429) { + return "Rate limit exceeded. Consider using a different API key or wait a bit before trying again." + } - if (result.status === 405) { - return "Method not allowed. Check the URL to ensure it has all the required parameters. If you keep getting a 405, please forward a screenshot of this to support@shuffler.io" - } + if (result.status === 405) { + return "Method not allowed. Check the URL to ensure it has all the required parameters. If you keep getting a 405, please forward a screenshot of this to support@shuffler.io" + } - if (result.status === 415) { - return "Content-Type header missing or wrong. Please add the correct Content-Type header and save the workflow." - } + if (result.status === 415) { + return "Content-Type header missing or wrong. Please add the correct Content-Type header and save the workflow." + } - if (result.status === 401) { - return "Authentication failed (401). The URL or auth key is wrong. Check the body of the result for more information." - } + if (result.status === 401) { + return "Authentication failed (401). The URL or auth key is wrong. Check the body of the result for more information." + } - if (result.status === 403) { - return "Authorization failed (403). The API user most likely doesn't have the correct permissions. Check the body of the result for more information." - } + if (result.status === 403) { + return "Authorization failed (403). The API user most likely doesn't have the correct permissions. Check the body of the result for more information." + } - if (result.status === 404) { - return "The URL, or content of the URL is incorrect. Check it and try again." - } + if (result.status === 404) { + return "The URL, or content of the URL is incorrect. Check it and try again." + } - if (result.status === 400) { - return "The queries or data sent to the API is most likely wrong (400). Check the body of the result for more information." - } + if (result.status === 400) { + return "The queries or data sent to the API is most likely wrong (400). Check the body of the result for more information." + } - if (result.status === 200 || result.status === 201 || result.status === 204) { - return "It looks like the result was successful! If it didn't work, make sure to check if the body you are sending was correct." - } + if (result.status === 200 || result.status === 201 || result.status === 204) { + return "It looks like the result was successful! If it didn't work, make sure to check if the body you are sending was correct." + } - // Validate and check for newlines - if (result.success !== false) { + // Validate and check for newlines + if (result.success !== false) { - var stringjson = result - const valid = validateJson(stringjson, true) - if (valid.valid === false) { - if (stringjson.startsWith("{") && stringjson.endsWith("}")) { - // Look for newline - if (stringjson.includes("\n") && !stringjson.includes("\n")) { - return "Looks like you have a newline problem. Consider using the | replace: '\n', '\\n' }} filter in Liquid." - } else { - return "The result looks like it should be JSON, but is invalid. Look for potential single quotes instead of double quotes, missing commas or newlines" - } - } - } + var stringjson = result + const valid = validateJson(stringjson, true) + if (valid.valid === false) { + if (stringjson.startsWith("{") && stringjson.endsWith("}")) { + // Look for newline + if (stringjson.includes("\n") && !stringjson.includes("\n")) { + return "Looks like you have a newline problem. Consider using the | replace: '\n', '\\n' }} filter in Liquid." + } else { + return "The result looks like it should be JSON, but is invalid. Look for potential single quotes instead of double quotes, missing commas or newlines" + } + } + } - //return "" - } + //return "" + } - try { - stringjson = JSON.stringify(result) - } catch (e) { - } + try { + stringjson = JSON.stringify(result) + } catch (e) { + } - stringjson = stringjson.toLowerCase() - if (stringjson.includes("localhost")) { - return "You can't use localhost in apps. Use the external ip or url of the server instead" - } + stringjson = stringjson.toLowerCase() + if (stringjson.includes("localhost")) { + return "You can't use localhost in apps. Use the external ip or url of the server instead" + } - if (stringjson.includes("manifest unknown")) { - return "The app's Docker Image is not available in the environment yet. Re-run the app to force a re-download of the app. If the problem persists, contact support" - } + if (stringjson.includes("manifest unknown")) { + return "The app's Docker Image is not available in the environment yet. Re-run the app to force a re-download of the app. If the problem persists, contact support" + } - if (result.status !== 200 && result.url !== undefined && result.url !== null && typeof result.url === "string" && (result.url.includes("192.168") || result.url.includes("172.16") || result.url.includes("10.0"))) { - return "Consider whether your Orborus environment can connect to a local IP or not." - } + if (result.status !== 200 && result.url !== undefined && result.url !== null && typeof result.url === "string" && (result.url.includes("192.168") || result.url.includes("172.16") || result.url.includes("10.0"))) { + return "Consider whether your Orborus environment can connect to a local IP or not." + } - if (stringjson.includes("kms/")) { - return "KMS authentication most likely failed. Check your notifications for more details on this page: /admin?admin_tab=notifications. If you need help with KMS, please contact support@shuffler.io" - } + if (stringjson.includes("kms/")) { + return "KMS authentication most likely failed. Check your notifications for more details on this page: /admin?admin_tab=notifications. If you need help with KMS, please contact support@shuffler.io" + } - if (stringjson.includes("invalidurl")) { - // IF count of "http" is more than one, 1, it's prolly invalid - var additionalinfo = "" - if (stringjson.includes("http") && stringjson.match(/http/g).length > 1) { - additionalinfo = "You may be using multiple 'http' in the URL. " - } + if (stringjson.includes("invalidurl")) { + // IF count of "http" is more than one, 1, it's prolly invalid + var additionalinfo = "" + if (stringjson.includes("http") && stringjson.match(/http/g).length > 1) { + additionalinfo = "You may be using multiple 'http' in the URL. " + } - return "The URL is invalid. Change the URL to a valid one, and try again. "+additionalinfo - } + return "The URL is invalid. Change the URL to a valid one, and try again. " + additionalinfo + } - if (stringjson.includes("result too large to handle")) { - return "Execution loading failed. Reload the execution by closing it and clicking it again" - } + if (stringjson.includes("result too large to handle")) { + return "Execution loading failed. Reload the execution by closing it and clicking it again" + } - if (isCloud && stringjson.toLowerCase().includes("timeout error")) { - return "Run this workflow in a local environment to increase the timeout. Go to https://shuffler.io/admin?tab=locations to create an environment to connect to" - } + if (isCloud && stringjson.toLowerCase().includes("timeout error")) { + return "Run this workflow in a local environment to increase the timeout. Go to https://shuffler.io/admin?tab=locations to create an environment to connect to" + } - if (stringjson.toLowerCase().includes("invalid header")) { - return "A header or authentication token in the app is invalid. Check the app's configuration" - } + if (stringjson.toLowerCase().includes("invalid header")) { + return "A header or authentication token in the app is invalid. Check the app's configuration" + } - if (stringjson.includes("connectionerror")) { - if (stringjson.includes("kms")) { - return "KMS authentication most likely failed (2). Check your notifications for more details on this page: /admin?admin_tab=notifications&kms=true. If you need help with KMS, please contact support@shuffler.io" - } + if (stringjson.includes("connectionerror")) { + if (stringjson.includes("kms")) { + return "KMS authentication most likely failed (2). Check your notifications for more details on this page: /admin?admin_tab=notifications&kms=true. If you need help with KMS, please contact support@shuffler.io" + } - return "The URL is incorrect, or Shuffle can't reach it. Set up a Shuffle Environment in the same VLAN, or whitelist Shuffle's IPs." - } + return "The URL is incorrect, or Shuffle can't reach it. Set up a Shuffle Environment in the same VLAN, or whitelist Shuffle's IPs." + } - return "" + return "" } const currentSuggestion = getErrorSuggestion(validate.result) const codePopoutModal = !codeModalOpen ? null : ( - setActiveDialog("result"), - style: { - pointerEvents: "auto", - color: "white", - minWidth: isMobile ? "90%" : 750, - padding: 30, - maxHeight: 550, - overflowY: "auto", - overflowX: "hidden", - border: theme.palette.defaultBorder, + setActiveDialog("result"), + style: { + pointerEvents: "auto", + color: "white", + minWidth: isMobile ? "90%" : 750, + padding: 30, + maxHeight: 550, + overflowY: "auto", + overflowX: "hidden", + border: theme.palette.defaultBorder, - borderRadius: theme.palette.borderRadius, - backgroundColor: "black", - }, - }} - > - {/* Have a sticky top bar */} - - + {/* Have a sticky top bar */} + + + { + e.preventDefault() + }} > - { - e.preventDefault() - }} - > - - - - - { - e.preventDefault() + + + + + { + e.preventDefault() - if (workflowExecutions !== null) { - for (let execkey in workflowExecutions) { - const execution = workflowExecutions[execkey]; - if (execution.execution_argument.includes("too large")) { - continue - } - - const result = execution.results.find((data) => data.status === "SUCCESS" && data.action.id === selectedResult.action.id) - - if (result !== undefined) { - const oldstartnode = cy.getElementById(selectedResult.action.id) - if (oldstartnode !== undefined && oldstartnode !== null) { - const foundname = oldstartnode.data("label") - if (foundname !== undefined && foundname !== null) { - result.action.label = foundname - } - } - - setSelectedResult(result) - setUpdate(Math.random()) - break; - } - } - } - }} - > - - - - - { - e.preventDefault(); + if (workflowExecutions !== null) { for (let execkey in workflowExecutions) { const execution = workflowExecutions[execkey]; - const result = execution.results.find( - (data) => - data.action.id === selectedResult.action.id && - data.status !== "SUCCESS" && - data.status !== "SKIPPED" && - data.status !== "WAITING" - ); + if (execution.execution_argument.includes("too large")) { + continue + } + + const result = execution.results.find((data) => data.status === "SUCCESS" && data.action.id === selectedResult.action.id) + + if (result !== undefined) { + const oldstartnode = cy.getElementById(selectedResult.action.id) + if (oldstartnode !== undefined && oldstartnode !== null) { + const foundname = oldstartnode.data("label") + if (foundname !== undefined && foundname !== null) { + result.action.label = foundname + } + } + + setSelectedResult(result) + setUpdate(Math.random()) + break; + } + } + } + }} + > + + + + + { + e.preventDefault(); + for (let execkey in workflowExecutions) { + const execution = workflowExecutions[execkey]; + const result = execution.results.find( + (data) => + data.action.id === selectedResult.action.id && + data.status !== "SUCCESS" && + data.status !== "SKIPPED" && + data.status !== "WAITING" + ); if (result !== undefined) { const oldstartnode = cy.getElementById(selectedResult.action.id); @@ -20607,15 +20653,15 @@ const releaseToConnectLabel = "Release to Connect" setExecutionModalOpen(true); setExecutionModalView(1); - if (workflowExecutions[executionIndex] !== undefined && workflowExecutions[executionIndex] !== null && workflowExecutions[executionIndex].execution_argument.includes("too large")) { - //checkStarted = true - setExecutionData({}); - start(); - setExecutionRunning(true); - setExecutionRequestStarted(false); - } else { - setExecutionData(workflowExecutions[executionIndex]); - } + if (workflowExecutions[executionIndex] !== undefined && workflowExecutions[executionIndex] !== null && workflowExecutions[executionIndex].execution_argument.includes("too large")) { + //checkStarted = true + setExecutionData({}); + start(); + setExecutionRunning(true); + setExecutionRequestStarted(false); + } else { + setExecutionData(workflowExecutions[executionIndex]); + } } }} > @@ -20629,13 +20675,13 @@ const releaseToConnectLabel = "Release to Connect" > { }} > @@ -20670,8 +20716,8 @@ const releaseToConnectLabel = "Release to Connect" width: imgsize, height: imgsize, border: `2px solid ${statusColor}`, - filter: curapp === undefined ? "grayscale(100%)" : null, - borderRadius: theme.palette?.borderRadius, + filter: curapp === undefined ? "grayscale(100%)" : null, + borderRadius: theme.palette?.borderRadius, }} /> )} @@ -20693,15 +20739,15 @@ const releaseToConnectLabel = "Release to Connect"
    - {currentSuggestion.length > 0 ? -
    - Debug: {currentSuggestion} -
    - : -
    - Status {selectedResult.status} -
    - } + {currentSuggestion.length > 0 ? +
    + Debug: {currentSuggestion} +
    + : +
    + Status {selectedResult.status} +
    + } {validate.valid ? ( { - return collapseField(jsonField) - }} - iconStyle={theme.palette.jsonIconStyle} - collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength} - displayArrayKey={false} + shouldCollapse={(jsonField) => { + return collapseField(jsonField) + }} + iconStyle={theme.palette.jsonIconStyle} + collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength} + displayArrayKey={false} enableClipboard={(copy) => { handleReactJsonClipboard(copy); }} @@ -20727,13 +20773,13 @@ const releaseToConnectLabel = "Release to Connect" ) : (
    Result -
    +
    { to_be_copied = selectedResult.result; @@ -20811,7 +20857,7 @@ const releaseToConnectLabel = "Release to Connect" ); const newView = ( -
    +
    @@ -20839,15 +20885,15 @@ const releaseToConnectLabel = "Release to Connect"
    ) : ( - - {/**/} + + {/**/} { // FIXME: There's something specific loading when // you do the first hover of a node. Why is this different? - - setCy(incy); + + setCy(incy); }} /> - + )}
    {executionModal} - + { - rightSideBarOpen && Object.getOwnPropertyNames(selectedAction).length > 0 ? - -
    - -
    -
    - : null + rightSideBarOpen && Object.getOwnPropertyNames(selectedAction).length > 0 ? + +
    + +
    +
    + : null } - {/* Looks for triggers" */} - {/* Only fixed the ones that require scrolling on a small screen */} - {/* Most important: Actions. But these are a lot more complex */} - {rightSideBarOpen && (selectedTrigger.trigger_type === "SCHEDULE" || selectedTrigger.trigger_type === "WEBHOOK" || selectedTrigger.trigger_type === "PIPELINE" || selectedTrigger.trigger_type === "USERINPUT" || selectedTrigger.trigger_type === "SUBFLOW") ? -
    - {Object.getOwnPropertyNames(selectedTrigger)?.length > 0 ? - selectedTrigger.trigger_type === "SCHEDULE" ? - ScheduleSidebar - : selectedTrigger.trigger_type === "PIPELINE" ? - PipelineSidebar - : selectedTrigger.trigger_type === "WEBHOOK" ? - WebhookSidebar - : selectedTrigger.trigger_type === "USERINPUT" ? - UserinputSidebar - : selectedTrigger.trigger_type === "SUBFLOW" ? - SubflowSidebar - : null - : null} -
    - : null} -{/* + {/* Looks for triggers" */} + {/* Only fixed the ones that require scrolling on a small screen */} + {/* Most important: Actions. But these are a lot more complex */} + {rightSideBarOpen && (selectedTrigger.trigger_type === "SCHEDULE" || selectedTrigger.trigger_type === "WEBHOOK" || selectedTrigger.trigger_type === "PIPELINE" || selectedTrigger.trigger_type === "USERINPUT" || selectedTrigger.trigger_type === "SUBFLOW") ? +
    + {Object.getOwnPropertyNames(selectedTrigger)?.length > 0 ? + selectedTrigger.trigger_type === "SCHEDULE" ? + ScheduleSidebar + : selectedTrigger.trigger_type === "PIPELINE" ? + PipelineSidebar + : selectedTrigger.trigger_type === "WEBHOOK" ? + WebhookSidebar + : selectedTrigger.trigger_type === "USERINPUT" ? + UserinputSidebar + : selectedTrigger.trigger_type === "SUBFLOW" ? + SubflowSidebar + : null + : null} +
    + : null} + {/* { rightSideBarOpen && selectedTrigger?.trigger_type === "SUBFLOW"&& Object.getOwnPropertyNames(selectedTrigger)?.length > 0 ?
    : null } */} - - {/* + + {/* */} - {showWorkflowRevisions ? null : - - {/**/} - {shownErrors} - - - - - } + {showWorkflowRevisions ? null : + + {/**/} + {shownErrors} + + + + + }
    ); @@ -21039,10 +21085,10 @@ const releaseToConnectLabel = "Release to Connect" color: "white", border: theme.palette.defaultBorder, maxWidth: isMobile ? bodyWidth - 100 : 800, - minWidth: isMobile ? bodyWidth - 100 : 800, + minWidth: isMobile ? bodyWidth - 100 : 800, - borderRadius: theme.palette.borderRadius, - backgroundColor: "black", + borderRadius: theme.palette.borderRadius, + backgroundColor: "black", }, }} > @@ -21072,7 +21118,7 @@ const releaseToConnectLabel = "Release to Connect" }, }} margin="dense" - label="Name" + label="Name" fullWidth defaultValue={newVariableName} /> @@ -21087,7 +21133,7 @@ const releaseToConnectLabel = "Release to Connect" }, }} margin="dense" - label="Default Value (optional)" + label="Default Value (optional)" fullWidth defaultValue={newVariableValue} /> @@ -21127,9 +21173,9 @@ const releaseToConnectLabel = "Release to Connect" workflow.execution_variables[found].name = newVariableName; } - if (newVariableValue.length > 0) { - workflow.execution_variables[found].value = newVariableValue; - } + if (newVariableValue.length > 0) { + workflow.execution_variables[found].value = newVariableValue; + } } else { workflow.execution_variables.push({ name: newVariableName, @@ -21220,8 +21266,8 @@ const releaseToConnectLabel = "Release to Connect" border: theme.palette.defaultBorder, maxWidth: isMobile ? bodyWidth - 100 : "100%", - borderRadius: theme.palette.borderRadius, - backgroundColor: "black", + borderRadius: theme.palette.borderRadius, + backgroundColor: "black", }, }} > @@ -21446,18 +21492,18 @@ const releaseToConnectLabel = "Release to Connect" selectedAction.authentication_id = authenticationOption.id; selectedAction.selectedAuthentication = authenticationOption; - console.log("auth option 4: ", authenticationOption) + console.log("auth option 4: ", authenticationOption) if (selectedAction.authentication === undefined || selectedAction.authentication === null) { selectedAction.authentication = [authenticationOption] } else { - try { - selectedAction.authentication.push(authenticationOption) - } catch (e) { - //console.log("Error: ", e) - } + try { + selectedAction.authentication.push(authenticationOption) + } catch (e) { + //console.log("Error: ", e) + } } setSelectedAction(selectedAction) @@ -21482,8 +21528,8 @@ const releaseToConnectLabel = "Release to Connect" setUpdate(authenticationOption.id) } - if (authenticationOption.label === null || authenticationOption.label === undefined) { - authenticationOption.label = selectedApp.name + " authentication"; + if (authenticationOption.label === null || authenticationOption.label === undefined) { + authenticationOption.label = selectedApp.name + " authentication"; } return ( @@ -21532,35 +21578,35 @@ const releaseToConnectLabel = "Release to Connect" />
    {selectedApp.authentication.parameters.map((data, index) => { - // FIXME: Look for relevant fields in the action that may already be filled in with the same name - if (data.value === "" || data.value === null || data.value === undefined || data.name === "url") { - if (selectedAction !== undefined && selectedAction !== null && selectedAction.parameters !== undefined && selectedAction.parameters !== null) { - for (var fieldkey in selectedAction.parameters) { - const field = selectedAction.parameters[fieldkey] - if (field.name !== data.name) { - continue - } + // FIXME: Look for relevant fields in the action that may already be filled in with the same name + if (data.value === "" || data.value === null || data.value === undefined || data.name === "url") { + if (selectedAction !== undefined && selectedAction !== null && selectedAction.parameters !== undefined && selectedAction.parameters !== null) { + for (var fieldkey in selectedAction.parameters) { + const field = selectedAction.parameters[fieldkey] + if (field.name !== data.name) { + continue + } - if (field.value !== undefined && field.value !== null && field.value.length > 0) { - data.value = field.value - data.autocomplete = true - break - } - } - } - } + if (field.value !== undefined && field.value !== null && field.value.length > 0) { + data.value = field.value + data.autocomplete = true + break + } + } + } + } return (
    -
    - - - {data?.name?.endsWith("_basic") ? data?.name?.replace("_basic", "") : data?.name} - -
    +
    + + + {data?.name?.endsWith("_basic") ? data?.name?.replace("_basic", "") : data?.name} + +
    {data.schema !== undefined && data.schema !== null && @@ -21631,7 +21677,7 @@ const releaseToConnectLabel = "Release to Connect" authenticationOption.fields[data.name] = event.target.value; }} - id={`${data.name}_auth`} + id={`${data.name}_auth`} /> )}
    @@ -21640,9 +21686,9 @@ const releaseToConnectLabel = "Release to Connect"
    - - + - - - + cursor: "move", + }} + > + + + - {authenticationType.type === "oauth2" || authenticationType.type === "oauth2-app" ? + {authenticationType.type === "oauth2" || authenticationType.type === "oauth2-app" ? - : + : }
    @@ -21879,51 +21925,51 @@ const releaseToConnectLabel = "Release to Connect" overflowY: "auto", overflowX: "hidden", }} - onLoad={() => { - /* - if (isCloud && ReactGA !== undefined) { - toast("Sending GA info") - // Google analytics info about what app people are looking at - ReactGA.event({ - category: "workflow", - action: `documentation_load`, - label: selectedApp.name, - }) - - } - */ - }} + onLoad={() => { + /* + if (isCloud && ReactGA !== undefined) { + toast("Sending GA info") + // Google analytics info about what app people are looking at + ReactGA.event({ + category: "workflow", + action: `documentation_load`, + label: selectedApp.name, + }) + + } + */ + }} > {selectedApp.documentation === undefined || selectedApp.documentation === null || selectedApp.documentation.length === 0 ? ( - -
    - - {selectedApp.description} - -
    + +
    + + {selectedApp.description} + +
    -
    - - There is no Shuffle-specific documentation for this app yet outside of the general description above. Documentation is written for each api, and is a community effort. We hope to see your contribution! - - -
    + setTimeout(() => { + window.open(`https://github.com/Shuffle/openapi-apps/new/master/docs?filename=${selectedApp.name.toLowerCase()}.md`, "_blank") + }, 2500) + }} + > +   Create Docs + +
    Want to help the making of, or improve this app?{" "} -
    +
    ) : ( -
    - {selectedMeta !== undefined && selectedMeta !== null && Object.getOwnPropertyNames(selectedMeta).length > 0 && selectedMeta.name !== undefined && selectedMeta.name !== null ? -
    -
    - {isMobile ? null : ( - - - - - - )} - {isMobile ? null : ( -
    - )} - - {selectedMeta.read_time} minute - {selectedMeta.read_time === 1 ? "" : "s"} to read - -
    -
    - {isMobile || - selectedMeta.contributors === undefined || - selectedMeta.contributors === null ? ( - "" - ) : ( -
    - {selectedMeta.contributors.slice(0, 7).map((data, index) => { - return ( - - - {data.url} - - - ); - })} -
    - )} -
    -
    - : null} +
    + {selectedMeta !== undefined && selectedMeta !== null && Object.getOwnPropertyNames(selectedMeta).length > 0 && selectedMeta.name !== undefined && selectedMeta.name !== null ? +
    +
    + {isMobile ? null : ( + + + + + + )} + {isMobile ? null : ( +
    + )} + + {selectedMeta.read_time} minute + {selectedMeta.read_time === 1 ? "" : "s"} to read + +
    +
    + {isMobile || + selectedMeta.contributors === undefined || + selectedMeta.contributors === null ? ( + "" + ) : ( +
    + {selectedMeta.contributors.slice(0, 7).map((data, index) => { + return ( + + + {data.url} + + + ); + })} +
    + )} +
    +
    + : null} - - {selectedApp.documentation} - -
    + + {selectedApp.documentation} + +
    )}
    ) : null; - const tenzirConfigModal = !tenzirConfigModalOpen ? null : - - -
    Run a Tenzir Pipeline
    - - Runs a Tenzir pipeline. You can use the output of the pipeline in your workflow. - -
    - -
    - Pipeline - -
    - -
    - - - - -
    + placeholder={""} + defaultValue={selectedOption} + /> +
    - const SuggestionBoxUi = () => { - const [suggestionValue, setSuggestionValue] = useState(""); - const [suggestionLoading, setSuggestionLoading] = useState(false); - const [responseMsg, setResponseMsg] = useState(""); + - if (suggestionBox === undefined || suggestionBox.open === false) { - return false - } + + + + - return ( -
    - {/* + const SuggestionBoxUi = () => { + const [suggestionValue, setSuggestionValue] = useState(""); + const [suggestionLoading, setSuggestionLoading] = useState(false); + const [responseMsg, setResponseMsg] = useState(""); + + if (suggestionBox === undefined || suggestionBox.open === false) { + return false + } + + return ( +
    + {/* */} - - { - e.preventDefault(); - setSuggestionBox({ - "position": { - "top": 500, - "left": 500, - }, - "open": false, - "value": "", - "loading": false, - }); - }} - > - - - - { - e.preventDefault(); - aiSubmit(suggestionValue, setResponseMsg, setSuggestionLoading) - }}> - { - setSuggestionValue(e.target.value) - }} - InputProps={{ - endAdornment: ( - - - { - e.preventDefault(); - aiSubmit(suggestionValue, setResponseMsg, setSuggestionLoading) - }} /> - - - ), - }} - /> - - {suggestionLoading === true ? - - : null} - {responseMsg.length > 0 ? - - {responseMsg} - - : null} -
    - ) - } + + { + e.preventDefault(); + setSuggestionBox({ + "position": { + "top": 500, + "left": 500, + }, + "open": false, + "value": "", + "loading": false, + }); + }} + > + + + +
    { + e.preventDefault(); + aiSubmit(suggestionValue, setResponseMsg, setSuggestionLoading) + }}> + { + setSuggestionValue(e.target.value) + }} + InputProps={{ + endAdornment: ( + + + { + e.preventDefault(); + aiSubmit(suggestionValue, setResponseMsg, setSuggestionLoading) + }} /> + + + ), + }} + /> + + {suggestionLoading === true ? + + : null} + {responseMsg.length > 0 ? + + {responseMsg} + + : null} +
    + ) + } - - /*else if (selectedRevision === undefined || selectedRevision === null || selectedRevision == {} && originalWorkflow !== undefined && originalWorkflow !== null && originalWorkflow !== {}) { - console.log("Setting original workflow as selected revision") - setSelectedRevision(originalWorkflow) - }*/ - const RevisionBox = (props) => { - const { revision, showBorder, } = props - if (revision === undefined || revision === null) { - return null - } + /*else if (selectedRevision === undefined || selectedRevision === null || selectedRevision == {} && originalWorkflow !== undefined && originalWorkflow !== null && originalWorkflow !== {}) { + console.log("Setting original workflow as selected revision") + setSelectedRevision(originalWorkflow) + }*/ - var newrevision = JSON.parse(JSON.stringify(revision)) - // Make unix timestamp into ISO timestamp in the format July 27th, 3:05 AM - // Format: July 27th, 3:05 AM - //console.log("Edited time: ", revision.edited) - // Convert 1692128391 to valid timestamp - const validTimestamp = newrevision.edited.toString().length === 10 ? newrevision.edited * 1000 : newrevision.edited - const translatedDate = new Date(validTimestamp).toLocaleString('en-US', { month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: true }) + const RevisionBox = (props) => { + const { revision, showBorder, } = props + if (revision === undefined || revision === null) { + return null + } - var workflowStatus = newrevision.status !== undefined && newrevision.status !== null && newrevision.status !== "" ? newrevision.status : "test" - if (newrevision.name !== undefined && newrevision.name !== null && newrevision.name !== "") { - if (newrevision.name.toLowerCase().includes("test")) { - workflowStatus = "test" - } + var newrevision = JSON.parse(JSON.stringify(revision)) + // Make unix timestamp into ISO timestamp in the format July 27th, 3:05 AM + // Format: July 27th, 3:05 AM + //console.log("Edited time: ", revision.edited) + // Convert 1692128391 to valid timestamp + const validTimestamp = newrevision.edited.toString().length === 10 ? newrevision.edited * 1000 : newrevision.edited + const translatedDate = new Date(validTimestamp).toLocaleString('en-US', { month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: true }) - if (newrevision.name.toLowerCase().includes("dev") || newrevision.name.toLowerCase().includes("staging") || newrevision.name.toLowerCase().includes("rollback")) { - workflowStatus = "dev" - } + var workflowStatus = newrevision.status !== undefined && newrevision.status !== null && newrevision.status !== "" ? newrevision.status : "test" + if (newrevision.name !== undefined && newrevision.name !== null && newrevision.name !== "") { + if (newrevision.name.toLowerCase().includes("test")) { + workflowStatus = "test" + } - if (newrevision.name.toLowerCase().includes("prod") || newrevision.name.toLowerCase().includes("main")) { - workflowStatus = "prod" - } - } + if (newrevision.name.toLowerCase().includes("dev") || newrevision.name.toLowerCase().includes("staging") || newrevision.name.toLowerCase().includes("rollback")) { + workflowStatus = "dev" + } - return ( - { + if (newrevision.name.toLowerCase().includes("prod") || newrevision.name.toLowerCase().includes("main")) { + workflowStatus = "prod" + } + } + + return ( + { setRightSideBarOpen(false) - if (newrevision.edited === selectedVersion.edited) { - console.log("Same revision! No setting.") - return - } + if (newrevision.edited === selectedVersion.edited) { + console.log("Same revision! No setting.") + return + } - // Should render if it's not the same as workflow.edited - console.log("Clicked revision: ", newrevision) - setLastSaved(false) - setSelectedVersion(newrevision); - setWorkflow(newrevision) - setSelectedAction({}); - setSelectedApp({}) + // Should render if it's not the same as workflow.edited + console.log("Clicked revision: ", newrevision) + setLastSaved(false) + setSelectedVersion(newrevision); + setWorkflow(newrevision) + setSelectedAction({}); + setSelectedApp({}) - // Remove all cytoscape triggers first? - if (cy !== undefined && cy !== null) { - cy.removeListener("select"); - cy.removeListener("unselect"); + // Remove all cytoscape triggers first? + if (cy !== undefined && cy !== null) { + cy.removeListener("select"); + cy.removeListener("unselect"); - cy.removeListener("add"); - cy.removeListener("remove"); + cy.removeListener("add"); + cy.removeListener("remove"); - cy.removeListener("mouseover"); - cy.removeListener("mouseout"); + cy.removeListener("mouseover"); + cy.removeListener("mouseout"); - cy.removeListener("drag"); - cy.removeListener("free"); - cy.removeListener("cxttap"); + cy.removeListener("drag"); + cy.removeListener("free"); + cy.removeListener("cxttap"); - setElements([]) + setElements([]) - cy.remove('*') - cy.edges().remove() - cy.nodes().remove() - } + cy.remove('*') + cy.edges().remove() + cy.nodes().remove() + } - // Remove all cy nodes - setTimeout(() => { - //toast("Running setupgraph with new revision. Actions: " + newrevision.actions.length) - setupGraph(newrevision) - }, 250) + // Remove all cy nodes + setTimeout(() => { + //toast("Running setupgraph with new revision. Actions: " + newrevision.actions.length) + setupGraph(newrevision) + }, 250) - // Re-adding cytoscape triggers - if (cy !== undefined && cy !== null) { - cy.on("select", "node", (e) => { - onNodeSelect(e, appAuthentication); - }); - cy.on("select", "edge", (e) => onEdgeSelect(e)); + // Re-adding cytoscape triggers + if (cy !== undefined && cy !== null) { + cy.on("select", "node", (e) => { + onNodeSelect(e, appAuthentication); + }); + cy.on("select", "edge", (e) => onEdgeSelect(e)); - cy.on("unselect", (e) => onUnselect(e)); + cy.on("unselect", (e) => onUnselect(e)); - cy.on("add", "node", (e) => onNodeAdded(e)); - cy.on("add", "edge", (e) => onEdgeAdded(e)); - cy.on("remove", "node", (e) => onNodeRemoved(e)); - cy.on("remove", "edge", (e) => onEdgeRemoved(e)); + cy.on("add", "node", (e) => onNodeAdded(e)); + cy.on("add", "edge", (e) => onEdgeAdded(e)); + cy.on("remove", "node", (e) => onNodeRemoved(e)); + cy.on("remove", "edge", (e) => onEdgeRemoved(e)); - cy.on("mouseover", "edge", (e) => onEdgeHover(e)); - cy.on("mouseout", "edge", (e) => onEdgeHoverOut(e)); - cy.on("mouseover", "node", (e) => onNodeHover(e)); - cy.on("mouseout", "node", (e) => onNodeHoverOut(e)); + cy.on("mouseover", "edge", (e) => onEdgeHover(e)); + cy.on("mouseout", "edge", (e) => onEdgeHoverOut(e)); + cy.on("mouseover", "node", (e) => onNodeHover(e)); + cy.on("mouseout", "node", (e) => onNodeHoverOut(e)); - // Handles dragging - cy.on("drag", "node", (e) => onNodeDrag(e, selectedAction)); - cy.on("free", "node", (e) => onNodeDragStop(e, selectedAction)); + // Handles dragging + cy.on("drag", "node", (e) => onNodeDrag(e, selectedAction)); + cy.on("free", "node", (e) => onNodeDragStop(e, selectedAction)); - cy.on("cxttap", "node", (e) => onCtxTap(e)); - + cy.on("cxttap", "node", (e) => onCtxTap(e)); - if (selectedAction.id !== undefined && selectedAction.id !== null && selectedAction.id !== "") { - setTimeout(() => { - const foundaction = cy.$id(selectedAction.id) - if (foundaction !== undefined && foundaction !== null) { - foundaction.select() - } - }, 250) - } - } + + if (selectedAction.id !== undefined && selectedAction.id !== null && selectedAction.id !== "") { + setTimeout(() => { + const foundaction = cy.$id(selectedAction.id) + if (foundaction !== undefined && foundaction !== null) { + foundaction.select() + } + }, 250) + } + } - // Need to run through graph setup with this one - }}> -
    - - - {translatedDate} - {/* {newrevision.edited.toString().slice(6,10)} | {newrevision.revision_id.slice(0,5)} */} - - - - - - - -
    - {/*revision.edited === originalWorkflow.edited ? + // Need to run through graph setup with this one + }}> +
    + + + {translatedDate} + {/* {newrevision.edited.toString().slice(6,10)} | {newrevision.revision_id.slice(0,5)} */} + + + + + + + +
    + {/*revision.edited === originalWorkflow.edited ? Current version : null*/} -
    - {revision.actions !== undefined && revision.actions !== null ? - - - - - {revision.actions.length} - - - - : null} - {revision.triggers !== undefined && revision.triggers !== null ? - - - - - {revision.triggers.length} - - - - : null} -
    - {revision.updated_by !== undefined && revision.updated_by !== null && revision.updated_by !== "" ? - - {revision.updated_by} - - : null} -
    - ) - } +
    + {revision.actions !== undefined && revision.actions !== null ? + + + + + {revision.actions.length} + + + + : null} + {revision.triggers !== undefined && revision.triggers !== null ? + + + + + {revision.triggers.length} + + + + : null} +
    + {revision.updated_by !== undefined && revision.updated_by !== null && revision.updated_by !== "" ? + + {revision.updated_by} + + : null} +
    + ) + } - const drawerData = originalWorkflow !== undefined && originalWorkflow !== null ? -
    - - Version History - - - Versions are stored for every change made, up to once per minute. When restoring a version, the changes will not take effect until you save the workflow. - - -
    - {/* + const drawerData = originalWorkflow !== undefined && originalWorkflow !== null ? +
    + + Version History + + + Versions are stored for every change made, up to once per minute. When restoring a version, the changes will not take effect until you save the workflow. + + +
    + {/*
    @@ -22500,85 +22547,85 @@ const releaseToConnectLabel = "Release to Connect" */} - {allRevisions.length > 0 ? -
    - { - allRevisions.map((revision, index) => { - /* - if(revision.edited === selectedVersion.edited){ - return null - } - */ + {allRevisions.length > 0 ? +
    + { + allRevisions.map((revision, index) => { + /* + if(revision.edited === selectedVersion.edited){ + return null + } + */ - return ( - - ) - }) - } -
    + showBorder={revision.edited === selectedVersion.edited} + /> + ) + }) + } +
    - : -
    - - No other revisions found. Save your workflow with changes to create a revision. - -
    - } -
    + : +
    + + No other revisions found. Save your workflow with changes to create a revision. + +
    + } +
    - : null + : null - const workflowRevisions = !showWorkflowRevisions ? null : -
    - { - //setShowWorkflowRevisions(false) - }} - style={{ - resize: "both", - overflow: "hidden", - zIndex: 10005, - }} - hideBackdrop={true} - variant="persistent" - BackdropProps={{ - style: { - //backgroundColor: "transparent", - } - }} - PaperProps={{ - style: { - resize: "both", - overflow: "hidden", - minWidth: isMobile ? "100%" : 360, - maxWidth: isMobile ? "100%" : 360, - backgroundColor: theme.palette.platformColor, - color: "white", - fontSize: 18, - zIndex: 15001, - borderRight: theme.palette.defaultBorder, + const workflowRevisions = !showWorkflowRevisions ? null : +
    + { + //setShowWorkflowRevisions(false) + }} + style={{ + resize: "both", + overflow: "hidden", + zIndex: 10005, + }} + hideBackdrop={true} + variant="persistent" + BackdropProps={{ + style: { + //backgroundColor: "transparent", + } + }} + PaperProps={{ + style: { + resize: "both", + overflow: "hidden", + minWidth: isMobile ? "100%" : 360, + maxWidth: isMobile ? "100%" : 360, + backgroundColor: theme.palette.platformColor, + color: "white", + fontSize: 18, + zIndex: 15001, + borderRight: theme.palette.defaultBorder, - paddingLeft: leftSideBarOpenByClick ? 280 : 100, - transition: "padding-left 0.3s", + paddingLeft: leftSideBarOpenByClick ? 280 : 100, + transition: "padding-left 0.3s", - borderRadius: theme.palette.borderRadius, - backgroundColor: "black", - }, - }} - > - {drawerData} - -
    -
    - {/*selectedRevision.edited !== undefined && selectedRevision.edited !== null && selectedRevision.edited !== originalWorkflow.edited ? + borderRadius: theme.palette.borderRadius, + backgroundColor: "black", + }, + }} + > + {drawerData} + +
    +
    + {/*selectedRevision.edited !== undefined && selectedRevision.edited !== null && selectedRevision.edited !== originalWorkflow.edited ?
    -
    - - {selectedVersion?.name} - -
    -
    - -
    -
    -
    +
    +
    + + {selectedVersion?.name} + +
    +
    + +
    +
    +
    - const changeActionParameterCodeMirror = (event, count, data, actionlist, parametername) => { + const changeActionParameterCodeMirror = (event, count, data, actionlist, parametername) => { - // FIXME: This exists ONLY to make sure focus + blur actually changes the field value - // in fields from ParsedAction.jsx such as rightside_field_2 - const simulateTyping = (inputElement, text) => { - if (!inputElement) { - console.error("Target element not found!") - return; - } + // FIXME: This exists ONLY to make sure focus + blur actually changes the field value + // in fields from ParsedAction.jsx such as rightside_field_2 + const simulateTyping = (inputElement, text) => { + if (!inputElement) { + console.error("Target element not found!") + return; + } - //console.log("Simulating typing for: ", text, "in", inputElement) + //console.log("Simulating typing for: ", text, "in", inputElement) - inputElement.value = "" - setTimeout(() => { - text.split("").forEach((char, index) => { - setTimeout(() => { - inputElement.value = text.slice(0, index + 1) + inputElement.value = "" + setTimeout(() => { + text.split("").forEach((char, index) => { + setTimeout(() => { + inputElement.value = text.slice(0, index + 1) - // Simulate an event object like React's synthetic event - const event = { - target: { - value: inputElement.value, - }, - }; + // Simulate an event object like React's synthetic event + const event = { + target: { + value: inputElement.value, + }, + }; - // Find the onChange handler, assuming you're calling it from here - if (typeof inputElement.onchange === 'function') { - inputElement.onchange(event); // Call onChange with the synthetic event - } + // Find the onChange handler, assuming you're calling it from here + if (typeof inputElement.onchange === 'function') { + inputElement.onchange(event); // Call onChange with the synthetic event + } - // Dispatch the input event for React's internal event system - const inputEvent = new Event("input", { bubbles: true }); - inputElement.dispatchEvent(inputEvent); + // Dispatch the input event for React's internal event system + const inputEvent = new Event("input", { bubbles: true }); + inputElement.dispatchEvent(inputEvent); - }, 10) - }) - }, 50) + }, 10) + }) + }, 50) - setTimeout(() => { - inputElement.focus() - }, 500) - }; + setTimeout(() => { + inputElement.focus() + }, 500) + }; - // Check if event.target.value is an array. If it is, split with comma - if (parametername !== undefined && parametername.startsWith("${") && parametername.endsWith("}")) { - var paramcheckIndex = selectedAction.parameters.findIndex(param => param.name === parametername) - if (paramcheckIndex !== -1) { - // Replace the value in the field - const toReplace = data.replaceAll("\\\"", "\"").replaceAll("\"", "\\\""); - selectedAction.parameters[paramcheckIndex].value = toReplace - setSelectedAction(selectedAction) - setUpdate(Math.random()) + // Check if event.target.value is an array. If it is, split with comma + if (parametername !== undefined && parametername.startsWith("${") && parametername.endsWith("}")) { + var paramcheckIndex = selectedAction.parameters.findIndex(param => param.name === parametername) + if (paramcheckIndex !== -1) { + // Replace the value in the field + const toReplace = data.replaceAll("\\\"", "\"").replaceAll("\"", "\\\""); + selectedAction.parameters[paramcheckIndex].value = toReplace + setSelectedAction(selectedAction) + setUpdate(Math.random()) - // Find the fieldname - const clickedFieldId = "rightside_field_" + count; - const clickedField = document.getElementById(clickedFieldId) - if (clickedField !== undefined && clickedField !== null) { - simulateTyping(clickedField, toReplace) + // Find the fieldname + const clickedFieldId = "rightside_field_" + count; + const clickedField = document.getElementById(clickedFieldId) + if (clickedField !== undefined && clickedField !== null) { + simulateTyping(clickedField, toReplace) - /* - clickedField.value = toReplace - const newEvent = new Event("input", { bubbles: true }) - Object.defineProperty(event, "target", { - value: { ...clickedField, value: toReplace }, - writable: false, - }) + /* + clickedField.value = toReplace + const newEvent = new Event("input", { bubbles: true }) + Object.defineProperty(event, "target", { + value: { ...clickedField, value: toReplace }, + writable: false, + }) - //const newEvent = new Event("input", { bubbles: true }) - clickedField.dispatchEvent(newEvent) - console.log("Found field: ", clickedField) - */ - } + //const newEvent = new Event("input", { bubbles: true }) + clickedField.dispatchEvent(newEvent) + console.log("Found field: ", clickedField) + */ + } - //toast("Replaced field!") + //toast("Replaced field!") - return - } - } - - if (data.startsWith("${") && data.endsWith("}")) { - console.log("Changing field with variable: ", data) + return + } + } - // PARAM FIX - Gonna use the ID field, even though it's a hack - var paramcheck = selectedAction.parameters.find(param => param.name === "body") - if (paramcheck !== undefined) { - // Escapes all double quotes - const toReplace = event.target.value.replaceAll("\\\"", "\"").replaceAll("\"", "\\\""); - if (paramcheck["value_replace"] === undefined || paramcheck["value_replace"] === null) { - paramcheck["value_replace"] = [{ - "key": data.name, - "value": toReplace, - }] + if (data.startsWith("${") && data.endsWith("}")) { + console.log("Changing field with variable: ", data) - } else { - const subparamindex = paramcheck["value_replace"].findIndex(param => param.key === data.name) - if (subparamindex === -1) { - paramcheck["value_replace"].push({ - "key": data.name, - "value": toReplace, - }) - } else { - paramcheck["value_replace"][subparamindex]["value"] = toReplace - } - } + // PARAM FIX - Gonna use the ID field, even though it's a hack + var paramcheck = selectedAction.parameters.find(param => param.name === "body") + if (paramcheck !== undefined) { + // Escapes all double quotes + const toReplace = event.target.value.replaceAll("\\\"", "\"").replaceAll("\"", "\\\""); + if (paramcheck["value_replace"] === undefined || paramcheck["value_replace"] === null) { + paramcheck["value_replace"] = [{ + "key": data.name, + "value": toReplace, + }] - if (paramcheck["value_replace"] === undefined) { - selectedAction.parameters[count]["value_replace"] = paramcheck - } else { - //selectedActionParameters[count]["value_replace"] = paramcheck["value_replace"] - selectedAction.parameters[count]["value_replace"] = paramcheck["value_replace"] - } + } else { + const subparamindex = paramcheck["value_replace"].findIndex(param => param.key === data.name) + if (subparamindex === -1) { + paramcheck["value_replace"].push({ + "key": data.name, + "value": toReplace, + }) + } else { + paramcheck["value_replace"][subparamindex]["value"] = toReplace + } + } - setSelectedAction(selectedAction) - return - } - } + if (paramcheck["value_replace"] === undefined) { + selectedAction.parameters[count]["value_replace"] = paramcheck + } else { + //selectedActionParameters[count]["value_replace"] = paramcheck["value_replace"] + selectedAction.parameters[count]["value_replace"] = paramcheck["value_replace"] + } - if (event.target.value[event.target.value.length-1] === "." && actionlist.length > 0) { - var curstring = "" - var record = false - for (let [key,keyval] in Object.entries(selectedAction.parameters[count].value)) { - const item = selectedAction.parameters[count].value[key] - if (record) { - curstring += item - } + setSelectedAction(selectedAction) + return + } + } - if (item === "$") { - record = true - curstring = "" - } - } + if (event.target.value[event.target.value.length - 1] === "." && actionlist.length > 0) { + var curstring = "" + var record = false + for (let [key, keyval] in Object.entries(selectedAction.parameters[count].value)) { + const item = selectedAction.parameters[count].value[key] + if (record) { + curstring += item + } - if (curstring.length > 0 && actionlist !== null) { - // Search back in the action list - curstring = curstring.split(" ").join("_").toLowerCase() - var actionItem = actionlist.find(data => data.autocomplete.split(" ").join("_").toLowerCase() === curstring) - if (actionItem !== undefined) { - console.log("Found item: ", actionItem) + if (item === "$") { + record = true + curstring = "" + } + } - var jsonvalid = true - try { - const tmp = String(JSON.parse(actionItem.example)) - if (!actionItem.example.includes("{") && !actionItem.example.includes("[")) { - jsonvalid = false - } - } catch (e) { - jsonvalid = false - } - } - } - } + if (curstring.length > 0 && actionlist !== null) { + // Search back in the action list + curstring = curstring.split(" ").join("_").toLowerCase() + var actionItem = actionlist.find(data => data.autocomplete.split(" ").join("_").toLowerCase() === curstring) + if (actionItem !== undefined) { + console.log("Found item: ", actionItem) - if (selectedAction.app_name === "Shuffle Tools" && selectedAction.name === "filter_list" && count === 0) { - const parsedvalue = data - if (parsedvalue.includes("#")) { - const splitparsed = parsedvalue.split(".#.") - //console.log("Cant contain #: ", splitparsed) - if (splitparsed.length > 1) { - //data.value = splitparsed[0] + var jsonvalid = true + try { + const tmp = String(JSON.parse(actionItem.example)) + if (!actionItem.example.includes("{") && !actionItem.example.includes("[")) { + jsonvalid = false + } + } catch (e) { + jsonvalid = false + } + } + } + } - selectedAction.parameters[0].value = splitparsed[0] - selectedAction.parameters[1].value = splitparsed[1] + if (selectedAction.app_name === "Shuffle Tools" && selectedAction.name === "filter_list" && count === 0) { + const parsedvalue = data + if (parsedvalue.includes("#")) { + const splitparsed = parsedvalue.split(".#.") + //console.log("Cant contain #: ", splitparsed) + if (splitparsed.length > 1) { + //data.value = splitparsed[0] - selectedAction.parameters[0].autocompleted = true - selectedAction.parameters[1].autocompleted = true - setUpdate(Math.random()) - } - } - } else { - if (selectedAction.parameters !== undefined && selectedAction.parameters !== null && selectedAction.parameters.length > count) { - selectedAction.parameters[count].autocompleted = false - selectedAction.parameters[count].value = data - } - } + selectedAction.parameters[0].value = splitparsed[0] + selectedAction.parameters[1].value = splitparsed[1] - setSelectedAction(selectedAction) - //setUpdate(Math.random()) - } + selectedAction.parameters[0].autocompleted = true + selectedAction.parameters[1].autocompleted = true + setUpdate(Math.random()) + } + } + } else { + if (selectedAction.parameters !== undefined && selectedAction.parameters !== null && selectedAction.parameters.length > count) { + selectedAction.parameters[count].autocompleted = false + selectedAction.parameters[count].value = data + } + } + + setSelectedAction(selectedAction) + //setUpdate(Math.random()) + } /* var foundusecase = {} if (workflow.actions !== undefined && workflow.actions !== null && workflow.actions.length > 0 && userdata !== undefined && userdata !== null && userdata.priorities !== undefined && userdata.priorities !== null && userdata.priorities.length > 0) { - for (let priokey in userdata.priorities) { - const prio = userdata.priorities[priokey] - if (prio.type !== "usecase") { - continue - } + for (let priokey in userdata.priorities) { + const prio = userdata.priorities[priokey] + if (prio.type !== "usecase") { + continue + } - const descsplit = prio.description.split("&") - var srcapp = "" - var dstapp = "" - if (descsplit.length > 0) { - srcapp = descsplit[0].toLowerCase().replaceAll(" ", "_") + const descsplit = prio.description.split("&") + var srcapp = "" + var dstapp = "" + if (descsplit.length > 0) { + srcapp = descsplit[0].toLowerCase().replaceAll(" ", "_") - if (descsplit.length > 2) { - dstapp = descsplit[2].toLowerCase().replaceAll(" ", "_") - } - } + if (descsplit.length > 2) { + dstapp = descsplit[2].toLowerCase().replaceAll(" ", "_") + } + } - if (srcapp.length > 0 && dstapp.length > 0) { - for (let actionkey in workflow.actions) { - const curaction = workflow.actions[actionkey] - const appname = curaction.app_name.toLowerCase().replaceAll(" ", "_") - if (appname === srcapp || appname === dstapp) { - foundusecase = prio - break - } - } - } + if (srcapp.length > 0 && dstapp.length > 0) { + for (let actionkey in workflow.actions) { + const curaction = workflow.actions[actionkey] + const appname = curaction.app_name.toLowerCase().replaceAll(" ", "_") + if (appname === srcapp || appname === dstapp) { + foundusecase = prio + break + } + } + } - if (foundusecase.name !== undefined && foundusecase.name !== null && foundusecase.name !== "") { - break - } - } + if (foundusecase.name !== undefined && foundusecase.name !== null && foundusecase.name !== "") { + break + } + } } const templatePopup = foundusecase.name === undefined || foundusecase.name === null || foundusecase.name === "" ? null : - -
    - +
    + -
    - - */ + srcapp={foundusecase.description.split("&")[0]} + img1={foundusecase.description.split("&")[1]} + dstapp={foundusecase.description.split("&")[2]} + img2={foundusecase.description.split("&")[3]} + /> +
    +
    + */ const loadedCheck = isLoaded && workflowDone ? ( -
    +
    {newView} - {aiQueryModal} + {aiQueryModal} {conditionsModal} {codePopoutModal} - {workflowRevisions} + {workflowRevisions} {authenticationModal} {tenzirConfigModal} {/*editWorkflowModal*/} - {authgroupModal} - {executionArgumentModal} + {authgroupModal} + {executionArgumentModal} {configureWorkflowModal} - {/*usecaseSlidein*/} + {/*usecaseSlidein*/} - + - {codeEditorModalOpen ? - - : null} + setAiQueryModalOpen={setAiQueryModalOpen} + /> + : null} {editWorkflowModalOpen === true ? : null} - + {/*selectionOpen === true ?
    @@ -22942,12 +22989,12 @@ const releaseToConnectLabel = "Release to Connect"
    : null*/} -
    +
    {showVideo !== undefined && showVideo.length > 0 ?
    @@ -22988,12 +23035,12 @@ const releaseToConnectLabel = "Release to Connect" />
    ) : ( -
    - - - Loading Workflow & Apps... - -
    +
    + + + Loading Workflow & Apps... + +
    ); // Awful way of handling scroll diff --git a/frontend/src/views/AppCreator.jsx b/frontend/src/views/AppCreator.jsx index 8e474eed..3ce3cf09 100755 --- a/frontend/src/views/AppCreator.jsx +++ b/frontend/src/views/AppCreator.jsx @@ -5435,6 +5435,7 @@ const AppCreator = (defaultprops) => { minWidth: 174, minHeight: 174, objectFit: "contain", + borderRadius: theme.palette?.borderRadius, }} /> ); @@ -5450,6 +5451,7 @@ const AppCreator = (defaultprops) => { margin: "auto", marginTop: 30, marginLeft: 40, + borderRadius: theme.palette?.borderRadius, }} onClick={() => { upload.click(); @@ -5832,6 +5834,7 @@ const AppCreator = (defaultprops) => { //setOpenApiModal(true) toast.info("Action merging & fork management coming soon") }} + disabled={true} style={{marginLeft: 10, }} > { href="https://shuffler.io/docs/app_creation#app-creator-instructions" style={{ textDecoration: "none", color: "#f85a3e" }} > - Click here to learn more about app creation + Click to learn more about app creation
    { { style={{ width: 150, backgroundColor: theme.palette.surfaceColor, - backgroundColor: inputColor, color: "white", height: 35, marginleft: 10, diff --git a/frontend/src/views/Apps2.jsx b/frontend/src/views/Apps2.jsx index 10b9cd78..1b62cf14 100644 --- a/frontend/src/views/Apps2.jsx +++ b/frontend/src/views/Apps2.jsx @@ -1853,6 +1853,7 @@ const Apps2 = (props) => { app={selectedApp} userdata={userdata} globalUrl={globalUrl} + getApps={getApps} /> { maxHeight: 500, position: "absolute", left: 150, - top: 0, + top: 75, border: "1px solid rgba(255,255,255,0.3)", borderRadius: theme.palette?.borderRadius, diff --git a/frontend/src/views/Usecases2.jsx b/frontend/src/views/Usecases2.jsx index dd7fc19d..3e64f723 100644 --- a/frontend/src/views/Usecases2.jsx +++ b/frontend/src/views/Usecases2.jsx @@ -621,7 +621,7 @@ const UsecaseListComponent = (props) => { parsedUsecase.dstapp = newsubcase.dstapp - var workflowBuilt = false + var workflowBuilt = "" const newname = subcase.name.toLowerCase().replaceAll(" ", "_") for (var workflowkey in workflows) { const workflow = workflows[workflowkey] @@ -635,7 +635,7 @@ const UsecaseListComponent = (props) => { //console.log("WORKFLOW: ", newname, newusecases) if (newusecases.includes(newname)) { - workflowBuilt = true + workflowBuilt = workflow.id break } } @@ -676,6 +676,7 @@ const UsecaseListComponent = (props) => { showTryit={false} shownColor={""} workflowBuilt={workflowBuilt} + inputWorkflowId={workflowBuilt} usecaseDetails={usecaseDetails} /> diff --git a/frontend/src/views/Workflows2.jsx b/frontend/src/views/Workflows2.jsx index c58001da..b659ab7b 100644 --- a/frontend/src/views/Workflows2.jsx +++ b/frontend/src/views/Workflows2.jsx @@ -92,6 +92,7 @@ import { ArrowRight as ArrowRightIcon, Visibility as VisibilityIcon, EditNote as EditNoteIcon, + ErrorOutline as ErrorOutlineIcon, } from "@mui/icons-material"; // Additional Components @@ -108,6 +109,8 @@ import { InstantSearch, Configure, connectHits, connectSearchBox, connectRefinem import { debounce } from "lodash"; import { removeQuery } from "../components/ScrollToTop.jsx"; +import {green, yellow, red, grey } from "../views/AngularWorkflow.jsx" + const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240"); @@ -1114,12 +1117,9 @@ const Workflows2 = (props) => {
    ) : null} + {(data.sharing !== undefined && data.sharing !== null && data.sharing === "form") || (data?.form_control?.input_markdown !== undefined && data?.form_control?.input_markdown !== null && data?.form_control?.input_markdown !== "") && type !== "public" ?
    @@ -2821,10 +2822,33 @@ const Workflows2 = (props) => { > - {workflowMenuButtons}
    - : null} + : null} + + {(data?.validation?.validation_ran === true && data?.validation?.valid === false && data?.validation?.errors?.length > 0 ) ? + +
    + { + window.open(`/admin?admin_tab=notifications&workflow_id=${data.id}`, "_blank") + }} + style={{ + padding: "0px", + color: "#979797", + }} + > + + +
    +
    + + : null}