diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index 1db53973..95a9ad4e 100755 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -180,9 +180,8 @@ const ParsedAction = (props) => { const [fieldCount, setFieldCount] = React.useState(0); const [hiddenDescription, setHiddenDescription] = React.useState(true); - const [autoCompleting, setAutocompleting] = React.useState(false); - const [selectedActionParameters, setSelectedActionParameters] = React.useState([]); + const [selectedActionParameters, setSelectedActionParameters] = React.useState(selectedAction.parameters); const [selectedVariableParameter, setSelectedVariableParameter] = React.useState(""); const [actionlist, setActionlist] = React.useState([]); const [jsonList, setJsonList] = React.useState([]); @@ -382,9 +381,12 @@ const ParsedAction = (props) => { useEffect( () => { + console.log("UseEffect Rendered!") + console.log("Workflow", workflow) // if (selectedActionParameters !== undefined && selectedActionParameters !== null // ) { if (selectedAction.parameters !== undefined && selectedAction.parameters !== null && selectedAction.parameters.length > 0) { + console.log("Setting action parameters!!") setSelectedActionParameters(selectedAction.parameters); // } } @@ -614,9 +616,13 @@ const ParsedAction = (props) => { } } }, - [selectedAction, selectedVariableParameter, workflowExecutions, listCache]); - - + [selectedAction,selectedApp,setNewSelectedAction] + ); + console.log("selectedActionParameters: ", selectedActionParameters) + console.log("selectedApp:", selectedApp) + console.log("selectedAction: ", selectedAction) + console.log("ACTIONLIST: ", actionlist) + console.log("selectedVariableParameter", selectedVariableParameter) const calculateHelpertext = (input_data) => { var helperText = "" var looperText = "" @@ -1184,7 +1190,7 @@ const ParsedAction = (props) => { } // FIXME: Issue #40 - selectedActionParameters not reset - + if (Object.getOwnPropertyNames(selectedAction).length > 0 && selectedActionParameters.length > 0) { var wrapperapp = { "id": "", "name": "noapp", @@ -1210,15 +1216,16 @@ const ParsedAction = (props) => { var authWritten = false; var noAppSelected = false - const paramIndex = selectedAction.parameters.findIndex((param) => param.name === "app_name") + 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 { data, newActionname, newActiondescription, useIcon, extraDescription, } = actionprops; + const { option, newActionname, newActiondescription, useIcon, extraDescription, } = actionprops; const [hover, setHover] = React.useState(false); return ( @@ -1234,18 +1241,20 @@ const ParsedAction = (props) => { paddingBottom: 4, backgroundColor: hover ? theme.palette.surfaceColor : theme.palette.inputColor, }} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)} - onClick={() => { + onClick={(event) => { + // event.preventDefault() //setSelectedAction(actionprops) //setShowActionList(false) //setUpdate(Math.random()) // - if (data !== undefined && data !== null) { + if (option !== undefined && option !== null) { setNewSelectedAction({ target: { - value: data.name + value: option.name } }); } + document.activeElement.blur(); }} >
@@ -1308,7 +1317,7 @@ const ParsedAction = (props) => { const selectedAppIcon = selectedAction.large_image - console.log("Selected action: ", selectedAction) +// console.log("Selected action: ", selectedAction) console.log("Selected action paramaters: ", selectedAction.parameters) var baselabel = selectedAction.label return ( @@ -2220,54 +2229,55 @@ const ParsedAction = (props) => { } }); } - }} - renderOption={(props, data, state) => { - var newActionname = data.name; - if (data.label !== undefined && data.label !== null && data.label.length > 0) { - newActionname = data.label; + event.target.blur(); + }} + renderOption={(props, option, state) => { + var newActionname = option.name; + if (option.label !== undefined && option.label !== null && option.label.length > 0) { + newActionname = option.label; } - var newActiondescription = data.description; + var newActiondescription = option.description; //console.log("DESC: ", newActiondescription) - if (data.description === undefined || data.description === null) { + if (option.description === undefined || option.description === null) { newActiondescription = "Description: No description defined for this action" } else { newActiondescription = "Description: "+newActiondescription } - const iconInfo = GetIconInfo({ name: data.name }); + const iconInfo = GetIconInfo({ name: option.name }); const useIcon = iconInfo.originalIcon; if (newActionname === undefined || newActionname === null) { newActionname = "No name" - data.name = "No name" - data.label = "No name" + option.name = "No name" + option.label = "No name" } newActionname = (newActionname.charAt(0).toUpperCase() + newActionname.substring(1)).replaceAll("_", " "); var method = "" var extraDescription = "" - if (data.name.includes("get_")) { + if (option.name.includes("get_")) { method = "GET" - } else if (data.name.includes("post_")) { + } else if (option.name.includes("post_")) { method = "POST" - } else if (data.name.includes("put_")) { + } else if (option.name.includes("put_")) { method = "PUT" - } else if (data.name.includes("patch_")) { + } else if (option.name.includes("patch_")) { method = "PATCH" - } else if (data.name.includes("delete_")) { + } else if (option.name.includes("delete_")) { method = "DELETE" - } else if (data.name.includes("options_")) { + } else if (option.name.includes("options_")) { method = "OPTIONS" - } else if (data.name.includes("connect_")) { + } else if (option.name.includes("connect_")) { method = "CONNECT" } // FIXME: Should it require a base URL? - if (method.length > 0 && data.description !== undefined && data.description !== null && data.description.includes("http")) { + if (method.length > 0 && option.description !== undefined && option.description !== null && option.description.includes("http")) { var extraUrl = "" - const descSplit = data.description.split("\n") + const descSplit = option.description.split("\n") // Last line of descSplit if (descSplit.length > 0) { extraUrl = descSplit[descSplit.length-1] @@ -2306,7 +2316,8 @@ const ParsedAction = (props) => { return ( { //const data = JSON.parse(JSON.stringify(event.target.data())) const data = event.target.data() - + console.log("===============================Node selected=============================") console.log("NODE SELECT: ", data) if (data.app_name === "Shuffle Workflow") { @@ -8567,11 +8567,15 @@ const AngularWorkflow = (defaultprops) => { ); }; - const handleSetTab = (event, newValue) => { - setCurrentView(newValue); - }; + const HandleLeftView = () => { + // console.log("HandleLeftView Rendered!") + + const handleSetTab = (event, newValue) => { + setCurrentView(newValue); + }; + // Defaults to apps. var thisview = ( { ) } - - - const TriggersView = () => { - const triggersViewStyle = { - marginLeft: 10, - marginRight: 10, - display: "flex", - flexDirection: "column", - } - - // Predefined hurr - return ( -
-
- {triggers.map((trigger, index) => { - - /* - if (trigger.trigger_type === "PIPELINE") { - if (userdata.support !== true) { - return null - } - } - */ - - // Hiding since March 2024 - if (trigger.trigger_type === "EMAIL") { - return null - } - - const imagesize = isMobile ? 40 : trigger.large_image.includes("svg") ? 50 : 50 - var imageline = trigger.large_image.length === 0 ? - : - - - const title = trigger.trigger_type === "WEBHOOK" ? "Workflow starters" : trigger.trigger_type === "SUBFLOW" ? "Mid-Workflow" : "" - - const color = trigger.is_valid ? green : yellow; - return ( - - {title.length > 0 ? - - {title} - - : null} - - { - handleTriggerDrag(e, trigger); - }} - onStop={(e) => { - handleDragStop(e); - }} - dragging={false} - position={{ - x: 0, - y: 0, - }} - > - { }}> -
- - - {imageline} - - {isMobile ? null : - - - - {trigger.name} - - - - - {trigger.description} - - - - } - -
-
-
- ); - })} -
-
- ); - }; - - var newNodeId = ""; - var parsedApp = {}; - const handleTriggerDrag = (e, data) => { - const cycontainer = cy.container(); - // Chrome lol - if ( - e.pageX > cycontainer.offsetLeft && - e.pageX < cycontainer.offsetLeft + cycontainer.offsetWidth && - e.pageY > cycontainer.offsetTop && - e.pageY < cycontainer.offsetTop + cycontainer.offsetHeight - ) { - if (newNodeId.length > 0) { - var currentnode = cy.getElementById(newNodeId); - if (currentnode.length === 0) { - return; - } - - currentnode[0].renderedPosition("x", e.pageX - cycontainer.offsetLeft); - currentnode[0].renderedPosition("y", e.pageY - cycontainer.offsetTop); - } else { - if (workflow.start === "" || workflow.start === undefined) { - toast("Define a starting action first."); - return; - } - - const triggerLabel = getNextActionName(data.name); - - newNodeId = uuidv4(); - const newposition = { - x: e.pageX - cycontainer.offsetLeft, - y: e.pageY - cycontainer.offsetTop, - }; - - const newAppData = { - app_name: data.name, - app_version: "1.0.0", - environment: isCloud ? "cloud" : data.environment, - description: data.description, - long_description: data.long_description, - errors: [], - id_: newNodeId, - _id_: newNodeId, - id: newNodeId, - finished: false, - label: triggerLabel, - type: data.type, - is_valid: true, - trigger_type: data.trigger_type, - large_image: data.large_image, - status: "uninitialized", - name: data.name, - isStartNode: false, - position: newposition, - }; - - // Can all the data be in here? hmm - const nodeToBeAdded = { - group: "nodes", - data: newAppData, - renderedPosition: newposition, - }; - - cy.add(nodeToBeAdded); - parsedApp = nodeToBeAdded; - return; - } - } - }; - - const handleDragStop = (e, app) => { - var currentnode = cy.getElementById(newNodeId); - if ( - currentnode === undefined || - currentnode === null || - currentnode.length === 0 - ) { - return; - } - - // Using remove & replace, as this triggers the function - // onNodeAdded() with this node after it's added - - currentnode.remove(); - parsedApp.data.finished = true; - parsedApp.data.position = currentnode.renderedPosition(); - parsedApp.position = currentnode.renderedPosition(); - parsedApp.renderedPosition = currentnode.renderedPosition(); - - var newAppData = parsedApp.data; - if (newAppData.type === "ACTION") { - - //const activateApp = (appid) => { - if (newAppData.activated === false) { - activateApp(newAppData.app_id, false) - } - - // AUTHENTICATION - if (app.authentication !== undefined && app.authentication !== null && app.authentication.required === true) { - - // Setup auth here :) - const authenticationOptions = []; - var findAuthId = ""; - if ( - newAppData.authentication_id !== null && - newAppData.authentication_id !== undefined && - newAppData.authentication_id.length > 0 - ) { - findAuthId = newAppData.authentication_id; - } - - const tmpAuth = JSON.parse(JSON.stringify(appAuthentication)); - for (let authkey in tmpAuth) { - if (authkey === undefined) { - continue - } - - var item = tmpAuth[authkey]; - const newfields = {}; - 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 - } - - newfields[filterkey] = item.fields[fieldkey]["value"]; - } - - item.fields = newfields; - if (item.app.id === app.id || item.app.name === app.name) { - authenticationOptions.push(item); - - if (item.id === findAuthId) { - newAppData.selectedAuthentication = item - newAppData.authentication_id = item.id - - } else if (findAuthId === "") { - // Will always be set to the last one if one isn't found. - // Last = timestamp too - newAppData.selectedAuthentication = item - newAppData.authentication_id = item.id - } - } - } - - if ( - authenticationOptions !== undefined && - authenticationOptions !== null && - authenticationOptions.length > 0 - ) { - for (let authkey in authenticationOptions) { - const option = authenticationOptions[authkey]; - - if (option.active && newAppData.authentication_id === "") { - newAppData.selectedAuthentication = option; - newAppData.authentication_id = option.id; - break; - } - } - } - } else { - newAppData.authentication = []; - newAppData.authentication_id = ""; - newAppData.selectedAuthentication = {}; - } - - parsedApp.data = newAppData; - cy.add(parsedApp); - } else if (newAppData.type === "TRIGGER") { - cy.add(parsedApp); - } - - newNodeId = ""; - parsedApp = {}; - }; - - const barHeight = bodyHeight - appBarSize - 50; - const appScrollStyle = { - overflow: "scroll", - maxHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight, - minHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight, - marginTop: 1, - overflowY: "auto", - overflowX: "hidden", - } - - const handleAppDrag = (e, app) => { - const cycontainer = cy.container(); - - - if (app.type === "TRIGGER") { - handleTriggerDrag(e, app) - return - } - - //console.log("e: ", e) - //console.log("Offset: ", cycontainer) - - // Chrome lol - if ( - e.pageX > cycontainer.offsetLeft && - e.pageX < cycontainer.offsetLeft + cycontainer.offsetWidth && - e.pageY > cycontainer.offsetTop && - e.pageY < cycontainer.offsetTop + cycontainer.offsetHeight - ) { - if (newNodeId.length > 0) { - var currentnode = cy.getElementById(newNodeId); - if ( - currentnode === undefined || - currentnode === null || - currentnode.length === 0 - ) { - return; - } - - currentnode[0].renderedPosition("x", e.pageX - cycontainer.offsetLeft) - currentnode[0].renderedPosition("y", e.pageY - cycontainer.offsetTop) - } else { - if (workflow.public) { - console.log("workflow is public - not adding") - return; - } - - if (app.actions === undefined || app.actions === null) { - app.actions = [] - } - - /* - if (app.actions === undefined || app.actions === null || app.actions.length === 0) { - toast("App " + app.name + " currently has no actions to perform. Please go to https://shuffler.io/apps to edit it.") - - return - } - */ - - newNodeId = uuidv4(); - const actionType = "ACTION"; - const actionLabel = getNextActionName(app.name); - //console.log("Next action name: ", actionLabel) - var parameters = null; - var example = ""; - var description = "" - - const startIndex = app.actions.findIndex((action) => action.category_label !== undefined && action.category_label !== null && action.category_label.length > 0) - const actionIndex = startIndex < 0 ? 0 : startIndex - - // Make the first action the most relevant one for them based on previous use - if ( - app.actions[actionIndex].parameters !== undefined && - app.actions[actionIndex].parameters !== null && - app.actions[actionIndex].parameters.length > 0 - ) { - parameters = app.actions[actionIndex].parameters; - for (let paramkey in parameters) { - // Check if parameter.name == "headers" and if it includes "=undefined". If it does, set the value to example if it exists, otherwise empty - if (parameters[paramkey].name === "headers" && parameters[paramkey].value.includes("=undefined")) { - if (parameters[paramkey].example !== undefined && parameters[paramkey].example !== null && parameters[paramkey].example.length > 0) { - parameters[paramkey].value = parameters[paramkey].example - } else { - parameters[paramkey].value = "" - } - } - } - - //parameters = app.actions[0].parameters; - } - - if ( - app.actions[actionIndex].returns !== undefined && - app.actions[actionIndex].returns !== null && - app.actions[actionIndex].returns.example !== undefined && - app.actions[actionIndex].returns.example !== null && - app.actions[actionIndex].returns.example.length > 0 - ) { - example = app.actions[actionIndex].returns.example; - } - - if ( - app.actions[actionIndex].description !== undefined && - app.actions[actionIndex].description !== null && - app.actions[actionIndex].description.length > 0 - ) { - description = app.actions[actionIndex].description - } - - var parsedEnvironments = - environments === null || environments === [] - ? "cloud" - : environments[defaultEnvironmentIndex] === undefined - ? "cloud" - : environments[defaultEnvironmentIndex].Name - - // Basic automatic auth mapping - var authId = "" - if (appAuthentication !== undefined && appAuthentication !== null && appAuthentication.length > 0) { - const appname = app.name.toLowerCase().replace(" ", "_") - for (var key in appAuthentication) { - const authKey = appAuthentication[key] - if (authKey.app.id === app.id) { - authId = authKey.id - break - } - - const appauthname = authKey.app.name.toLowerCase().replace(" ", "_") - if (appauthname === appname) { - authId = authKey.id - } - } - } - - // List other nodes in the workflow and see if they have an environment set. If they do, use that as the default - if (cy !== undefined && cy !== null) { - const foundnodes = cy.nodes().jsons() - if (foundnodes !== undefined && foundnodes !== null && foundnodes.length > 0) { - // As they should all be the same, this is just an override - for (let nodekey in foundnodes) { - const curnode = foundnodes[nodekey] - if (curnode.data.environment !== undefined && curnode.data.environment !== null && curnode.data.environment.length > 0) { - parsedEnvironments = curnode.data.environment - break - } - } - } - } - - const newAppData = { - name: app.actions[actionIndex].name, - label: actionLabel, - app_name: app.name, - app_version: app.app_version, - app_id: app.id, - sharing: app.sharing, - private_id: app.private_id, - description: description, - environment: parsedEnvironments, - errors: [], - finished: false, - id_: newNodeId, - _id_: newNodeId, - id: newNodeId, - is_valid: true, - type: actionType, - parameters: parameters, - isStartNode: false, - large_image: app.large_image, - run_magic_output: false, - authentication: [], - execution_variable: undefined, - example: example, - required_body_fields: app.actions[actionIndex].required_body_fields, - category: - app.categories !== null && - app.categories !== undefined && - app.categories.length > 0 - ? app.categories[0] - : "", - authentication_id: authId, - finished: false, - template: app.template === true ? true : false, - }; - - // FIXME: overwrite category if the ACTION chosen has a different category - // - - if (!isCloud && (!app.is_valid || (!app.activated && app.generated))) { - console.log("NOT VALID: Activate!") - - activateApp(app.id, false) - } - - // const image = "url("+app.large_image+")" - // FIXME - find the cytoscape offset position - // Can this be done with zoom calculations? - const nodeToBeAdded = { - group: "nodes", - data: newAppData, - renderedPosition: { - x: e.pageX - cycontainer.offsetLeft, - y: e.pageY - cycontainer.offsetTop, - }, - }; - - parsedApp = nodeToBeAdded; - cy.add(nodeToBeAdded); - return; - } - } - }; - const AppView = (props) => { const { allApps, prioritizedApps, filteredApps, extraApps } = props; - + // console.log("AppView Rendered!") //extraApps, const [visibleApps, setVisibleApps] = React.useState( Array.prototype.concat.apply( @@ -9833,8 +9323,505 @@ const AngularWorkflow = (defaultprops) => {
); +} + + const TriggersView = () => { + console.log("TriggerView Rendered!") + const triggersViewStyle = { + marginLeft: 10, + marginRight: 10, + display: "flex", + flexDirection: "column", + } + + // Predefined hurr + return ( +
+
+ {triggers.map((trigger, index) => { + + /* + if (trigger.trigger_type === "PIPELINE") { + if (userdata.support !== true) { + return null + } + } + */ + + // Hiding since March 2024 + if (trigger.trigger_type === "EMAIL") { + return null + } + + const imagesize = isMobile ? 40 : trigger.large_image.includes("svg") ? 50 : 50 + var imageline = trigger.large_image.length === 0 ? + : + + + const title = trigger.trigger_type === "WEBHOOK" ? "Workflow starters" : trigger.trigger_type === "SUBFLOW" ? "Mid-Workflow" : "" + + const color = trigger.is_valid ? green : yellow; + return ( + + {title.length > 0 ? + + {title} + + : null} + + { + handleTriggerDrag(e, trigger); + }} + onStop={(e) => { + handleDragStop(e); + }} + dragging={false} + position={{ + x: 0, + y: 0, + }} + > + { }}> +
+ + + {imageline} + + {isMobile ? null : + + + + {trigger.name} + + + + + {trigger.description} + + + + } + +
+
+
+ ); + })} +
+
+ ); + } + + var newNodeId = ""; + var parsedApp = {}; + const handleTriggerDrag = (e, data) => { + const cycontainer = cy.container(); + // Chrome lol + if ( + e.pageX > cycontainer.offsetLeft && + e.pageX < cycontainer.offsetLeft + cycontainer.offsetWidth && + e.pageY > cycontainer.offsetTop && + e.pageY < cycontainer.offsetTop + cycontainer.offsetHeight + ) { + if (newNodeId.length > 0) { + var currentnode = cy.getElementById(newNodeId); + if (currentnode.length === 0) { + return; + } + + currentnode[0].renderedPosition("x", e.pageX - cycontainer.offsetLeft); + currentnode[0].renderedPosition("y", e.pageY - cycontainer.offsetTop); + } else { + if (workflow.start === "" || workflow.start === undefined) { + toast("Define a starting action first."); + return; + } + + const triggerLabel = getNextActionName(data.name); + + newNodeId = uuidv4(); + const newposition = { + x: e.pageX - cycontainer.offsetLeft, + y: e.pageY - cycontainer.offsetTop, + }; + + const newAppData = { + app_name: data.name, + app_version: "1.0.0", + environment: isCloud ? "cloud" : data.environment, + description: data.description, + long_description: data.long_description, + errors: [], + id_: newNodeId, + _id_: newNodeId, + id: newNodeId, + finished: false, + label: triggerLabel, + type: data.type, + is_valid: true, + trigger_type: data.trigger_type, + large_image: data.large_image, + status: "uninitialized", + name: data.name, + isStartNode: false, + position: newposition, + }; + + // Can all the data be in here? hmm + const nodeToBeAdded = { + group: "nodes", + data: newAppData, + renderedPosition: newposition, + }; + + cy.add(nodeToBeAdded); + parsedApp = nodeToBeAdded; + return; + } + } }; + const handleDragStop = (e, app) => { + var currentnode = cy.getElementById(newNodeId); + if ( + currentnode === undefined || + currentnode === null || + currentnode.length === 0 + ) { + return; + } + + // Using remove & replace, as this triggers the function + // onNodeAdded() with this node after it's added + + currentnode.remove(); + parsedApp.data.finished = true; + parsedApp.data.position = currentnode.renderedPosition(); + parsedApp.position = currentnode.renderedPosition(); + parsedApp.renderedPosition = currentnode.renderedPosition(); + + var newAppData = parsedApp.data; + if (newAppData.type === "ACTION") { + + //const activateApp = (appid) => { + if (newAppData.activated === false) { + activateApp(newAppData.app_id, false) + } + + // AUTHENTICATION + if (app.authentication !== undefined && app.authentication !== null && app.authentication.required === true) { + + // Setup auth here :) + const authenticationOptions = []; + var findAuthId = ""; + if ( + newAppData.authentication_id !== null && + newAppData.authentication_id !== undefined && + newAppData.authentication_id.length > 0 + ) { + findAuthId = newAppData.authentication_id; + } + + const tmpAuth = JSON.parse(JSON.stringify(appAuthentication)); + for (let authkey in tmpAuth) { + if (authkey === undefined) { + continue + } + + var item = tmpAuth[authkey]; + const newfields = {}; + 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 + } + + newfields[filterkey] = item.fields[fieldkey]["value"]; + } + + item.fields = newfields; + if (item.app.id === app.id || item.app.name === app.name) { + authenticationOptions.push(item); + + if (item.id === findAuthId) { + newAppData.selectedAuthentication = item + newAppData.authentication_id = item.id + + } else if (findAuthId === "") { + // Will always be set to the last one if one isn't found. + // Last = timestamp too + newAppData.selectedAuthentication = item + newAppData.authentication_id = item.id + } + } + } + + if ( + authenticationOptions !== undefined && + authenticationOptions !== null && + authenticationOptions.length > 0 + ) { + for (let authkey in authenticationOptions) { + const option = authenticationOptions[authkey]; + + if (option.active && newAppData.authentication_id === "") { + newAppData.selectedAuthentication = option; + newAppData.authentication_id = option.id; + break; + } + } + } + } else { + newAppData.authentication = []; + newAppData.authentication_id = ""; + newAppData.selectedAuthentication = {}; + } + + parsedApp.data = newAppData; + cy.add(parsedApp); + } else if (newAppData.type === "TRIGGER") { + cy.add(parsedApp); + } + + newNodeId = ""; + parsedApp = {}; + }; + + const barHeight = bodyHeight - appBarSize - 50; + const appScrollStyle = { + overflow: "scroll", + maxHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight, + minHeight: isMobile ? bodyHeight - appBarSize * 4 : barHeight, + marginTop: 1, + overflowY: "auto", + overflowX: "hidden", + } + + const handleAppDrag = (e, app) => { + const cycontainer = cy.container(); + + + if (app.type === "TRIGGER") { + handleTriggerDrag(e, app) + return + } + + //console.log("e: ", e) + //console.log("Offset: ", cycontainer) + + // Chrome lol + if ( + e.pageX > cycontainer.offsetLeft && + e.pageX < cycontainer.offsetLeft + cycontainer.offsetWidth && + e.pageY > cycontainer.offsetTop && + e.pageY < cycontainer.offsetTop + cycontainer.offsetHeight + ) { + if (newNodeId.length > 0) { + var currentnode = cy.getElementById(newNodeId); + if ( + currentnode === undefined || + currentnode === null || + currentnode.length === 0 + ) { + return; + } + + currentnode[0].renderedPosition("x", e.pageX - cycontainer.offsetLeft) + currentnode[0].renderedPosition("y", e.pageY - cycontainer.offsetTop) + } else { + if (workflow.public) { + console.log("workflow is public - not adding") + return; + } + + if (app.actions === undefined || app.actions === null) { + app.actions = [] + } + + /* + if (app.actions === undefined || app.actions === null || app.actions.length === 0) { + toast("App " + app.name + " currently has no actions to perform. Please go to https://shuffler.io/apps to edit it.") + + return + } + */ + + newNodeId = uuidv4(); + const actionType = "ACTION"; + const actionLabel = getNextActionName(app.name); + //console.log("Next action name: ", actionLabel) + var parameters = null; + var example = ""; + var description = "" + + const startIndex = app.actions.findIndex((action) => action.category_label !== undefined && action.category_label !== null && action.category_label.length > 0) + const actionIndex = startIndex < 0 ? 0 : startIndex + + // Make the first action the most relevant one for them based on previous use + if ( + app.actions[actionIndex].parameters !== undefined && + app.actions[actionIndex].parameters !== null && + app.actions[actionIndex].parameters.length > 0 + ) { + parameters = app.actions[actionIndex].parameters; + for (let paramkey in parameters) { + // Check if parameter.name == "headers" and if it includes "=undefined". If it does, set the value to example if it exists, otherwise empty + if (parameters[paramkey].name === "headers" && parameters[paramkey].value.includes("=undefined")) { + if (parameters[paramkey].example !== undefined && parameters[paramkey].example !== null && parameters[paramkey].example.length > 0) { + parameters[paramkey].value = parameters[paramkey].example + } else { + parameters[paramkey].value = "" + } + } + } + + //parameters = app.actions[0].parameters; + } + + if ( + app.actions[actionIndex].returns !== undefined && + app.actions[actionIndex].returns !== null && + app.actions[actionIndex].returns.example !== undefined && + app.actions[actionIndex].returns.example !== null && + app.actions[actionIndex].returns.example.length > 0 + ) { + example = app.actions[actionIndex].returns.example; + } + + if ( + app.actions[actionIndex].description !== undefined && + app.actions[actionIndex].description !== null && + app.actions[actionIndex].description.length > 0 + ) { + description = app.actions[actionIndex].description + } + + var parsedEnvironments = + environments === null || environments === [] + ? "cloud" + : environments[defaultEnvironmentIndex] === undefined + ? "cloud" + : environments[defaultEnvironmentIndex].Name; + + // List other nodes in the workflow and see if they have an environment set. If they do, use that as the default + if (cy !== undefined && cy !== null) { + const foundnodes = cy.nodes().jsons() + if (foundnodes !== undefined && foundnodes !== null && foundnodes.length > 0) { + // As they should all be the same, this is just an override + for (let nodekey in foundnodes) { + const curnode = foundnodes[nodekey] + if (curnode.data.environment !== undefined && curnode.data.environment !== null && curnode.data.environment.length > 0) { + parsedEnvironments = curnode.data.environment + break + } + } + } + } + + const newAppData = { + name: app.actions[actionIndex].name, + label: actionLabel, + app_name: app.name, + app_version: app.app_version, + app_id: app.id, + sharing: app.sharing, + private_id: app.private_id, + description: description, + environment: parsedEnvironments, + errors: [], + finished: false, + id_: newNodeId, + _id_: newNodeId, + id: newNodeId, + is_valid: true, + type: actionType, + parameters: parameters, + isStartNode: false, + large_image: app.large_image, + run_magic_output: false, + authentication: [], + execution_variable: undefined, + example: example, + required_body_fields: app.actions[actionIndex].required_body_fields, + category: + app.categories !== null && + app.categories !== undefined && + app.categories.length > 0 + ? app.categories[0] + : "", + authentication_id: "", + finished: false, + template: app.template === true ? true : false, + }; + + // FIXME: overwrite category if the ACTION chosen has a different category + // + + if (!isCloud && (!app.is_valid || (!app.activated && app.generated))) { + console.log("NOT VALID: Activate!") + + activateApp(app.id, false) + } + + // const image = "url("+app.large_image+")" + // FIXME - find the cytoscape offset position + // Can this be done with zoom calculations? + const nodeToBeAdded = { + group: "nodes", + data: newAppData, + renderedPosition: { + x: e.pageX - cycontainer.offsetLeft, + y: e.pageY - cycontainer.offsetTop, + }, + }; + + parsedApp = nodeToBeAdded; + cy.add(nodeToBeAdded); + return; + } + } + }; + + const getNextActionName = (appName) => { var highest = "";