Fixed code editor and small ui changes in workflow ui

This commit is contained in:
Frikky
2024-03-15 14:39:50 +01:00
parent b5d04bef13
commit b8e9599053
5 changed files with 644 additions and 287 deletions
+69 -11
View File
@@ -456,14 +456,33 @@ const ParsedAction = (props) => {
if (workflow.execution_variables !== null && workflow.execution_variables !== undefined && workflow.execution_variables.length > 0) { if (workflow.execution_variables !== null && workflow.execution_variables !== undefined && workflow.execution_variables.length > 0) {
for (let [key,keyval] in Object.entries(workflow.execution_variables)) { for (let [key,keyval] in Object.entries(workflow.execution_variables)) {
const item = workflow.execution_variables[key]; const item = workflow.execution_variables[key]
var exampleoutput = ""
for (let execkey in workflowExecutions) {
const exec = workflowExecutions[execkey]
if (exec["execution_variables"] === undefined || exec["execution_variables"] === null) {
continue
}
const foundExec = exec.execution_variables.find((exvar) => exvar.name === item.name)
if (!foundExec) {
continue
}
if (foundExec.value !== undefined && foundExec.value !== null && foundExec.value.length > 0) {
exampleoutput = foundExec.value
break
}
}
actionlist.push({ actionlist.push({
type: "execution_variable", type: "execution_variable",
name: item.name, name: item.name,
value: item.value, value: item.value,
id: item.id, id: item.id,
autocomplete: `${item.name.split(" ").join("_")}`, autocomplete: `${item.name.split(" ").join("_")}`,
example: "", example: exampleoutput,
}); });
} }
} }
@@ -2711,11 +2730,39 @@ const ParsedAction = (props) => {
) )
} }
//const CustomPopper = function (props) { const sortByCategoryLabel = (a, b) => {
// const classes = useStyles() const aHasCategoryLabel = a.category_label !== undefined && a.category_label !== null && a.category_label.length > 0
// return <Popper {...props} className={classes.root} placement="bottom" /> const bHasCategoryLabel = b.category_label !== undefined && b.category_label !== null && b.category_label.length > 0
//}
//console.log("env: ", selectedActionEnvironment) // 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
})
}
// 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))
var baselabel = selectedAction.label; var baselabel = selectedAction.label;
return ( return (
@@ -2743,7 +2790,7 @@ const ParsedAction = (props) => {
onClick={() => { onClick={() => {
if (workflowExecutions.length > 0) { if (workflowExecutions.length > 0) {
// Look for the ID // Look for the ID
const found = false; var found = false;
for (let [key,keyval] in Object.entries(workflowExecutions)) { for (let [key,keyval] in Object.entries(workflowExecutions)) {
if (workflowExecutions[key].results === undefined || workflowExecutions[key].results === null) { if (workflowExecutions[key].results === undefined || workflowExecutions[key].results === null) {
continue; continue;
@@ -2758,7 +2805,6 @@ const ParsedAction = (props) => {
} }
const oldstartnode = cy.getElementById(selectedAction.id); const oldstartnode = cy.getElementById(selectedAction.id);
console.log("FOUND NODe: ", oldstartnode)
if (oldstartnode !== undefined && oldstartnode !== null) { if (oldstartnode !== undefined && oldstartnode !== null) {
const foundname = oldstartnode.data("label") const foundname = oldstartnode.data("label")
if (foundname !== undefined && foundname !== null) { if (foundname !== undefined && foundname !== null) {
@@ -2769,10 +2815,16 @@ const ParsedAction = (props) => {
setSelectedResult(foundResult); setSelectedResult(foundResult);
if (setCodeModalOpen !== undefined) { if (setCodeModalOpen !== undefined) {
setCodeModalOpen(true); setCodeModalOpen(true);
found = true
} }
break; break;
} }
if (!found) {
toast("No result for this action yet. Please run the workflow first.")
}
} }
}} }}
> >
@@ -2804,6 +2856,7 @@ const ParsedAction = (props) => {
<DescriptionIcon style={{ color: "rgba(255,255,255,0.7)" }} /> <DescriptionIcon style={{ color: "rgba(255,255,255,0.7)" }} />
</Tooltip> </Tooltip>
</IconButton> </IconButton>
{/*
<IconButton <IconButton
style={{ style={{
marginTop: "auto", marginTop: "auto",
@@ -2829,6 +2882,7 @@ const ParsedAction = (props) => {
</Tooltip> </Tooltip>
</a> </a>
</IconButton> </IconButton>
*/}
{/* {/*
<IconButton <IconButton
style={{ style={{
@@ -2865,6 +2919,7 @@ const ParsedAction = (props) => {
</Tooltip> </Tooltip>
</IconButton> </IconButton>
*/} */}
{/*
<IconButton <IconButton
style={{ style={{
marginTop: "auto", marginTop: "auto",
@@ -2886,6 +2941,7 @@ const ParsedAction = (props) => {
</a> </a>
</Tooltip> </Tooltip>
</IconButton> </IconButton>
*/}
<IconButton <IconButton
style={{ style={{
marginTop: "auto", marginTop: "auto",
@@ -2906,7 +2962,7 @@ const ParsedAction = (props) => {
> >
<Tooltip <Tooltip
color="primary" color="primary"
title={"Autocomplete fields. Will show a popup so that you can query how you would like to fill it in"} title={"Autocomplete fields. Uses the name of the current action, the fields and previous actions' results"}
placement="top" placement="top"
> >
{autoCompleting ? {autoCompleting ?
@@ -3560,6 +3616,8 @@ const ParsedAction = (props) => {
return option.category_label !== undefined && option.category_label !== null && option.category_label.length > 0 ? "Most used" : "All Actions"; return option.category_label !== undefined && option.category_label !== null && option.category_label.length > 0 ? "Most used" : "All Actions";
}} }}
renderGroup={(params) => { renderGroup={(params) => {
//return null
return ( return (
<li key={params.key}> <li key={params.key}>
<Typography variant="body1" style={{textAlign: "center", marginLeft: 10, marginTop: 25, marginBottom: 10, }}>{params.group}</Typography> <Typography variant="body1" style={{textAlign: "center", marginLeft: 10, marginTop: 25, marginBottom: 10, }}>{params.group}</Typography>
@@ -3567,7 +3625,7 @@ const ParsedAction = (props) => {
</li> </li>
) )
}} }}
options={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"))} options={renderedActionOptions}
ListboxProps={{ ListboxProps={{
style: { style: {
backgroundColor: theme.palette.surfaceColor, backgroundColor: theme.palette.surfaceColor,
+8 -12
View File
@@ -676,6 +676,8 @@ const CodeEditor = (props) => {
for (var i = 0; i < found.length; i++) { for (var i = 0; i < found.length; i++) {
try { try {
const fixedVariable = fixVariable(found[i]) const fixedVariable = fixVariable(found[i])
// Finding if the value is in the list at all, and does initial replacement
var valuefound = false var valuefound = false
for (var j = 0; j < actionlist.length; j++) { for (var j = 0; j < actionlist.length; j++) {
if(fixedVariable.slice(1,).toLowerCase() !== actionlist[j].autocomplete.toLowerCase()){ if(fixedVariable.slice(1,).toLowerCase() !== actionlist[j].autocomplete.toLowerCase()){
@@ -697,12 +699,13 @@ const CodeEditor = (props) => {
} catch (e) { } catch (e) {
input = input.replace(found[i], actionlist[j].example, -1) input = input.replace(found[i], actionlist[j].example, -1)
} }
} }
//console.log("INPUT: ", fixedVariable, valuefound, input)
//if (!valuefound) { if (!valuefound) {
// console.log("Couldn't find value "+fixedVariable) //console.log("Couldn't find value "+fixedVariable)
//} }
if (!valuefound && availableVariables.includes(fixedVariable)) { if (!valuefound && availableVariables.includes(fixedVariable)) {
var shouldbreak = false var shouldbreak = false
@@ -729,8 +732,6 @@ const CodeEditor = (props) => {
console.log("ERR IN INPUT: ", e) console.log("ERR IN INPUT: ", e)
} }
//console.log("Got output for: ", fullpath, new_input, actionlist[k].example, typeof new_input)
if (typeof new_input === "object") { if (typeof new_input === "object") {
new_input = JSON.stringify(new_input) new_input = JSON.stringify(new_input)
} else { } else {
@@ -752,10 +753,6 @@ const CodeEditor = (props) => {
input = input.replace(fixedVariable, new_input, -1) input = input.replace(fixedVariable, new_input, -1)
input = input.replace(found[i], new_input, -1) input = input.replace(found[i], new_input, -1)
//} catch (e) {
// input = input.replace(found[i], actionlist[k].example)
//}
shouldbreak = true shouldbreak = true
break break
} }
@@ -1498,7 +1495,6 @@ const CodeEditor = (props) => {
backgroundColor: "rgba(40,40,40,1)", backgroundColor: "rgba(40,40,40,1)",
}} }}
onLoad={(editor) => { onLoad={(editor) => {
console.log("LOAD: ", editor)
highlight_variables(localcodedata) highlight_variables(localcodedata)
}} }}
onCursorChange={(cursorPosition, editor, value) => { onCursorChange={(cursorPosition, editor, value) => {
@@ -1591,7 +1587,7 @@ const CodeEditor = (props) => {
minheight: 450, minheight: 450,
overflow: "auto", overflow: "auto",
minWidth: 450, minWidth: 450,
maxWidth: 450, maxWidth: "100%",
}} }}
collapsed={false} collapsed={false}
enableClipboard={(copy) => { enableClipboard={(copy) => {
+15 -1
View File
@@ -34,6 +34,20 @@ const data = [
"z-index": 5001, "z-index": 5001,
}, },
}, },
{
selector: `node[buttonType="ACTIONSUGGESTION"]`,
css: {
label: "data(label)",
shape: "roundrectangle",
"height": "16px",
"width": "120px",
"background-color": "#212121",
"border-color": "#81c784",
"z-index": 10000,
"border-radius": "10px",
"text-margin-x": "0px",
},
},
{ {
selector: `node[type="ACTION"]`, selector: `node[type="ACTION"]`,
css: { css: {
@@ -120,7 +134,7 @@ const data = [
{ {
selector: `node[type="TRIGGER"]`, selector: `node[type="TRIGGER"]`,
css: { css: {
shape: "octagon", shape: "round-octagon",
"border-radius": "5px", "border-radius": "5px",
"border-color": "orange", "border-color": "orange",
"background-color": "#213243", "background-color": "#213243",
+394 -103
View File
@@ -6,6 +6,7 @@ import theme from "../theme.jsx";
import { useInterval } from "react-powerhooks"; import { useInterval } from "react-powerhooks";
import { makeStyles, } from "@mui/styles"; import { makeStyles, } from "@mui/styles";
import WorkflowTemplatePopup from "../components/WorkflowTemplatePopup.jsx"
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import { useNavigate, Link, useParams } from "react-router-dom"; import { useNavigate, Link, useParams } from "react-router-dom";
import { useBeforeunload } from "react-beforeunload"; import { useBeforeunload } from "react-beforeunload";
@@ -25,6 +26,7 @@ import algoliasearch from 'algoliasearch/lite';
import { import {
Zoom, Zoom,
Fade, Fade,
Slide,
Avatar, Avatar,
Popover, Popover,
@@ -535,6 +537,8 @@ const AngularWorkflow = (defaultprops) => {
const [workflowExecutionCount, setWorkflowExecutionCount] = React.useState(0); const [workflowExecutionCount, setWorkflowExecutionCount] = React.useState(0);
const [defaultEnvironmentIndex, setDefaultEnvironmentIndex] = React.useState(0); const [defaultEnvironmentIndex, setDefaultEnvironmentIndex] = React.useState(0);
const [workflowRecommendations, setWorkflowRecommendations] = React.useState(undefined); const [workflowRecommendations, setWorkflowRecommendations] = React.useState(undefined);
const [showErrors, setShowErrors] = React.useState(true);
const [highlightedApp, setHighlightedApp] = React.useState("")
const [listCache, setListCache] = React.useState([]); const [listCache, setListCache] = React.useState([]);
const [suggestionBox, setSuggestionBox] = React.useState({ const [suggestionBox, setSuggestionBox] = React.useState({
@@ -557,6 +561,59 @@ const AngularWorkflow = (defaultprops) => {
"field_id": "", "field_id": "",
}) })
// Event for making sure app is correct
useEffect(() => {
if (selectedApp === undefined || selectedApp === null && selectedApp.app_name === undefined) {
return
}
if (apps === undefined || apps === null || apps.length === 0) {
return
}
// Handle the activation case, as they are NOT in the event management system yet
if (selectedApp.actions === undefined || selectedApp.actions === null || selectedApp.actions.length > 1) {
return
}
console.log("Checking to update app with useeffect.")
for (let appkey in apps) {
const curapp = apps[appkey]
if (curapp.name !== selectedApp.name) {
continue
}
console.log("Found app: ", curapp)
if (curapp.actions !== undefined && curapp.actions !== null && curapp.actions.length > selectedApp.actions.length) {
var foundActionIndex = -1
for (let actionkey in curapp.actions) {
const curaction = curapp.actions[actionkey]
// First action with a label, as they are most used (typically)
if (curaction.category_label !== undefined && curaction.category_label !== null && curaction.category_label.length > 0) {
foundActionIndex = actionkey
break
}
}
if (foundActionIndex >= 0) {
var newaction = curapp.actions[foundActionIndex]
setNewSelectedAction({
"target": {
"value": newaction.name
},
})
}
setSelectedApp(curapp)
}
break
}
}, [selectedApp])
const [executionArgumentModalOpen, setExecutionArgumentModalOpen] = React.useState(false); const [executionArgumentModalOpen, setExecutionArgumentModalOpen] = React.useState(false);
// This should all be set once, not on every iteration // This should all be set once, not on every iteration
@@ -569,32 +626,6 @@ const AngularWorkflow = (defaultprops) => {
: false; : false;
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
useEffect(() => {
return () => {
console.log("UNMOUNTING USER!")
sendStreamRequest({
"item": "workflow",
"type": "leave",
"id": workflow.id,
})
}
}, [])
/*
useEffect(() => {
console.log("In useeffect for workflow: ", workflow)
if (cy === undefined || cy === null) {
return
}
if (workflow === undefined || workflow === null || workflow.actions === undefined || workflow.actions === null) {
return
}
// Check if actions of original vs new are changed
fetchRecommendations(workflow)
}, [workflow])
*/
const appBarSize = isCloud ? 75 : 72; const appBarSize = isCloud ? 75 : 72;
const triggerEnvironments = isCloud ? ["cloud"] : ["onprem", "cloud"]; const triggerEnvironments = isCloud ? ["cloud"] : ["onprem", "cloud"];
const unloadText = "Are you sure you want to leave without saving (CTRL+S)?"; const unloadText = "Are you sure you want to leave without saving (CTRL+S)?";
@@ -2108,23 +2139,24 @@ const AngularWorkflow = (defaultprops) => {
setPrioritizedApps(responseJson.filter((app) => internalIds.includes(app.name.toLowerCase()))); setPrioritizedApps(responseJson.filter((app) => internalIds.includes(app.name.toLowerCase())));
} else { } else {
//setFilteredApps(
// responseJson.filter(
// (app) =>
// !internalIds.includes(app.name) &&
// !(!app.activated && app.generated)
// )
//);
var tmpFiltered = responseJson.filter((app) => !internalIds.includes(app.name.toLowerCase())) var tmpFiltered = responseJson.filter((app) => !internalIds.includes(app.name.toLowerCase()))
//tmpFiltered = sortByKey(tmpFiltered, "activated")
setFilteredApps(tmpFiltered) setFilteredApps(tmpFiltered)
//!(!app.activated && app.generated)
setPrioritizedApps(responseJson.filter((app) => internalIds.includes(app.name.toLowerCase()))); setPrioritizedApps(responseJson.filter((app) => internalIds.includes(app.name.toLowerCase())));
} }
setAppsLoaded(true) setAppsLoaded(true)
// Remove all cytoscape triggers first?
if (cy !== undefined && cy !== null) {
cy.removeListener("select");
}
// Re-adding cytoscape triggers
if (cy !== undefined && cy !== null) {
cy.on("select", "node", (e) => {
onNodeSelect(e, appAuthentication);
});
}
}) })
.catch((error) => { .catch((error) => {
console.log("App loading error: " + error.toString()); console.log("App loading error: " + error.toString());
@@ -3586,7 +3618,70 @@ const AngularWorkflow = (defaultprops) => {
//const data = JSON.parse(JSON.stringify(event.target.data())) //const data = JSON.parse(JSON.stringify(event.target.data()))
const data = event.target.data() const data = event.target.data()
if (data.isSuggestion === true) {
if (data.buttonType == "ACTIONSUGGESTION") {
const attachedToId = data.attachedTo
const parentitem = cy.getElementById(data.attachedTo).data()
if (parentitem !== null && parentitem !== undefined) {
const findaction = data.label
console.log("CLICKED: ", findaction, apps.length)
for (let appkey in apps) {
const curapp = apps[appkey]
if (curapp.name !== parentitem.app_name) {
continue
}
if (curapp.actions === undefined || curapp.actions === null) {
continue
}
for (let actionkey in curapp.actions) {
const curaction = curapp.actions[actionkey]
if (curaction.category_label !== undefined && curaction.category_label !== null && curaction.category_label.length > 0) {
if (curaction.category_label[0].toLowerCase() === findaction.toLowerCase()) {
console.log("FOUND: ", curaction)
// Update the action itself
// Find the action index, and update:
// - label
// - description
// - parameters
// - name
var foundindex = -1
for (let wfactionkey in workflow.actions) {
const wfaction = workflow.actions[wfactionkey]
if (wfaction.id === data.attachedTo) {
foundindex = wfactionkey
break
}
}
console.log("Updating action: ", foundindex, findaction)
if (foundindex >= 0) {
workflow.actions[foundindex].label = findaction
workflow.actions[foundindex].description = curaction.description
workflow.actions[foundindex].parameters = curaction.parameters
workflow.actions[foundindex].name = curaction.name
setWorkflow(workflow)
}
break
}
}
}
break
}
return
}
} else if (data.isSuggestion === true) {
console.log("Suggestion! Replace with a real action.") console.log("Suggestion! Replace with a real action.")
const attachedToId = data.attachedTo const attachedToId = data.attachedTo
@@ -4115,7 +4210,6 @@ const AngularWorkflow = (defaultprops) => {
//} //}
//curaction.parameters = newparams //curaction.parameters = newparams
console.log("ACTION CLICK: ", curaction)
setSelectedApp(curapp); setSelectedApp(curapp);
setSelectedAction(curaction); setSelectedAction(curaction);
@@ -4268,8 +4362,10 @@ const AngularWorkflow = (defaultprops) => {
toast("Failed to auto-activate the app. Go to /apps and activate it.") toast("Failed to auto-activate the app. Go to /apps and activate it.")
} else { } else {
if (refresh === true) { if (refresh === true) {
setHighlightedApp(appid)
//toast("App activated for your organization! Refresh the page to use the app.") //toast("App activated for your organization! Refresh the page to use the app.")
getApps() getApps()
} }
} }
}) })
@@ -5392,7 +5488,6 @@ const AngularWorkflow = (defaultprops) => {
} }
if (nodedata.finished === false) { if (nodedata.finished === false) {
console.log("NODE UNFINISHED HOVEROUT: ", nodedata)
// Should just be 1, so this should be fast enough :3 // Should just be 1, so this should be fast enough :3
const incomingEdges = event.target.incomers("edge").jsons() const incomingEdges = event.target.incomers("edge").jsons()
@@ -5567,6 +5662,87 @@ const AngularWorkflow = (defaultprops) => {
}); });
}; };
const addActionSuggestions = (nodedata, event) => {
console.log("App Action suggestions disabled for now")
return
if (nodedata.type !== "ACTION") {
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 parentlabel = parentNode.data("label").toLowerCase().replace(" ", "_")
const parentname = parentNode.data("app_name").toLowerCase().replace(" ", "_")
if (!parentlabel.startsWith(parentname)) {
console.log("Bad startname to start with: ", parentname, parentlabel)
return
}
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 = `<svg width="${svgSize}" height="${svgSize}" viewBox="0 0 ${svgSize} ${svgSize}" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="${iconInfo.icon}" fill="${iconInfo.iconColor}"></path></svg>`;
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 added = 0
for (let appKey in apps) {
const curapp = apps[appKey]
if (curapp.name.toLowerCase().replace(" ", "_") !== parentname) {
continue
}
if (curapp.actions === undefined || curapp.actions === null || curapp.actions.length === 0) {
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 (curaction.category_label !== undefined && curaction.category_label !== null && curaction.category_label.length > 0) {
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 + (added * 50),
},
})
added += 1
if (added >= 2) {
break
}
}
}
break
}
}
const addSuggestionButtons = (nodedata, event) => { const addSuggestionButtons = (nodedata, event) => {
//console.log("Skipping Adding suggestion buttons") //console.log("Skipping Adding suggestion buttons")
//return //return
@@ -5610,8 +5786,6 @@ const AngularWorkflow = (defaultprops) => {
*/ */
} }
console.log("RECS: ", workflowRecommendations)
if (workflowRecommendations === undefined || workflowRecommendations === null || workflowRecommendations.length === 0) { if (workflowRecommendations === undefined || workflowRecommendations === null || workflowRecommendations.length === 0) {
return return
} }
@@ -5816,6 +5990,7 @@ const AngularWorkflow = (defaultprops) => {
cytoscapeElement.style.cursor = "pointer" cytoscapeElement.style.cursor = "pointer"
} }
sendStreamRequest({ sendStreamRequest({
"item": "node", "item": "node",
"type": "hover", "type": "hover",
@@ -5936,6 +6111,8 @@ const AngularWorkflow = (defaultprops) => {
// autocomplete // autocomplete
// right click // right click
// suggestions // suggestions
addActionSuggestions(nodedata, event);
if (workflow.actions.length < 4) { if (workflow.actions.length < 4) {
addSuggestionButtons(nodedata, event); addSuggestionButtons(nodedata, event);
} else { } else {
@@ -5944,6 +6121,7 @@ const AngularWorkflow = (defaultprops) => {
} }
} }
var parsedStyle = { var parsedStyle = {
"border-width": "7px", "border-width": "7px",
"border-opacity": ".7", "border-opacity": ".7",
@@ -6007,7 +6185,7 @@ const AngularWorkflow = (defaultprops) => {
if (incomingEdges.length > 0) { if (incomingEdges.length > 0) {
outgoingEdges.addClass("hover-highlight"); outgoingEdges.addClass("hover-highlight");
} }
}; }
const onEdgeHoverOut = (event) => { const onEdgeHoverOut = (event) => {
if (event === null || event === undefined || event.target === null || event.target === undefined) { if (event === null || event === undefined || event.target === null || event.target === undefined) {
@@ -6650,8 +6828,6 @@ const AngularWorkflow = (defaultprops) => {
} }
const getRevisionHistory = (workflow_id) => { const getRevisionHistory = (workflow_id) => {
console.log("Loading revisions for workflow ID ", workflow_id)
fetch(`${globalUrl}/api/v1/workflows/${workflow_id}/revisions`, { fetch(`${globalUrl}/api/v1/workflows/${workflow_id}/revisions`, {
method: "GET", method: "GET",
headers: { headers: {
@@ -6816,7 +6992,6 @@ const AngularWorkflow = (defaultprops) => {
cy.on("boxstart", (e) => { cy.on("boxstart", (e) => {
console.log("START"); console.log("START");
//cy.removeListener("select");
}); });
cy.on("boxend", (e) => { cy.on("boxend", (e) => {
@@ -7940,10 +8115,17 @@ const AngularWorkflow = (defaultprops) => {
? `${pixelSize} solid ${green}` ? `${pixelSize} solid ${green}`
: `${pixelSize} solid ${yellow}`; : `${pixelSize} solid ${yellow}`;
if (app.id == highlightedApp) {
console.log("Found correct appid to highlight: ", app.id)
newAppStyle.border = "3px solid " + green
}
if (!app.activated && app.generated) { if (!app.activated && app.generated) {
newAppStyle.borderLeft = `${pixelSize} solid ${yellow}`; newAppStyle.borderLeft = `${pixelSize} solid ${yellow}`;
} }
return ( return (
<Draggable <Draggable
onDrag={(e) => { onDrag={(e) => {
@@ -8235,9 +8417,40 @@ const AngularWorkflow = (defaultprops) => {
hits = hits.slice(0, 4) hits = hits.slice(0, 4)
} }
const clickedApp = (hit) => {
toast(`Activating App. Please wait a moment.`)
const queryID = hit.__queryID
if (queryID !== undefined && queryID !== null) {
aa('init', {
appId: "JNSS5CFDZZ",
apiKey: "db08e40265e2941b9a7d8f644b6e5240",
})
const timestamp = new Date().getTime()
aa('sendEvents', [
{
eventType: 'conversion',
eventName: 'Public App Activated',
index: 'appsearch',
objectIDs: [hit.objectID],
timestamp: timestamp,
queryID: queryID,
userToken: userdata === undefined || userdata === null || userdata.id === undefined ? "unauthenticated" : userdata.id,
}
])
} else {
console.log("No query to handle when activating")
}
activateApp(hit.objectID, true)
}
var type = "app" var type = "app"
const baseImage = <LibraryBooksIcon /> const baseImage = <LibraryBooksIcon />
return ( return (
<div style={{ position: "relative", marginTop: 15, marginLeft: 0, marginRight: 10, position: "absolute", color: "white", zIndex: 1001, backgroundColor: theme.palette.inputColor, minWidth: leftBarSize - 10, maxWidth: leftBarSize - 10, boxShadows: "none", overflowX: "hidden", }}> <div style={{ position: "relative", marginTop: 15, marginLeft: 0, marginRight: 10, position: "absolute", color: "white", zIndex: 1001, backgroundColor: theme.palette.inputColor, minWidth: leftBarSize - 10, maxWidth: leftBarSize - 10, boxShadows: "none", overflowX: "hidden", }}>
<List style={{ backgroundColor: theme.palette.inputColor, }}> <List style={{ backgroundColor: theme.palette.inputColor, }}>
@@ -8310,46 +8523,30 @@ const AngularWorkflow = (defaultprops) => {
var parsedUrl = isCloud ? `/apps/${hit.objectID}` : `https://shuffler.io/apps/${hit.objectID}` var parsedUrl = isCloud ? `/apps/${hit.objectID}` : `https://shuffler.io/apps/${hit.objectID}`
parsedUrl += `?queryID=${hit.__queryID}` parsedUrl += `?queryID=${hit.__queryID}`
var appdragged = false
return ( return (
<Draggable
onDrag={(e) => {
e.preventDefault()
e.stopPropagation()
if (!appdragged) {
clickedApp(hit)
}
appdragged = true
}}
onStop={(e) => {
}}
dragging={false}
position={{
x: 0,
y: 0,
}}
>
<div style={{ textDecoration: "none", color: "white", }} onClick={(event) => { <div style={{ textDecoration: "none", color: "white", }} onClick={(event) => {
//if (!isCloud) { clickedApp(hit)
// toast("Since this is an on-prem instance. You will need to activate the app yourself. Opening link to download it in a new window.")
// setTimeout(() => {
// event.preventDefault()
// window.open(parsedUrl, '_blank')
// }, 2000)
//} else {
toast(`Activating ${name}`)
//}
console.log("CLICK: ", hit)
const queryID = hit.__queryID
console.log("QUERY: ", queryID)
if (queryID !== undefined && queryID !== null) {
aa('init', {
appId: "JNSS5CFDZZ",
apiKey: "db08e40265e2941b9a7d8f644b6e5240",
})
const timestamp = new Date().getTime()
aa('sendEvents', [
{
eventType: 'conversion',
eventName: 'Public App Activated',
index: 'appsearch',
objectIDs: [hit.objectID],
timestamp: timestamp,
queryID: queryID,
userToken: userdata === undefined || userdata === null || userdata.id === undefined ? "unauthenticated" : userdata.id,
}
])
} else {
console.log("No query to handle when activating")
}
activateApp(hit.objectID, true)
}}> }}>
<ListItem key={hit.objectID} style={innerlistitemStyle} onMouseOver={() => { <ListItem key={hit.objectID} style={innerlistitemStyle} onMouseOver={() => {
setMouseHoverIndex(index) setMouseHoverIndex(index)
@@ -8370,6 +8567,7 @@ const AngularWorkflow = (defaultprops) => {
*/} */}
</ListItem> </ListItem>
</div> </div>
</Draggable>
) )
}) })
} }
@@ -8449,7 +8647,7 @@ const AngularWorkflow = (defaultprops) => {
) )
})} })}
{visibleApps.length <= 4 ? ( {visibleApps.length <= 2 ?
<div <div
style={{ textAlign: "center", width: leftBarSize, marginTop: 40, maxWidth: 340, overflow: "hidden", }} style={{ textAlign: "center", width: leftBarSize, marginTop: 40, maxWidth: 340, overflow: "hidden", }}
onLoad={() => { onLoad={() => {
@@ -8467,7 +8665,7 @@ const AngularWorkflow = (defaultprops) => {
</Index> </Index>
</InstantSearch> </InstantSearch>
</div> </div>
) : :
<div <div
style={{marginTop: 100, }} style={{marginTop: 100, }}
/>} />}
@@ -8542,6 +8740,8 @@ const AngularWorkflow = (defaultprops) => {
return return
} }
console.log("action input: ", e)
const newaction = selectedApp.actions.find( const newaction = selectedApp.actions.find(
(a) => a.name === e.target.value (a) => a.name === e.target.value
); );
@@ -8570,8 +8770,6 @@ const AngularWorkflow = (defaultprops) => {
newSelectedAction.is_valid = true; newSelectedAction.is_valid = true;
newSelectedAction.required_body_fields = newaction.required_body_fields newSelectedAction.required_body_fields = newaction.required_body_fields
console.log("New selected action: ", newSelectedAction)
// Simple action swap autocompleter // Simple action swap autocompleter
if (oldaction.parameters !== undefined && oldaction.parameters !== null && newSelectedAction.parameters !== undefined && oldaction.id === newSelectedAction.id) { if (oldaction.parameters !== undefined && oldaction.parameters !== null && newSelectedAction.parameters !== undefined && oldaction.id === newSelectedAction.id) {
var fileid_found = false var fileid_found = false
@@ -8661,7 +8859,11 @@ const AngularWorkflow = (defaultprops) => {
// Further checks if those fields are already set in a previously used action // Further checks if those fields are already set in a previously used action
newSelectedAction = RunAutocompleter(newSelectedAction); newSelectedAction = RunAutocompleter(newSelectedAction);
console.log("newaction: ", newaction)
if ( if (
newaction.return !== undefined &&
newaction.return !== null &&
newaction.returns.example !== undefined && newaction.returns.example !== undefined &&
newaction.returns.example !== null && newaction.returns.example !== null &&
newaction.returns.example.length > 0 newaction.returns.example.length > 0
@@ -12161,12 +12363,6 @@ const AngularWorkflow = (defaultprops) => {
selectedTrigger.app_association = parsedvalue selectedTrigger.app_association = parsedvalue
setUpdate(Math.random()); setUpdate(Math.random());
} }
// setNewSelectedAction({
// target: {
// value: newValue.name
// }
// });
//}
}} }}
renderOption={(props, app, state) => { renderOption={(props, app, state) => {
var appname = app.name.replaceAll("_", " ") var appname = app.name.replaceAll("_", " ")
@@ -14068,7 +14264,7 @@ const AngularWorkflow = (defaultprops) => {
) )
} }
const showErrors = !isMobile && !workflow.public && workflow.errors !== undefined && workflow.errors !== null && workflow.errors.length > 0 ? const shownErrors = !isMobile && !workflow.public && workflow.errors !== undefined && workflow.errors !== null && workflow.errors.length > 0 && showErrors ?
<div <div
style={{ style={{
border: "1px solid rgba(255,255,255,0.1)", border: "1px solid rgba(255,255,255,0.1)",
@@ -14080,6 +14276,24 @@ const AngularWorkflow = (defaultprops) => {
borderRadius: theme.palette.borderRadius, borderRadius: theme.palette.borderRadius,
}} }}
> >
<Tooltip
title="Hide error messages. They will show up the next refresh."
placement="top"
>
<IconButton
style={{ position: "absolute", top: 0, right: 0}}
onClick={(e) => {
e.preventDefault();
// A temporary hider thing
setShowErrors(false)
}}
>
<CloseIcon style={{ color: "white" }} />
</IconButton>
</Tooltip>
<Typography variant="body22"> <Typography variant="body22">
{/*<WarningIcon style={{marginRight: 5, height: 15, width: 15, }} />*/} {/*<WarningIcon style={{marginRight: 5, height: 15, width: 15, }} />*/}
@@ -16653,30 +16867,48 @@ const AngularWorkflow = (defaultprops) => {
return "" return ""
} }
// Validate and check for newlines
if (result.success !== false) { 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"
}
}
}
return "" return ""
} }
var stringjson = result
try { try {
stringjson = JSON.stringify(result) stringjson = JSON.stringify(result)
} catch (e) { } catch (e) {
} }
console.log("JSON: ", stringjson)
stringjson = stringjson.toLowerCase() stringjson = stringjson.toLowerCase()
if (stringjson.includes("localhost")) { if (stringjson.includes("localhost")) {
return "You can't use localhost in apps. Use the external ip or url of the server instead" return "You can't use localhost in apps. Use the external ip or url of the server instead"
} }
if (stringjson.includes("connectionerror")) { if (stringjson.includes("connectionerror")) {
return "Your URL is most likely incorrect." if (stringjson.includes("kms")) {
return "KMS authentication failed. Check your notifications for more details."
}
return "Your URL is incorrect."
} }
if (stringjson.includes("result too large to handle")) { if (stringjson.includes("result too large to handle")) {
return "Execution loading failed. Reload the execution by closing it and clicking it again" return "Execution loading failed. Reload the execution by closing it and clicking it again"
} }
return "" return ""
} }
@@ -16944,17 +17176,17 @@ const AngularWorkflow = (defaultprops) => {
<span <span
style={{ style={{
wordBreak: "break-word", wordBreak: "break-word",
display: "inline-block",
whiteSpace: "pre-wrap",
}} }}
onClick={() => { onClick={() => {
console.log("IN HERE TO CLICK");
to_be_copied = selectedResult.result; to_be_copied = selectedResult.result;
var copyText = document.getElementById( var copyText = document.getElementById(
"copy_element_shuffle" "copy_element_shuffle"
); );
console.log("PRECOPY: ", to_be_copied);
if (copyText !== null && copyText !== undefined) { if (copyText !== null && copyText !== undefined) {
console.log("COPY: ", copyText);
console.log("NAVIGATOR: ", navigator);
const clipboard = navigator.clipboard; const clipboard = navigator.clipboard;
if (clipboard === undefined) { if (clipboard === undefined) {
toast("Can only copy over HTTPS (port 3443)"); toast("Can only copy over HTTPS (port 3443)");
@@ -17139,7 +17371,7 @@ const AngularWorkflow = (defaultprops) => {
{showWorkflowRevisions ? null : {showWorkflowRevisions ? null :
<span> <span>
{/*<BottomAvatars />*/} {/*<BottomAvatars />*/}
{showErrors} {shownErrors}
<BottomCytoscapeBar /> <BottomCytoscapeBar />
<TopCytoscapeBar /> <TopCytoscapeBar />
<RightsideBar /> <RightsideBar />
@@ -18813,6 +19045,63 @@ const AngularWorkflow = (defaultprops) => {
//setUpdate(Math.random()) //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
}
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 (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
}
}
}
const foundusecase.name === undefined || foundusecase.name === null || foundusecase.name === "" ? null :
<Slide direction="down" in={true} mountOnEnter unmountOnExit>
<div style={{position: "fixed", top: "10%", left: "37%", border: "1px solid rgba(255,255,255,0.3)", backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius, display: "flex", }}>
<WorkflowTemplatePopup
isLoggedIn={isLoggedIn}
userdata={userdata}
globalUrl={globalUrl}
title={foundusecase.name.split("Suggested Usecase: ")[1]}
description={"Suggested usecase based on usage"}
srcapp={foundusecase.description.split("&")[0]}
img1={foundusecase.description.split("&")[1]}
dstapp={foundusecase.description.split("&")[2]}
img2={foundusecase.description.split("&")[3]}
/>
</div>
</Slide>
*/
const loadedCheck = const loadedCheck =
isLoaded && workflowDone ? ( isLoaded && workflowDone ? (
<div> <div>
@@ -18827,6 +19116,8 @@ const AngularWorkflow = (defaultprops) => {
{/*editWorkflowModal*/} {/*editWorkflowModal*/}
{executionArgumentModal} {executionArgumentModal}
{configureWorkflowModal} {configureWorkflowModal}
{/*usecaseSlidein*/}
<SuggestionBoxUi /> <SuggestionBoxUi />
{codeEditorModalOpen ? {codeEditorModalOpen ?
-2
View File
@@ -903,7 +903,6 @@ const UsecaseListComponent = (props) => {
isLoggedIn={isLoggedIn} isLoggedIn={isLoggedIn}
appFramework={frameworkData} appFramework={frameworkData}
userdata={userdata} userdata={userdata}
globalUrl={globalUrl} globalUrl={globalUrl}
img1={inputUsecase.srcimg} img1={inputUsecase.srcimg}
srcapp={inputUsecase.srcapp} srcapp={inputUsecase.srcapp}
@@ -911,7 +910,6 @@ const UsecaseListComponent = (props) => {
dstapp={inputUsecase.dstapp} dstapp={inputUsecase.dstapp}
title={inputUsecase.name} title={inputUsecase.name}
description={inputUsecase.description} description={inputUsecase.description}
apps={apps} apps={apps}
getAppFramework={getFramework} getAppFramework={getFramework}
//appSetupDone={appSetupDone} //appSetupDone={appSetupDone}