Workflow bugfixes and form updates

This commit is contained in:
Frikky
2024-11-19 01:37:56 +01:00
parent 9d14078732
commit 2439f9d986
12 changed files with 525 additions and 329 deletions
-55
View File
@@ -1,55 +0,0 @@
name: Upload App SDK to PiPy
on:
workflow_dispatch: # Allows the workflow to be run manually from GitHub
inputs:
version:
description: 'Version of the package to publish'
required: true
release:
types: [published]
push:
tags:
- 'v*' # Triggers when a version tag is pushed (e.g., v1.0.0)
permissions:
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: '3.x'
- name: Install dependencies
run: |
cd ./backend/app_sdk
python -m pip install --upgrade pip
pip install build
- name: Build package
run: |
cd ./backend/app_sdk
python -m build
- name: Move build artifacts
run: |
ls -alh
ls -alh ./backend/app_sdk
mv ./backend/app_sdk/dist ./dist
- name: Publish package
uses: pypa/gh-action-pypi-publish@v1.10.2
with:
verify-metadata: false
repository-url: https://upload.pypi.org/legacy/
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
env:
ACTIONS_STEP_DEBUG: true # Enables debug mode for this step
+10 -1
View File
@@ -464,8 +464,17 @@ const AppGrid = (props) => {
}} }}
> >
<img <img
id={`image_${index}`}
alt={data.name} alt={data.name}
src={data.image_url ? data.image_url : "/images/no_image.png"} src={data.image_url ? data.image_url : "/images/no_image.png"}
onError={(e) => {
// Replace the image with the default image
const foundImage = document.getElementById(`image_${index}`)
if (foundImage !== undefined && foundImage !== null) {
foundImage.src = theme.palette.defaultImage
data.image_url = theme.palette.defaultImage
}
}}
style={{ style={{
width: 80, width: 80,
height: 80, height: 80,
@@ -995,7 +1004,7 @@ const AppGrid = (props) => {
}} }}
autoComplete="off" autoComplete="off"
color="primary" color="primary"
placeholder="Search your Activated or Self-built apps" placeholder="Search your Activated or self-built apps"
id="shuffle_search_field" id="shuffle_search_field"
onChange={(event) => { onChange={(event) => {
setSearchQuery(event.currentTarget.value); setSearchQuery(event.currentTarget.value);
@@ -45,21 +45,21 @@ const AuthenticationItem = (props) => {
data.fields = [ data.fields = [
{ {
key: "url", key: "url",
value: "Secret. Replaced during app execution!", value: "URL Secret. Replaced during runtime",
}, },
{ {
key: "client_id", key: "client_id",
value: "Secret. Replaced during app execution!", value: "ClientID Secret. Replaced during runtime.",
}, },
{ {
key: "client_secret", key: "client_secret",
value: "Secret. Replaced during app execution!", value: "Client Secret. Replaced during runtime.",
}, },
{ {
key: "scope", key: "scope",
value: "Secret. Replaced during app execution!", value: "Scope Secret. Replaced during runtime.",
}, },
]; ]
} }
const deleteAuthentication = (data) => { const deleteAuthentication = (data) => {
@@ -330,8 +330,8 @@ const AuthenticationData = (props) => {
<Button <Button
style={{ borderRadius: theme.palette?.borderRadius, marginTop: authFieldsOnly ? 20 : 0 }} style={{ borderRadius: theme.palette?.borderRadius, marginTop: authFieldsOnly ? 20 : 0 }}
onClick={() => { onClick={() => {
setAuthenticationOptions(authenticationOption); setAuthenticationOptions(authenticationOption)
handleSubmitCheck(); handleSubmitCheck()
}} }}
variant={"contained"} variant={"contained"}
disabled={submitSuccessful} disabled={submitSuccessful}
+8 -6
View File
@@ -96,7 +96,7 @@ const AuthenticationOauth2 = (props) => {
autoAuth, autoAuth,
authButtonOnly, authButtonOnly,
isLoggedIn, isLoggedIn,
org_id,
setFinalized, setFinalized,
} = props; } = props;
@@ -148,7 +148,6 @@ const AuthenticationOauth2 = (props) => {
navigate(`/login?view=${window.location.pathname}&message=Log in to authenticate this app`) navigate(`/login?view=${window.location.pathname}&message=Log in to authenticate this app`)
} }
console.log("Should automatically click the auto-auth button?: ", autoAuth)
if (autoAuth === true && selectedApp !== undefined) { if (autoAuth === true && selectedApp !== undefined) {
startOauth2Request() startOauth2Request()
} }
@@ -452,6 +451,8 @@ const AuthenticationOauth2 = (props) => {
if (orgId !== undefined && orgId !== null && orgId.length > 0) { if (orgId !== undefined && orgId !== null && orgId.length > 0) {
console.log("Adding org_id from user side") console.log("Adding org_id from user side")
state += `%26org_id%3d${orgId}`; state += `%26org_id%3d${orgId}`;
}else{
state += `%26org_id%3d${org_id}`
} }
if (oauth_url !== undefined && oauth_url !== null && oauth_url.length > 0) { if (oauth_url !== undefined && oauth_url !== null && oauth_url.length > 0) {
@@ -466,7 +467,7 @@ const AuthenticationOauth2 = (props) => {
state += `%26refresh_uri%3d${authentication_url}` state += `%26refresh_uri%3d${authentication_url}`
} }
if (workflow.org_id !== undefined && workflow.org_id !== null && workflow.org_id.length > 0) { if (workflow?.org_id !== undefined && workflow?.org_id !== null && workflow?.org_id.length > 0) {
state += `%26org_id%3d${workflow.org_id}` state += `%26org_id%3d${workflow.org_id}`
} }
@@ -835,13 +836,14 @@ const AuthenticationOauth2 = (props) => {
setOauthUrl(data.value); setOauthUrl(data.value);
} }
const defaultValue = data.name === "url" && authenticationType.token_uri !== undefined && authenticationType.token_uri !== null && authenticationType.token_uri.length > 0 && (authenticationType.authorizationUrl === undefined || authenticationType.authorizationUrl === null || authenticationType.authorizationUrl.length === 0) && authenticationType.type === "oauth2-app" ? authenticationType.token_uri : data.value === undefined || data.value === null ? "" : data.value const isNormalOauth = authenticationType.redirect_uri !== undefined && authenticationType.redirect_uri !== null && authenticationType.redirect_uri.length > 0
const defaultValue = !isNormalOauth && data.name === "url" && authenticationType.token_uri !== undefined && authenticationType.token_uri !== null && authenticationType.token_uri.length > 0 && (authenticationType.authorizationUrl === undefined || authenticationType.authorizationUrl === null || authenticationType.authorizationUrl.length === 0) && authenticationType.type === "oauth2-app" ? authenticationType.token_uri : data.value === undefined || data.value === null ? "" : data.value
const fieldname = data.name === "url" && authenticationType.grant_type !== undefined && authenticationType.grant_type !== null && authenticationType.grant_type.length > 0 && authenticationType.type === "oauth2-app" ? "Token URL" : data.name const fieldname = !isNormalOauth && data.name === "url" && authenticationType.grant_type !== undefined && authenticationType.grant_type !== null && authenticationType.grant_type.length > 0 && authenticationType.type === "oauth2-app" ? "Token URL" : data.name
return ( return (
<div key={index} style={{ marginTop: authenticationType.type === "oauth2-app" ? 10 : 0, }}> <div key={index} style={{ marginTop: !isNormalOauth && authenticationType.type === "oauth2-app" ? 10 : 0, }}>
<LockOpenIcon style={{ marginRight: 10 }} /> <LockOpenIcon style={{ marginRight: 10 }} />
<b>{fieldname}</b> <b>{fieldname}</b>
+54 -4
View File
@@ -207,6 +207,53 @@ const ParsedAction = (props) => {
} }
}, [expansionModalOpen]) }, [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
}
var auth = []
var required = []
var optional = []
var keyorder = []
for (let paramkey in selectedActionParameters) {
const param = selectedActionParameters[paramkey]
keyorder.push(param.name)
if (param.configuration) {
auth.push(param)
continue
}
if (param.required) {
required.push(param)
continue
}
optional.push(param)
}
// Check new keyorder
const newparams = auth.concat(required).concat(optional)
var newkeyorder = []
for (let paramkey in newparams) {
newkeyorder.push(newparams[paramkey].name)
}
if (keyorder.join(",") !== newkeyorder.join(",")) {
//toast("Changed order of params")
setSelectedActionParameters(newparams)
selectedAction.parameters = newparams
setSelectedAction(selectedAction)
}
}, [selectedActionParameters])
useEffect(() => { useEffect(() => {
if (selectedActionEnvironment === undefined || selectedActionEnvironment === null || Object.keys(selectedActionEnvironment).length === 0) { if (selectedActionEnvironment === undefined || selectedActionEnvironment === null || Object.keys(selectedActionEnvironment).length === 0) {
@@ -582,8 +629,9 @@ const ParsedAction = (props) => {
} }
let newParameters = selectedAction?.parameters?.map((param) => { let newParameters = selectedAction?.parameters?.map((param) => {
let paramvalue = param.value; let paramvalue = param.value === undefined || param.value === null ? "" : param.value;
let errorVars = []; let errorVars = [];
if(paramvalue.includes("$")){ if(paramvalue.includes("$")){
let actions = workflow.actions?.map((action) => { let actions = workflow.actions?.map((action) => {
return "$"+action.label?.toLowerCase(); return "$"+action.label?.toLowerCase();
@@ -1161,7 +1209,7 @@ const ParsedAction = (props) => {
var helperText = "" var helperText = ""
if (name.includes("url")) { if (name.includes("url")) {
if (value.includes("localhost") || value.includes("127.0.0.1")) { if (value.includes("localhost") || value.includes("127.0.0.1")) {
helperText = "Can't use localhost. Please change to your external IP." helperText = "Can't use localhost in Shuffle. Please change to server's IP."
} }
} }
@@ -1855,7 +1903,9 @@ const ParsedAction = (props) => {
<span> <span>
<Button <Button
color="primary" color="primary"
style={{}} style={{
textTransform: "none",
}}
fullWidth fullWidth
variant="contained" variant="contained"
onClick={() => { onClick={() => {
@@ -2832,7 +2882,7 @@ const ParsedAction = (props) => {
if (selectedAction.parameters === undefined || selectedAction.parameters === null || selectedAction.parameters.length !== selectedActionParameters.length) { if (selectedAction.parameters === undefined || selectedAction.parameters === null || selectedAction.parameters.length !== selectedActionParameters.length) {
//selectedAction.parameters = selectedActionParameters //selectedAction.parameters = selectedActionParameters
console.log("PARAM BUG - length change(?): ", selectedAction) //console.log("PARAM BUG - length change(?): ", selectedAction)
} }
//!selectedAction.auth_not_required && //!selectedAction.auth_not_required &&
+3 -2
View File
@@ -874,10 +874,11 @@ const SearchData = props => {
</List> </List>
</Grid> </Grid>
<Grid style={{ textAlign: "end", width: "100%", textTransform: 'capitalize', }}> <Grid style={{ textAlign: "end", width: "100%", textTransform: 'capitalize', }}>
<Button style={{ textAlign: "center", textTransform: 'capitalize' }} <Link to="/search" style={{ textDecoration: "none", color: "#f85a3e" }}>
onClick={() => { window.location = "/search"; }} > <Button style={{ textAlign: "center", textTransform: 'capitalize' }}>
See More See More
</Button> </Button>
</Link>
</Grid> </Grid>
</Grid> </Grid>
) : null ) : null
+24 -1
View File
@@ -13,6 +13,30 @@ const data = [
return elementname return elementname
}, },
"text-valign": "center", "text-valign": "center",
"text-margin-x": function(element) {
// Attempt at bottom-positioning
// Required text-valign: bottom
// FIXME: Disabled for now.
return "15px"
const name = element.data("label")
console.log("Name: ", name)
if (name === null || name === undefined || name == "" || document=== undefined || document === null) {
return "0px"
}
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d')
context.font = '18px Segoe UI, Tahoma, Geneva, Verdana, sans-serif, sans-serif'
const textWidth = context.measureText(name).width
return textWidth + "px"
//return -1*(textWidth) + "px"
},
"font-family": "Segoe UI, Tahoma, Geneva, Verdana, sans-serif, sans-serif", "font-family": "Segoe UI, Tahoma, Geneva, Verdana, sans-serif, sans-serif",
"font-weight": "lighter", "font-weight": "lighter",
"font-size": "18px", "font-size": "18px",
@@ -23,7 +47,6 @@ const data = [
padding: "10px", padding: "10px",
margin: "5px", margin: "5px",
"border-width": "1px", "border-width": "1px",
"text-margin-x": "10px",
"z-index": 5001, "z-index": 5001,
}, },
}, },
+4 -4
View File
@@ -6223,9 +6223,9 @@ If you're interested, please let me know a time that works for you, or set up a
--name="shuffle-orborus" \\ --name="shuffle-orborus" \\
--pull=always \\ --pull=always \\
--volume "/var/run/docker.sock:/var/run/docker.sock" \\ --volume "/var/run/docker.sock:/var/run/docker.sock" \\
-e AUTH="d85b017c-7f47-4d3a-bb20-9b00731bc397" \\ -e AUTH="${environment.auth}" \\
-e ENVIRONMENT_NAME="swarm testing" \\ -e ENVIRONMENT_NAME="${environment.Name}" \\
-e ORG="9c4e7cd9-cfa4-457b-9ee5-3a9faa6e8c3c" \\ -e ORG="${environment.org_id}" \\
-e SHUFFLE_WORKER_IMAGE="ghcr.io/shuffle/shuffle-worker:nightly" \\ -e SHUFFLE_WORKER_IMAGE="ghcr.io/shuffle/shuffle-worker:nightly" \\
-e SHUFFLE_SWARM_CONFIG=run \\ -e SHUFFLE_SWARM_CONFIG=run \\
-e SHUFFLE_LOGS_DISABLED=true \\ -e SHUFFLE_LOGS_DISABLED=true \\
@@ -6284,7 +6284,7 @@ curTab === 6 ? (
<div style={{ marginTop: 20, marginBottom: 20 }}> <div style={{ marginTop: 20, marginBottom: 20 }}>
<h2 style={{ display: "inline" }}>Locations</h2> <h2 style={{ display: "inline" }}>Locations</h2>
<span style={{ marginLeft: 25 }}> <span style={{ marginLeft: 25 }}>
Decides where to run your workflows and actions. Uses Shuffle's Orborus runner to handle queued jobs. Previously "Environments". Decides where to run your workflows and actions. Uses Shuffle's Orborus runner to handle queued jobs onprem. Previously "Environments".
If you have scale problems, talk to our team: support@shuffler.io.&nbsp; If you have scale problems, talk to our team: support@shuffler.io.&nbsp;
<a <a
+235 -149
View File
@@ -566,7 +566,7 @@ const AngularWorkflow = (defaultprops) => {
const releaseToConnectLabel = "Release to Connect" const releaseToConnectLabel = "Release to Connect"
const integrationApps = [{ const integrationApps = [{
"id": "integration", "id": "integration",
"name": "Integration Framework", "name": "Singul",
"type": "ACTION", "type": "ACTION",
"app_version": "1.0.0", "app_version": "1.0.0",
"loop_versions": ["1.0.0"], "loop_versions": ["1.0.0"],
@@ -737,8 +737,64 @@ const releaseToConnectLabel = "Release to Connect"
} }
} }
if (cy !== undefined && cy !== null) {
// Check if any apps in the workflow has
cy.nodes().forEach((node) => {
const data = node.data()
if (data.app_id === foundapp.id) {
if (data.name === "tmp" && data.parameters !== undefined && data.parameters !== null && data.parameters.length === 1 && data.parameters[0].name === "tmp" && foundapp.actions !== undefined && foundapp.actions !== null && foundapp.actions.length > 0) {
const startIndex = foundapp.actions.findIndex((action) => action.category_label !== undefined && action.category_label !== null && action.category_label.length > 0)
const actionIndex = startIndex < 0 ? 0 : startIndex
node.data("name", foundapp.actions[actionIndex].name)
node.data("large_image", foundapp.large_image)
node.data("parameters", foundapp.actions[actionIndex].parameters)
node.data("finished", true)
node.data("category", foundapp.categories !== null && foundapp.categories !== undefined && foundapp.categories.length > 0 ? foundapp.categories[0] : "")
/*
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,
authentication_id: authId,
finished: false,
template: app.template === true ? true : false,
*/
toast("REPLACING ACTIONS")
}
}
})
//if (action.app_id === same && app.actions.length === 1 && app.actions[0].parameters.length === 1 && app.actions[0].parameters[0].name === "tmp") {
}
// FIXME: Add it to the existing list AND update the selected app // FIXME: Add it to the existing list AND update the selected app
} }
}) })
.catch((error) => { .catch((error) => {
console.log(`Failed side-loading app ${appId}: ${error}`) console.log(`Failed side-loading app ${appId}: ${error}`)
@@ -974,7 +1030,6 @@ const releaseToConnectLabel = "Release to Connect"
if (responseJson.reason !== undefined && responseJson.reason !== undefined && responseJson.reason.length > 0) { if (responseJson.reason !== undefined && responseJson.reason !== undefined && responseJson.reason.length > 0) {
if (!responseJson.reason.includes("404: Not Found") && responseJson.reason.length > 25) { if (!responseJson.reason.includes("404: Not Found") && responseJson.reason.length > 25) {
// Translate <img> into markdown ![]()
const imgRegex = /<img.*?src="(.*?)"/g; const imgRegex = /<img.*?src="(.*?)"/g;
const newdata = responseJson.reason.replace(imgRegex, '![]($1)'); const newdata = responseJson.reason.replace(imgRegex, '![]($1)');
@@ -993,7 +1048,6 @@ const releaseToConnectLabel = "Release to Connect"
useEffect(() => { useEffect(() => {
if (authenticationModalOpen === true && selectedAction.app_name !== undefined) { if (authenticationModalOpen === true && selectedAction.app_name !== undefined) {
console.log(`Should get app docs for: ${selectedAction.app_name}`)
//console.log(selectedAction) //console.log(selectedAction)
//console.log("APP: ", selectedApp) //console.log("APP: ", selectedApp)
@@ -2607,7 +2661,7 @@ const releaseToConnectLabel = "Release to Connect"
return return
} }
console.log("Apps loaded. JSON decoding next") //console.log("Apps loaded. JSON decoding next")
return response.json() return response.json()
}) })
@@ -3816,7 +3870,6 @@ const releaseToConnectLabel = "Release to Connect"
left: 0, left: 0,
selected: "", selected: "",
}); });
//console.timeEnd("UNSELECT");
}) })
sendStreamRequest({ sendStreamRequest({
@@ -4020,6 +4073,7 @@ const releaseToConnectLabel = "Release to Connect"
nodedata.app_name !== "Testing" && nodedata.app_name !== "Testing" &&
nodedata.app_name !== "Shuffle Workflow" && nodedata.app_name !== "Shuffle Workflow" &&
nodedata.app_name !== "Integration Framework" && nodedata.app_name !== "Integration Framework" &&
nodedata.app_name !== "Singul" &&
nodedata.app_name !== "User Input") || nodedata.app_name !== "User Input") ||
nodedata.isStartNode) nodedata.isStartNode)
) { ) {
@@ -4280,13 +4334,30 @@ const releaseToConnectLabel = "Release to Connect"
} }
} }
} }
/*
// FIXME: This is the start of a highlighter for the node
// to better match it up with other elements
// 1. Get current node's position in X/Y on the screen
// 2. Draw a red line on the X and Y axis for positioning
// Draw a red div line in the HTML
const position = event.target.position()
const redline = document.getElementById("redline")
if (redline !== null && redline !== undefined) {
redline.style.display = "block"
redline.style.position = "absolute"
redline.style.left = position.x + "px"
redline.style.top = position.y + "px"
redline.style.height = "10000px"
redline.style.width = 1
console.log("REDLINE!")
}
*/
} }
if ( if (originalLocation.x === 0 && originalLocation.y === 0 && nodedata.position !== undefined) {
originalLocation.x === 0 &&
originalLocation.y === 0 &&
nodedata.position !== undefined
) {
originalLocation.x = nodedata.position.x; originalLocation.x = nodedata.position.x;
originalLocation.y = nodedata.position.y; originalLocation.y = nodedata.position.y;
} }
@@ -5353,24 +5424,48 @@ const releaseToConnectLabel = "Release to Connect"
} }
} }
//curaction["authentication"] = [] // Fix authentication fields that may be missing in the UI
//curaction["authentication_id"] = "" if (curapp.authentication.required && !curapp?.authentication?.type?.includes("oauth")) {
// Fix parameters that are... Not ideal if (curapp.authentication.parameters !== undefined && curapp.authentication.parameters !== null) {
//var paramnames = [] var actionChanged = false
//var newparams = [] for (let paramKey in curapp.authentication.parameters) {
//for (let paramKey in curaction.parameters) { var param = curapp.authentication.parameters[paramKey]
// console.log("Name: ", curaction.parameters[paramKey].name)
// if (paramnames.includes(curaction.parameters[paramKey].name)) {
// continue
// }
// paramnames.push(curaction.parameters[paramKey].name) if (curaction.parameters === undefined || curaction.parameters === null) {
// newparams.push(curaction.parameters[paramKey]) curaction.parameters = []
//} }
//curaction.parameters = newparams var found = false
for (let actionParamKey in curaction.parameters) {
if (curaction.parameters[actionParamKey].name === param.name) {
found = true
break
}
}
setSelectedApp(curapp); if (!found) {
param.configuration = true
curaction.parameters.push(param)
actionChanged = true
}
}
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); setSelectedAction(curaction);
cy.removeListener("drag"); cy.removeListener("drag");
@@ -5537,7 +5632,7 @@ const releaseToConnectLabel = "Release to Connect"
setSelectedTriggerIndex(trigger_index) setSelectedTriggerIndex(trigger_index)
setSelectedTrigger(data) setSelectedTrigger(data)
setSelectedActionEnvironment(data.env) //setSelectedActionEnvironment(data.env)
}, 25) }, 25)
} else if (data.type === "COMMENT") { } else if (data.type === "COMMENT") {
setSelectedComment(data); setSelectedComment(data);
@@ -5889,7 +5984,7 @@ const releaseToConnectLabel = "Release to Connect"
const edge = event.target.data(); const edge = event.target.data();
if (edge.source === undefined && edge.target === undefined) { if (edge.source === undefined && edge.target === undefined) {
console.log("Edge added without source or target") //console.log("Edge added without source or target")
return return
} }
@@ -6020,7 +6115,7 @@ const releaseToConnectLabel = "Release to Connect"
found = true found = true
break break
} else { } else {
console.log("Old branch didn't exist afterall. Remove.") //console.log("Old branch didn't exist afterall. Remove.")
} }
} }
@@ -6115,28 +6210,13 @@ const releaseToConnectLabel = "Release to Connect"
const node = event.target; const node = event.target;
const nodedata = event.target.data(); const nodedata = event.target.data();
//if (Object.keys(nodedata).length === 1) {
// console.log("Check if another node actually exists before adding")
//}
if (nodedata.finished === false || (nodedata.id !== undefined && nodedata.is_valid === undefined) if (nodedata.finished === false || (nodedata.id !== undefined && nodedata.is_valid === undefined)
) { ) {
//if (nodedata.app_id === undefined) {
//console.log("Returning because node is not valid: ", nodedata)
return; return;
} }
// Check for recommendations when a new action is added
// if (isLoaded === true && firstrequest === false) {
// fetchRecommendations(workflow)
// }
// DONT MOVE THIS LINE RIGHT HERE v // DONT MOVE THIS LINE RIGHT HERE v
setLastSaved(false) setLastSaved(false)
// Dont move the line above. May break stuff.
if (node.isNode() && cy.nodes().size() === 1) { if (node.isNode() && cy.nodes().size() === 1) {
workflow.start = node.data("id"); workflow.start = node.data("id");
nodedata.isStartNode = true; nodedata.isStartNode = true;
@@ -6171,13 +6251,6 @@ const releaseToConnectLabel = "Release to Connect"
if (nodedata.type === "ACTION") { if (nodedata.type === "ACTION") {
// Should get recommendations to load in for all nodesma // Should get recommendations to load in for all nodesma
/*
var curaction = workflow.actions.find((a) => a.id === nodedata.id);
if (curaction === null || curaction === undefined) {
toast("Node not found. Please remake it.")
event.target.remove();
}
*/
if (workflow.actions.length === 1 && workflow.actions[0].id === workflow.start) { if (workflow.actions.length === 1 && workflow.actions[0].id === workflow.start) {
const newEdgeUuid = uuidv4(); const newEdgeUuid = uuidv4();
const newcybranch = { const newcybranch = {
@@ -6216,11 +6289,7 @@ const releaseToConnectLabel = "Release to Connect"
} }
if ( if (nodedata.parameters !== undefined && nodedata.parameters !== null && !nodedata.label.endsWith("_copy")) {
nodedata.parameters !== undefined &&
nodedata.parameters !== null &&
!nodedata.label.endsWith("_copy")
) {
var newparameters = []; var newparameters = [];
for (let [subkey,subkeyval] in Object.entries(nodedata.parameters)) { for (let [subkey,subkeyval] in Object.entries(nodedata.parameters)) {
@@ -6679,42 +6748,58 @@ const releaseToConnectLabel = "Release to Connect"
return response.json(); return response.json();
}) })
.then((responseJson) => { .then((responseJson) => {
var found = false; var found = false
var showEnvCnt = 0; var showEnvCnt = 0
for (let jsonkey in responseJson) { for (let jsonkey in responseJson) {
if (responseJson[jsonkey].default && !found) { if (responseJson[jsonkey].default && !found) {
setDefaultEnvironmentIndex(jsonkey); setDefaultEnvironmentIndex(jsonkey)
found = true; found = true
} }
if (responseJson[jsonkey].archived === false) { if (responseJson[jsonkey].archived === false) {
showEnvCnt += 1; showEnvCnt += 1
} }
} }
if (showEnvCnt > 1) { if (showEnvCnt > 1) {
setShowEnvironment(true); setShowEnvironment(true)
} }
if (!found) { if (!found) {
for (let jsonkey in responseJson) { for (let jsonkey in responseJson) {
if (!responseJson[jsonkey].archived) { if (!responseJson[jsonkey].archived) {
setDefaultEnvironmentIndex(jsonkey); setDefaultEnvironmentIndex(jsonkey)
break; break;
} }
} }
} }
// FIXME: Don't allow multiple in cloud yet. Cloud -> Onprem isn't stable.
if (isCloud) { if (isCloud) {
if (responseJson !== undefined && responseJson !== null && responseJson.length > 0) { if (responseJson !== undefined && responseJson !== null && responseJson.length > 0) {
setEnvironments(responseJson); setEnvironments(responseJson)
} else { } else {
setEnvironments([{ Name: "Cloud", Type: "cloud" }]); setEnvironments([{ Name: "Cloud", Type: "cloud" }])
} }
} else { } else {
setEnvironments(responseJson); 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)
*/
}) })
.catch((error) => { .catch((error) => {
//toast(error.toString()); //toast(error.toString());
@@ -7446,7 +7531,6 @@ const releaseToConnectLabel = "Release to Connect"
console.log("NODE UNFINISHED (hover in): ", nodedata) console.log("NODE UNFINISHED (hover in): ", 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()
if (incomingEdges !== undefined && incomingEdges !== null) { if (incomingEdges !== undefined && incomingEdges !== null) {
for (var i = 0; i < incomingEdges.length; i++) { for (var i = 0; i < incomingEdges.length; i++) {
@@ -7465,7 +7549,6 @@ const releaseToConnectLabel = "Release to Connect"
} }
return return
*/
} }
@@ -7603,28 +7686,6 @@ const releaseToConnectLabel = "Release to Connect"
if (nodedata.type !== "COMMENT") { if (nodedata.type !== "COMMENT") {
parsedStyle.color = "white"; parsedStyle.color = "white";
//if (!event.target.data("isButton") && !event.target.data("buttonId")) {
// const px = event.target.position("x") - 0;
// const py = event.target.position("y") - 50;
// const circleId = (newNodeId = uuidv4());
// console.log("Got px, py: ", px, py)
//
// cy.add({
// group: "nodes",
// data: {
// weight: 30,
// id: circleId,
// isButton: true,
// attachedTo: event.target.data("id"),
// buttonType: "edgehandler",
// is_valid: true,
// },
// position: { x: px, y: py },
// locked: true,
// })
//}
} }
if (event.target !== undefined && event.target !== null) { if (event.target !== undefined && event.target !== null) {
@@ -7884,7 +7945,7 @@ const releaseToConnectLabel = "Release to Connect"
} else { } else {
action.iconBackground = iconInfo.iconBackgroundColor; action.iconBackground = iconInfo.iconBackgroundColor;
} }
} else if (action.app_name === "Integration Framework") { } else if (action.app_name === "Integration Framework" || action.app_name === "Singul") {
const iconInfo = GetIconInfo(action) const iconInfo = GetIconInfo(action)
if (iconInfo !== undefined && iconInfo !== null) { if (iconInfo !== undefined && iconInfo !== null) {
action.fillGradient = iconInfo.fillGradient action.fillGradient = iconInfo.fillGradient
@@ -7921,13 +7982,17 @@ const releaseToConnectLabel = "Release to Connect"
}) })
// What are these again? Where are they used? // 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) => { const decoratorNodes = inputworkflow.actions.map((action) => {
if (!action.isStartNode) { if (!action.isStartNode) {
if (action.app_name === "Testing") { if (action.app_name === "Testing") {
return null return null
} else if (action.app_name === "Shuffle Tools") { } else if (action.app_name === "Shuffle Tools") {
return null return null
} else if (action.app_name === "Integration Framework") { } else if (action.app_name === "Integration Framework" || action.app_name === "Singul") {
return null return null
} }
} }
@@ -7964,6 +8029,7 @@ const releaseToConnectLabel = "Release to Connect"
} }
return decoratorNode return decoratorNode
}) })
*/
const foundtriggers = inputworkflow.triggers.map((trigger) => { const foundtriggers = inputworkflow.triggers.map((trigger) => {
@@ -9509,8 +9575,22 @@ const releaseToConnectLabel = "Release to Connect"
const handleAppDrag = (e, app) => { const handleAppDrag = (e, app) => {
const cycontainer = cy.container(); const cycontainer = cy.container();
console.log("APPDRAG!") // Handling drag of public apps
if (app.objectID !== undefined && app.objectID !== null && app.objectID.length > 0) {
// FIXME: This is still buggy for now. Not allowed
return
loadAppConfig(app.objectID, undefined)
// Some arbitrary check
app.id = app.objectID
app.actions = [{
"name": "tmp",
"parameters": [{
"name": "tmp",
}]
}]
}
if (app.type === "TRIGGER") { if (app.type === "TRIGGER") {
handleTriggerDrag(e, app) handleTriggerDrag(e, app)
@@ -9520,13 +9600,8 @@ const releaseToConnectLabel = "Release to Connect"
//console.log("e: ", e) //console.log("e: ", e)
//console.log("Offset: ", cycontainer) //console.log("Offset: ", cycontainer)
// Chrome lol // HTML -> Canvas overlap check
if ( if (e.pageX > cycontainer.offsetLeft && e.pageX < cycontainer.offsetLeft + cycontainer.offsetWidth && e.pageY > cycontainer.offsetTop && e.pageY < cycontainer.offsetTop + cycontainer.offsetHeight) {
e.pageX > cycontainer.offsetLeft &&
e.pageX < cycontainer.offsetLeft + cycontainer.offsetWidth &&
e.pageY > cycontainer.offsetTop &&
e.pageY < cycontainer.offsetTop + cycontainer.offsetHeight
) {
if (newNodeId.length > 0) { if (newNodeId.length > 0) {
var currentnode = cy.getElementById(newNodeId); var currentnode = cy.getElementById(newNodeId);
if ( if (
@@ -9902,8 +9977,19 @@ const releaseToConnectLabel = "Release to Connect"
> >
<Grid item> <Grid item>
<img <img
alt={newAppname} id={`image_${props?.index}`}
src={image} src={image}
onError={(e) => {
if (props.index !== undefined && props.index !== null) {
// Replace the image with the default image
const foundImage = document.getElementById(`image_${props.index}`)
if (foundImage !== undefined && foundImage !== null) {
foundImage.src = theme.palette.defaultImage
app.large_image = theme.palette.defaultImage
}
}
}}
style={{ style={{
pointerEvents: "none", pointerEvents: "none",
userDrag: "none", userDrag: "none",
@@ -10063,7 +10149,7 @@ const releaseToConnectLabel = "Release to Connect"
const clickedApp = (hit) => { const clickedApp = (hit) => {
toast.success(`Activating App. Please wait a moment.`) toast.success(`Activating App. Please wait a moment, and it will show up highlighted in your apps.`)
const queryID = hit.__queryID const queryID = hit.__queryID
@@ -10174,6 +10260,7 @@ const releaseToConnectLabel = "Release to Connect"
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
handleAppDrag(e, hit)
if (!appdragged) { if (!appdragged) {
clickedApp(hit) clickedApp(hit)
} }
@@ -10297,14 +10384,14 @@ const releaseToConnectLabel = "Release to Connect"
<span> <span>
{/*<Zoom key={index} in={true} style={{ transitionDelay: `${delay}ms` }}>*/} {/*<Zoom key={index} in={true} style={{ transitionDelay: `${delay}ms` }}>*/}
<div> <div>
<ParsedAppPaper key={index} app={app} /> <ParsedAppPaper key={index} index={index} app={app} />
</div> </div>
{/*</Zoom>*/} {/*</Zoom>*/}
</span> </span>
: :
<div key={index}> <div key={index}>
{extraMessage} {extraMessage}
<ParsedAppPaper key={index} app={app} /> <ParsedAppPaper key={index} index={index} app={app} />
</div> </div>
) )
})} })}
@@ -12728,7 +12815,7 @@ const releaseToConnectLabel = "Release to Connect"
type: "action", type: "action",
id: item.id, id: item.id,
name: item.label, name: item.label,
autocomplete: `${item.label.split(" ").join("_")}`, autocomplete: `${item?.label?.split(" ")?.join("_")}`,
example: exampledata, example: exampledata,
} }
actionlist.push(actionvalue); actionlist.push(actionvalue);
@@ -14843,7 +14930,7 @@ const releaseToConnectLabel = "Release to Connect"
<div style={{ flex: "10" }}> <div style={{ flex: "10" }}>
<b>Information</b> <b>Information</b>
<Typography variant="body2" color="textSecondary"> <Typography variant="body2" color="textSecondary">
The information you want to show the user. Supports variables. The information you want to show the user. Supports variables. Supports Markdown & HTML.
</Typography> </Typography>
</div> </div>
</div> </div>
@@ -15114,9 +15201,8 @@ const releaseToConnectLabel = "Release to Connect"
/> />
) : null} ) : null}
</div>
<div style={{marginTop: 0, }} /> <div style={{marginTop: 50, }} />
<b>Required Input-Questions</b> <b>Required Input-Questions</b>
{workflow.input_questions !== undefined && workflow.input_questions !== null && workflow.input_questions.length > 0 ? {workflow.input_questions !== undefined && workflow.input_questions !== null && workflow.input_questions.length > 0 ?
<div> <div>
@@ -15174,6 +15260,7 @@ const releaseToConnectLabel = "Release to Connect"
<Typography variant="body2">No Input-Questions found. Click to add them!</Typography> <Typography variant="body2">No Input-Questions found. Click to add them!</Typography>
</div> </div>
} }
</div>
</div> </div>
const defaultEnvironment = environments.find( const defaultEnvironment = environments.find(
@@ -15876,6 +15963,13 @@ const releaseToConnectLabel = "Release to Connect"
getFiles(e.target.value) getFiles(e.target.value)
listOrgCache(e.target.value) listOrgCache(e.target.value)
// 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
// Should look through childorg workflow
setTimeout(() => {
if (e.target.value === originalWorkflow.org_id) { if (e.target.value === originalWorkflow.org_id) {
console.log("Original org selected. No change.") console.log("Original org selected. No change.")
@@ -15886,8 +15980,6 @@ const releaseToConnectLabel = "Release to Connect"
//toast("Loading correct info for suborg") //toast("Loading correct info for suborg")
} }
// Should look through childorg workflow
console.log("Original: ", originalWorkflow) console.log("Original: ", originalWorkflow)
if (originalWorkflow.childorg_workflow_ids === undefined || originalWorkflow.childorg_workflow_ids === null || originalWorkflow.childorg_workflow_ids.length === 0) { if (originalWorkflow.childorg_workflow_ids === undefined || originalWorkflow.childorg_workflow_ids === null || originalWorkflow.childorg_workflow_ids.length === 0) {
console.log("In childorg doesn't exist. Suborgworkflows: ", suborgWorkflows) console.log("In childorg doesn't exist. Suborgworkflows: ", suborgWorkflows)
@@ -15941,6 +16033,7 @@ const releaseToConnectLabel = "Release to Connect"
//saveWorkflow(originalWorkflow, undefined, undefined, e.target.value) //saveWorkflow(originalWorkflow, undefined, undefined, e.target.value)
} }
} }
}, 500)
}) })
}} }}
label="Suborg Distribution" label="Suborg Distribution"
@@ -16048,7 +16141,7 @@ const releaseToConnectLabel = "Release to Connect"
})} })}
</div> </div>
{showEnvironment === true && environments.length > 1 ? {showEnvironment === true && environments.length > 1 && selectedActionEnvironment !== undefined && selectedActionEnvironment !== null && selectedActionEnvironment.Name !== undefined && selectedActionEnvironment.Name !== null ?
<FormControl fullWidth style={{marginTop: 15, marginleft: 10, pointerEvents: "auto", }}> <FormControl fullWidth style={{marginTop: 15, marginleft: 10, pointerEvents: "auto", }}>
<InputLabel <InputLabel
@@ -16069,10 +16162,11 @@ const releaseToConnectLabel = "Release to Connect"
}, },
}} }}
onChange={(e) => { onChange={(e) => {
setLastSaved(false)
const env = environments.find((a) => a.Name === e.target.value); const env = environments.find((a) => a.Name === e.target.value);
setSelectedActionEnvironment(env); setSelectedActionEnvironment(env)
selectedAction.environment = env.Name; selectedAction.environment = env.Name
setSelectedAction(selectedAction); setSelectedAction(selectedAction)
for (let actionkey in workflow.actions) { for (let actionkey in workflow.actions) {
workflow.actions[actionkey].environment = env.Name workflow.actions[actionkey].environment = env.Name
@@ -16110,7 +16204,7 @@ const releaseToConnectLabel = "Release to Connect"
{data.Name === "cloud" || data.Name === "Cloud" ? null : !isRunning ? {data.Name === "cloud" || data.Name === "Cloud" ? null : !isRunning ?
<a href={`/admin?tab=locations&env=${data.Name}`} target="_blank" style={{textDecoration: "none",}}> <a href={`/admin?tab=locations&env=${data.Name}`} target="_blank" style={{textDecoration: "none",}}>
<Tooltip title={"Click to configure the environment"} placement="top"> <Tooltip title={"Click to configure this location"} placement="top">
<Chip <Chip
style={{marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer", backgroundColor: red, }} style={{marginLeft: 0, padding: 0, marginRight: 10, cursor: "pointer", backgroundColor: red, }}
label={"Stopped"} label={"Stopped"}
@@ -19684,7 +19778,6 @@ const releaseToConnectLabel = "Release to Connect"
maxHeight: 550, maxHeight: 550,
overflowY: "auto", overflowY: "auto",
overflowX: "hidden", overflowX: "hidden",
// zIndex: 10012,
border: theme.palette.defaultBorder, border: theme.palette.defaultBorder,
}, },
}} }}
@@ -19866,7 +19959,7 @@ const releaseToConnectLabel = "Release to Connect"
</span> </span>
<div style={{ marginBottom: 40, }}> <div style={{ marginBottom: 40, }}>
<div style={{ display: "flex", marginBottom: 15, position: "sticky", top: -31, zIndex: 10000, backgroundColor: "rgba(56,56,56, 1)", }}> <div style={{ display: "flex", marginBottom: 15, position: "sticky", top: -31, zIndex: 10000, }}>
{curapp === null ? null : ( {curapp === null ? null : (
<img <img
alt={selectedResult.action.app_name} alt={selectedResult.action.app_name}
@@ -20631,7 +20724,7 @@ const releaseToConnectLabel = "Release to Connect"
toast( toast(
"Field " + "Field " +
selectedApp.authentication.parameters[paramkey].name + selectedApp.authentication.parameters[paramkey].name +
" can't be empty" " can't be empty. If you want it empty, put space."
); );
return; return;
} }
@@ -20660,7 +20753,6 @@ const releaseToConnectLabel = "Release to Connect"
var newAuthOption = JSON.parse(JSON.stringify(authenticationOption)); var newAuthOption = JSON.parse(JSON.stringify(authenticationOption));
var newFields = []; var newFields = [];
console.log("Fields: ", newAuthOption.fields)
for (let authkey in newAuthOption.fields) { for (let authkey in newAuthOption.fields) {
const value = newAuthOption.fields[authkey]; const value = newAuthOption.fields[authkey];
newFields.push({ newFields.push({
@@ -20673,7 +20765,7 @@ const releaseToConnectLabel = "Release to Connect"
setNewAppAuth(newAuthOption) setNewAppAuth(newAuthOption)
if (configureWorkflowModalOpen) { if (configureWorkflowModalOpen) {
setSelectedAction({}) //setSelectedAction({})
} }
setUpdate(authenticationOption.id) setUpdate(authenticationOption.id)
@@ -20750,8 +20842,14 @@ const releaseToConnectLabel = "Release to Connect"
return ( return (
<div key={index} style={{ marginTop: 10 }}> <div key={index} style={{ marginTop: 10 }}>
<LockOpenIcon style={{ marginRight: 10 }} /> <div style={{display: "flex", }}>
<b>{data.name}</b> <LockOpenIcon style={{
marginRight: 10
}} />
<Typography variant="body1">
{data?.name?.endsWith("_basic") ? data?.name?.replace("_basic", "") : data?.name}
</Typography>
</div>
{data.schema !== undefined && {data.schema !== undefined &&
data.schema !== null && data.schema !== null &&
@@ -20815,7 +20913,7 @@ const releaseToConnectLabel = "Release to Connect"
} }
color="primary" color="primary"
defaultValue={ defaultValue={
data.value !== undefined && data.value !== null data.value !== undefined && data.value !== null && !data.value.includes("Secret. Replace")
? data.value ? data.value
: "" : ""
} }
@@ -20824,6 +20922,7 @@ const releaseToConnectLabel = "Release to Connect"
authenticationOption.fields[data.name] = authenticationOption.fields[data.name] =
event.target.value; event.target.value;
}} }}
id={`${data.name}_auth`}
/> />
)} )}
</div> </div>
@@ -20832,19 +20931,11 @@ const releaseToConnectLabel = "Release to Connect"
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button <Button
style={{}} style={{width: 150, margin: "auto", }}
onClick={() => { disabled={false}
setAuthenticationModalOpen(false);
}}
color="secondary"
>
Cancel
</Button>
<Button
style={{}}
variant="outlined" variant="outlined"
onClick={() => { onClick={() => {
setAuthenticationOptions(authenticationOption); setAuthenticationOptions(authenticationOption)
handleSubmitCheck() handleSubmitCheck()
}} }}
color="primary" color="primary"
@@ -20856,7 +20947,8 @@ const releaseToConnectLabel = "Release to Connect"
); );
}; };
const configureWorkflowModal = // FIXME: Re-enable?
const configureWorkflowModal = true ? null :
configureWorkflowModalOpen && apps.length !== 0 ? ( configureWorkflowModalOpen && apps.length !== 0 ? (
<Dialog <Dialog
open={configureWorkflowModalOpen} open={configureWorkflowModalOpen}
@@ -20919,10 +21011,6 @@ const releaseToConnectLabel = "Release to Connect"
style={{ pointerEvents: "none" }} style={{ pointerEvents: "none" }}
open={authenticationModalOpen} open={authenticationModalOpen}
onClose={() => { onClose={() => {
//if (configureWorkflowModalOpen) {
// setSelectedAction({});
//}
//
setSelectedMeta(undefined) setSelectedMeta(undefined)
}} }}
PaperProps={{ PaperProps={{
@@ -21031,7 +21119,7 @@ const releaseToConnectLabel = "Release to Connect"
onClick={() => { onClick={() => {
setAuthenticationModalOpen(false); setAuthenticationModalOpen(false);
if (configureWorkflowModalOpen) { if (configureWorkflowModalOpen) {
setSelectedAction({}); //setSelectedAction({});
} }
}} }}
> >
@@ -21360,15 +21448,6 @@ const releaseToConnectLabel = "Release to Connect"
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button
style={{ borderRadius: "0px" }}
onClick={() => {
setTenzirConfigModalOpen(false);
}}
color="secondary"
>
Cancel
</Button>
<Button <Button
style={{ borderRadius: "0px" }} style={{ borderRadius: "0px" }}
variant="contained" variant="contained"
@@ -22050,6 +22129,13 @@ const releaseToConnectLabel = "Release to Connect"
</div> </div>
: null*/} : null*/}
<div
id="redline"
style={{
display: "none",
}}
/>
{showVideo !== undefined && showVideo.length > 0 ? {showVideo !== undefined && showVideo.length > 0 ?
<div style={{ borderRadius: theme.palette?.borderRadius, zIndex: 12501, position: "fixed", left: 40, bottom: 150, width: 300, }}> <div style={{ borderRadius: theme.palette?.borderRadius, zIndex: 12501, position: "fixed", left: 40, bottom: 150, width: 300, }}>
<IconButton <IconButton
+103 -22
View File
@@ -75,6 +75,7 @@ const RunWorkflow = (defaultprops) => {
const [realtimeMarkdown, setRealtimeMarkdown] = React.useState("") const [realtimeMarkdown, setRealtimeMarkdown] = React.useState("")
const [forms, setForms] = React.useState([]) const [forms, setForms] = React.useState([])
const [boxWidth, setBoxWidth] = React.useState(500) const [boxWidth, setBoxWidth] = React.useState(500)
const [inputQuestions, setInputQuestions] = React.useState([])
const IframeWrapper = (props) => { const IframeWrapper = (props) => {
var propsCopy = JSON.parse(JSON.stringify(props)) var propsCopy = JSON.parse(JSON.stringify(props))
@@ -141,6 +142,18 @@ const RunWorkflow = (defaultprops) => {
return true return true
} }
// Check if it's an object or not
if (typeof executionArgument === "string") {
// Make it an object
try {
executionArgument = JSON.parse(executionArgument)
} catch (e) {
console.log("Error parsing execution argument: ", e)
executionArgument = {}
}
}
console.log("EXEC: ", executionArgument)
for (var key in executionArgument) { for (var key in executionArgument) {
if (executionArgument[key] === undefined || executionArgument[key] === null || executionArgument[key] === "") { if (executionArgument[key] === undefined || executionArgument[key] === null || executionArgument[key] === "") {
return false return false
@@ -262,9 +275,12 @@ const RunWorkflow = (defaultprops) => {
return ( return (
<div style={{marginTop: executionMargin, }}> <div style={{marginTop: executionMargin, }}>
{workflowQuestion !== "" ? null :
<Divider style={{marginTop: 20, marginBottom: 20, }}/> <Divider style={{marginTop: 20, marginBottom: 20, }}/>
}
{validate.valid === false ? {workflowQuestion !== "" ? null :
validate.valid === false ?
<div style={{marginTop: 20, }}> <div style={{marginTop: 20, }}>
<Divider /> <Divider />
<Markdown <Markdown
@@ -533,6 +549,12 @@ const RunWorkflow = (defaultprops) => {
}) })
} }
const searchParams = new URLSearchParams(window.location.search)
const answer = searchParams.get("answer")
const execution_id = searchParams.get("reference_execution")
const authorization = searchParams.get("authorization")
const sourceNode = searchParams.get("source_node")
const getWorkflow = (workflow_id, selectedNode) => { const getWorkflow = (workflow_id, selectedNode) => {
setRealtimeMarkdown("") setRealtimeMarkdown("")
@@ -588,6 +610,56 @@ const RunWorkflow = (defaultprops) => {
} }
} }
// Override with just relevant fields
if (sourceNode !== undefined && sourceNode !== null && sourceNode.length > 0) {
for (var triggerkey in responseJson.triggers) {
const trig = responseJson.triggers[triggerkey]
if (trig.id !== sourceNode) {
continue
}
console.log("TRIG: ", trig)
if (trig.parameters === undefined || trig.parameters === null) {
trig.parameters = []
}
for (var paramkey in trig.parameters) {
const param = trig.parameters[paramkey]
if (param.name !== "input_questions") {
continue
}
// Parse as json
var keepfields = []
try {
const parsed = JSON.parse(param.value)
// Find this in the workflow.input_questions
for (var questionkey in responseJson.input_questions) {
var question = JSON.parse(JSON.stringify(responseJson.input_questions[questionkey]))
question.value = question.value.split(";")[0]
if (parsed.includes(question.name)) {
keepfields.push(question.value)
}
}
//newexec = {}
} catch (e) {
console.log("Error parsing input questions: ", e)
}
// Remapping it to exec
if (keepfields.length > 0) {
newexec = {}
for (var key in keepfields) {
newexec[keepfields[key]] = ""
}
}
}
}
}
setExecutionArgument(newexec) setExecutionArgument(newexec)
} }
@@ -624,7 +696,8 @@ const RunWorkflow = (defaultprops) => {
} }
} }
responseJson.input_questions = relevantquestions setInputQuestions(relevantquestions)
//responseJson.input_questions = relevantquestions
} }
} }
} }
@@ -899,11 +972,6 @@ const RunWorkflow = (defaultprops) => {
}); });
}; };
const searchParams = new URLSearchParams(window.location.search)
const answer = searchParams.get("answer")
const execution_id = searchParams.get("reference_execution")
const authorization = searchParams.get("authorization")
const sourceNode = searchParams.get("source_node")
useEffect(() => { useEffect(() => {
if (!isLoaded) { if (!isLoaded) {
@@ -963,9 +1031,14 @@ const RunWorkflow = (defaultprops) => {
} }
if (result.status !== "WAITING") { if (result.status !== "WAITING") {
if (parsedresult.information !== undefined && parsedresult.information !== null && parsedresult.information.length > 0) {
setWorkflowQuestion(parsedresult.information)
}
if (parsedresult.click_info !== undefined && parsedresult.click_info !== null) { if (parsedresult.click_info !== undefined && parsedresult.click_info !== null) {
if (parsedresult.click_info.user !== undefined && parsedresult.click_info.user !== null && parsedresult.click_info.user.length > 0) { if (parsedresult.click_info.user !== undefined && parsedresult.click_info.user !== null && parsedresult.click_info.user.length > 0) {
setMessage("Already answered by " + parsedresult.click_info.user) setMessage("Already answered by " + parsedresult.click_info.user)
} }
} else { } else {
setMessage("Answered.") setMessage("Answered.")
@@ -981,8 +1054,12 @@ const RunWorkflow = (defaultprops) => {
const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)" const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)"
const buttonStyle = {borderRadius: 25, height: 50, fontSize: 18, backgroundImage: handleValidateForm(executionArgument) || executionLoading ? buttonBackground : "grey", color: "white"} const buttonStyle = {borderRadius: 25, height: 50, fontSize: 18, backgroundImage: handleValidateForm(executionArgument) || executionLoading ? buttonBackground : "grey", color: "white"}
//const disabledButtons = message.length > 0 || executionData.status === "FINISHED" || executionData.status === "ABORTED" // Check if all fields are filled in?
const disabledButtons = executionLoading || executionRunning var disabledButtons = executionLoading || executionRunning || message.length > 0
if (disabledButtons === false && workflow.input_questions !== undefined && workflow.input_questions !== null && workflow.input_questions.length > 0) {
// Check field values
//disabledButtons = handleValidateForm(executionArgument)
}
const organization = selectedOrganization !== undefined && selectedOrganization !== null ? selectedOrganization.name : "Unknown" const organization = selectedOrganization !== undefined && selectedOrganization !== null ? selectedOrganization.name : "Unknown"
const contact = selectedOrganization !== undefined && selectedOrganization !== null && selectedOrganization.org !== undefined && selectedOrganization.org !== null? selectedOrganization.org : "support@shuffler.io" const contact = selectedOrganization !== undefined && selectedOrganization !== null && selectedOrganization.org !== undefined && selectedOrganization.org !== null? selectedOrganization.org : "support@shuffler.io"
@@ -1073,7 +1150,7 @@ const RunWorkflow = (defaultprops) => {
</div> </div>
: :
<div> <div>
{workflow.form_control.input_markdown !== undefined && workflow.form_control.input_markdown !== null && workflow.form_control.input_markdown.length > 0 ? {workflowQuestion !== "" || (workflow.form_control.input_markdown !== undefined && workflow.form_control.input_markdown !== null && workflow.form_control.input_markdown.length > 0) ?
<div style={{marginBottom: 20, }}> <div style={{marginBottom: 20, }}>
<Markdown <Markdown
components={{ components={{
@@ -1089,13 +1166,13 @@ const RunWorkflow = (defaultprops) => {
}} }}
rehypePlugins={[rehypeRaw]} rehypePlugins={[rehypeRaw]}
> >
{realtimeMarkdown !== undefined && realtimeMarkdown !== null && realtimeMarkdown.length > 0 ? realtimeMarkdown : workflow.form_control.input_markdown} {workflowQuestion !== "" ? workflowQuestion : realtimeMarkdown !== undefined && realtimeMarkdown !== null && realtimeMarkdown.length > 0 ? realtimeMarkdown : workflow.form_control.input_markdown}
</Markdown> </Markdown>
</div> </div>
: null} : null}
<form onSubmit={(e) => {onSubmit(e)}} style={{margin: "25px 0px 15px 0px",}}> <form onSubmit={(e) => {onSubmit(e)}} style={{margin: "25px 0px 15px 0px",}}>
{workflow.form_control.input_markdown !== undefined && workflow.form_control.input_markdown !== null && workflow.form_control.input_markdown.length > 0 ? null : {workflowQuestion !== "" || (workflow.form_control.input_markdown !== undefined && workflow.form_control.input_markdown !== null && workflow.form_control.input_markdown.length > 0) ? null :
<div> <div>
<img <img
alt={workflow.name} alt={workflow.name}
@@ -1146,7 +1223,7 @@ const RunWorkflow = (defaultprops) => {
{workflow.input_questions !== undefined && workflow.input_questions !== null && workflow.input_questions.length > 0 ? {workflow.input_questions !== undefined && workflow.input_questions !== null && workflow.input_questions.length > 0 ?
<div style={{marginBottom: 5, }}> <div style={{marginBottom: 5, }}>
{workflow.input_questions.map((question, index) => { {inputQuestions.map((question, index) => {
// Multiple choice checks for semicolon-splits // Multiple choice checks for semicolon-splits
var multiChoiceOptions = question.value !== undefined && question.value !== null && question.value.length > 0 && question.value.includes(";") ? question.value.split(";") : [] var multiChoiceOptions = question.value !== undefined && question.value !== null && question.value.length > 0 && question.value.includes(";") ? question.value.split(";") : []
@@ -1280,25 +1357,26 @@ const RunWorkflow = (defaultprops) => {
What do you want to do? What do you want to do?
</Typography> </Typography>
} }
<div fullWidth style={{width: "100%", marginTop: 10, marginBottom: 10, display: "flex", }}>
<Button fullWidth id="continue_execution" variant="contained" disabled={disabledButtons} color="primary" style={{flex: 1,}} onClick={() => {
onSubmit(null, execution_id, authorization, true)
<div fullWidth style={{width: "100%", marginTop: 10, marginBottom: 10, display: "flex", }}>
<Button fullWidth id="continue_execution" variant="contained" disabled={!handleValidateForm(executionArgument) || disabledButtons} color="primary" style={{flex: 1,}} onClick={() => {
setButtonClicked("FINISHED") setButtonClicked("FINISHED")
setExecutionData({ setExecutionData({
status: "FINISHED", status: "FINISHED",
}) })
onSubmit(null, execution_id, authorization, true)
}}>Continue</Button> }}>Continue</Button>
<Typography variant="body1" style={{marginLeft: 3, marginRight: 3, marginTop: 3, }}> <Typography variant="body1" style={{marginLeft: 3, marginRight: 3, marginTop: 3, }}>
&nbsp;or&nbsp; &nbsp;or&nbsp;
</Typography> </Typography>
<Button fullWidth id="abort_execution" variant="contained" color="primary" disabled={disabledButtons} style={{ flex: 1, }} onClick={() => { <Button fullWidth id="abort_execution" variant="contained" disabled={!handleValidateForm(executionArgument) || disabledButtons} color="primary" style={{ flex: 1, }} onClick={() => {
onSubmit(null, execution_id, authorization, false)
setButtonClicked("ABORTED") setButtonClicked("ABORTED")
setExecutionData({ setExecutionData({
status: "ABORTED", status: "ABORTED",
}) })
onSubmit(null, execution_id, authorization, false)
}}>Stop</Button> }}>Stop</Button>
</div> </div>
</span> </span>
@@ -1393,15 +1471,18 @@ const RunWorkflow = (defaultprops) => {
</div> </div>
} }
</Paper> </Paper>
{workflowQuestion !== "" ? null :
<Typography variant="body2" color="textSecondary" align="center" style={{marginTop: 10, }} > <Typography variant="body2" color="textSecondary" align="center" style={{marginTop: 10, }} >
Forms are in Beta. Form submission data includes your Organization's unique ID while logged in, or a unique identifier for your browser otherwise. Your input will be automatically sanitized. Forms are in late Beta. Form submission data includes your Organization's unique ID while logged in, or a unique identifier for your browser otherwise. Your input will be automatically sanitized.
</Typography> </Typography>
}
</div> </div>
// const isCorrectOrg = 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 = 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 loadedCheck = isLoaded ? const loadedCheck = isLoaded ?
<div> <div style={{marginTop: 30, }}>
{editWorkflowModalOpen === true ? {editWorkflowModalOpen === true ?
<EditWorkflow <EditWorkflow
saveWorkflow={saveWorkflow} saveWorkflow={saveWorkflow}
@@ -1485,7 +1566,7 @@ const RunWorkflow = (defaultprops) => {
</DialogContent> </DialogContent>
</Dialog> </Dialog>
{isLoggedIn && userdata?.active_org?.id === workflow?.org_id ? {isLoggedIn && userdata?.active_org?.id === workflow?.org_id || userdata?.support === true ?
<div style={{position: "fixed", top: 10, right: 20, }}> <div style={{position: "fixed", top: 10, right: 20, }}>
<Button <Button
-1
View File
@@ -782,7 +782,6 @@ func deployApp(cli *dockerclient.Client, image string, identifier string, env []
// image on every Orborus/new worker restart. // image on every Orborus/new worker restart.
// Running as coroutine for eventual completeness // Running as coroutine for eventual completeness
//go shuffle.DownloadDockerImageBackend(&http.Client{}, image)
// FIXME: With goroutines it got too much trouble of deploying with an older version // FIXME: With goroutines it got too much trouble of deploying with an older version
// Allowing slow startups, as long as it's eventually fast, and uses the same registry as on host. // Allowing slow startups, as long as it's eventually fast, and uses the same registry as on host.
shuffle.DownloadDockerImageBackend(&http.Client{Timeout: imagedownloadTimeout}, image) shuffle.DownloadDockerImageBackend(&http.Client{Timeout: imagedownloadTimeout}, image)