Fixed Hybrid triggers and minor view changes

This commit is contained in:
frikky
2021-10-12 00:27:32 +02:00
parent 2da6e43dc6
commit 5353f5aa63
11 changed files with 141 additions and 79 deletions
-1
View File
@@ -7,7 +7,6 @@ WORKDIR /app
ADD ./go-app/main.go /app ADD ./go-app/main.go /app
ADD ./go-app/walkoff.go /app ADD ./go-app/walkoff.go /app
ADD ./go-app/docker.go /app ADD ./go-app/docker.go /app
ADD ./go-app/oauth2.go /app
ADD ./go-app/go.mod /app ADD ./go-app/go.mod /app
+1
View File
@@ -1521,6 +1521,7 @@ class AppBase:
if variablename.lower() == actionname_lower: if variablename.lower() == actionname_lower:
baseresult = variable["value"] baseresult = variable["value"]
break break
except KeyError as e: except KeyError as e:
print("[INFO] KeyError wf variables: %s" % e) print("[INFO] KeyError wf variables: %s" % e)
pass pass
+2 -2
View File
@@ -2,7 +2,7 @@ module shuffle
go 1.13 go 1.13
replace github.com/frikky/shuffle-shared => ../../../../git/shuffle-shared //replace github.com/frikky/shuffle-shared => ../../../../git/shuffle-shared
//replace github.com/frikky/kin-openapi => ../../../../git/kin-openapi //replace github.com/frikky/kin-openapi => ../../../../git/kin-openapi
@@ -23,7 +23,7 @@ require (
github.com/docker/go-units v0.4.0 // indirect github.com/docker/go-units v0.4.0 // indirect
github.com/elastic/go-elasticsearch/v7 v7.13.1 // indirect github.com/elastic/go-elasticsearch/v7 v7.13.1 // indirect
github.com/frikky/kin-openapi v0.39.0 github.com/frikky/kin-openapi v0.39.0
github.com/frikky/shuffle-shared v0.1.5 github.com/frikky/shuffle-shared v0.1.12
github.com/fsouza/go-dockerclient v1.7.2 github.com/fsouza/go-dockerclient v1.7.2
github.com/ghodss/yaml v1.0.0 github.com/ghodss/yaml v1.0.0
github.com/go-git/go-billy/v5 v5.0.0 github.com/go-git/go-billy/v5 v5.0.0
-2
View File
@@ -2602,7 +2602,6 @@ func findValidScheduleAppFolders(rootAppFolder string) ([]string, error) {
appFiles, err := ioutil.ReadDir(appFolderLocation) appFiles, err := ioutil.ReadDir(appFolderLocation)
if err != nil { if err != nil {
// Invalid app folder (deleted within a few MS lol) // Invalid app folder (deleted within a few MS lol)
log.Printf("%s", err)
invalidRootFolders = append(invalidRootFolders, rootfile.Name()) invalidRootFolders = append(invalidRootFolders, rootfile.Name())
continue continue
} }
@@ -3168,7 +3167,6 @@ func buildSwaggerApp(resp http.ResponseWriter, body []byte, user shuffle.User) {
swagger, err := swaggerLoader.LoadSwaggerFromData(body) swagger, err := swaggerLoader.LoadSwaggerFromData(body)
if err != nil { if err != nil {
log.Printf("[ERROR] Swagger validation error: %s", err) log.Printf("[ERROR] Swagger validation error: %s", err)
//log.Printf("%s", string(body))
resp.WriteHeader(500) resp.WriteHeader(500)
resp.Write([]byte(`{"success": false, "reason": "Failed verifying openapi"}`)) resp.Write([]byte(`{"success": false, "reason": "Failed verifying openapi"}`))
return return
+1 -3
View File
@@ -730,7 +730,7 @@ func handleGetStreamResults(resp http.ResponseWriter, request *http.Request) {
ctx := context.Background() ctx := context.Background()
workflowExecution, err := shuffle.GetWorkflowExecution(ctx, actionResult.ExecutionId) workflowExecution, err := shuffle.GetWorkflowExecution(ctx, actionResult.ExecutionId)
if err != nil { if err != nil {
//log.Printf("Failed getting execution (streamresult) %s: %s", actionResult.ExecutionId, err) log.Printf("Failed getting execution (streamresult) %s: %s", actionResult.ExecutionId, err)
resp.WriteHeader(401) resp.WriteHeader(401)
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Bad authorization key or execution_id might not exist."}`))) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Bad authorization key or execution_id might not exist."}`)))
return return
@@ -1910,7 +1910,6 @@ func handleExecution(id string, workflow shuffle.Workflow, request *http.Request
//b, err := json.Marshal(workflowExecution) //b, err := json.Marshal(workflowExecution)
//if err == nil { //if err == nil {
// log.Printf("%s", string(b))
// log.Printf("LEN: %d", len(string(b))) // log.Printf("LEN: %d", len(string(b)))
// //workflowExecution.ExecutionOrg.SyncFeatures = Org{} // //workflowExecution.ExecutionOrg.SyncFeatures = Org{}
//} //}
@@ -3095,7 +3094,6 @@ func iterateOpenApiGithub(fs billy.Filesystem, dir []os.FileInfo, extra string,
// 3. Load this as a "standby" app // 3. Load this as a "standby" app
// FIXME: This should be a function ROFL // FIXME: This should be a function ROFL
//log.Printf("%s", string(readFile))
swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData([]byte(parsedOpenApi.Body)) swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData([]byte(parsedOpenApi.Body))
if err != nil { if err != nil {
log.Printf("[WARNING] Swagger validation error in loop (%s): %s. Continuing.", filename, err) log.Printf("[WARNING] Swagger validation error in loop (%s): %s. Continuing.", filename, err)
+3 -3
View File
@@ -1,7 +1,7 @@
version: '3' version: '3'
services: services:
frontend: frontend:
#build: ./frontend build: ./frontend
image: ghcr.io/frikky/shuffle-frontend:nightly image: ghcr.io/frikky/shuffle-frontend:nightly
container_name: shuffle-frontend container_name: shuffle-frontend
hostname: shuffle-frontend hostname: shuffle-frontend
@@ -16,7 +16,7 @@ services:
depends_on: depends_on:
- backend - backend
backend: backend:
#build: ./backend build: ./backend
image: ghcr.io/frikky/shuffle-backend:nightly image: ghcr.io/frikky/shuffle-backend:nightly
container_name: shuffle-backend container_name: shuffle-backend
hostname: ${BACKEND_HOSTNAME} hostname: ${BACKEND_HOSTNAME}
@@ -66,7 +66,7 @@ services:
- CLEANUP=${SHUFFLE_CONTAINER_AUTO_CLEANUP} - CLEANUP=${SHUFFLE_CONTAINER_AUTO_CLEANUP}
restart: unless-stopped restart: unless-stopped
opensearch: opensearch:
image: opensearchproject/opensearch:1.0.1 image: opensearchproject/opensearch:1.1.0
hostname: shuffle-opensearch hostname: shuffle-opensearch
container_name: shuffle-opensearch container_name: shuffle-opensearch
environment: environment:
+4 -2
View File
@@ -1,14 +1,16 @@
{ {
"name": "shuffler", "name": "shuffler",
"homepage": "https://shuffler.io", "homepage": "https://shuffler.io",
"version": "0.8.92", "version": "0.9.22",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@material-ui/core": "^4.5.2", "@material-ui/core": "^4.5.2",
"@material-ui/data-grid": "^4.0.0-alpha.22", "@material-ui/data-grid": "^4.0.0-alpha.22",
"@material-ui/icons": "^4.5.1", "@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.58", "@material-ui/lab": "^4.0.0-alpha.58",
"@material-ui/styles": "^4.5.2", "@material-ui/styles": "^4.5.2",
"@material-ui/utils": "^4.11.2",
"@mui/icons-material": "^5.0.3",
"@uiw/react-codemirror": "^3.2.1", "@uiw/react-codemirror": "^3.2.1",
"@use-it/interval": "^1.0.0", "@use-it/interval": "^1.0.0",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
+5 -4
View File
@@ -6,7 +6,8 @@ import {Link} from 'react-router-dom';
import { useTheme } from '@material-ui/core/styles'; import { useTheme } from '@material-ui/core/styles';
import { Chip, Badge, Typography, Paper, Tooltip, List, Avatar, Menu, ListItem, MenuItem, Select, Button, IconButton, Grid } from '@material-ui/core'; import { Chip, Badge, Typography, Paper, Tooltip, List, Avatar, Menu, ListItem, MenuItem, Select, Button, IconButton, Grid } from '@material-ui/core';
import { Notifications as NotificationsIcon, Home as HomeIcon, Polymer as PolymerIcon, Apps as AppsIcon, Description as DescriptionIcon} from '@material-ui/icons'; import { MeetingRoom as MeetingRoomIcon, Settings as SettingsIcon, Notifications as NotificationsIcon, Home as HomeIcon, Polymer as PolymerIcon, Apps as AppsIcon, Description as DescriptionIcon} from '@material-ui/icons';
//import LogoutIcon from '@mui/icons-material/Logout';
import { useAlert } from "react-alert"; import { useAlert } from "react-alert";
const hoverColor = "#f85a3e" const hoverColor = "#f85a3e"
@@ -331,7 +332,7 @@ const Header = props => {
anchorEl={anchorElAvatar} anchorEl={anchorElAvatar}
keepMounted keepMounted
open={Boolean(anchorElAvatar)} open={Boolean(anchorElAvatar)}
style={{zIndex: 10002}} style={{zIndex: 10012}}
onClose={() => { onClose={() => {
handleClose() handleClose()
}} }}
@@ -341,7 +342,7 @@ const Header = props => {
handleClose() handleClose()
}}> }}>
<Link to="/settings" style={hrefStyle}> <Link to="/settings" style={hrefStyle}>
Settings <SettingsIcon /> Settings
</Link> </Link>
</MenuItem> </MenuItem>
<MenuItem style={{color: "white"}} onClick={(event) => { <MenuItem style={{color: "white"}} onClick={(event) => {
@@ -349,7 +350,7 @@ const Header = props => {
handleClose() handleClose()
handleClickLogout() handleClickLogout()
}}> }}>
Logout <MeetingRoomIcon /> Logout
</MenuItem> </MenuItem>
</Menu> </Menu>
</span> </span>
+3
View File
@@ -1015,6 +1015,9 @@ const Admin = (props) => {
} }
const getOrgs = () => { const getOrgs = () => {
// API no longer in use, as it's in handleInfo request
return
fetch(globalUrl + "/api/v1/orgs", { fetch(globalUrl + "/api/v1/orgs", {
method: 'GET', method: 'GET',
headers: { headers: {
+109 -60
View File
@@ -36,6 +36,7 @@ import { Element as ScrollElement, animateScroll as scroll, scrollSpy, scroller
const surfaceColor = "#27292D" const surfaceColor = "#27292D"
const inputColor = "#383B40" const inputColor = "#383B40"
const appSorter = "favorite_apps"
// http://apps.cytoscape.org/apps/yfileslayoutalgorithms // http://apps.cytoscape.org/apps/yfileslayoutalgorithms
cytoscape.use(edgehandles); cytoscape.use(edgehandles);
@@ -314,13 +315,16 @@ const AngularWorkflow = (props) => {
} }
} }
if (param.name === "startnode" && outersub.id !== undefined) { console.log("PARAM: ", param)
console.log("SHOULD SET STARTNODE IN SUBFLOW SELECTION: ", outersub) //console.log("PARAMVAL: ", param.value)
const innernode = outersub.actions.find(action => action.id === param.value) if (param.name === "startnode" && param.value !== undefined && param.value !== null) {
console.log("FOUND NODE: ", innernode) //console.log("SHOULD SET STARTNODE IN SUBFLOW SELECTION: ", outersub)
if (innernode !== undefined && subworkflowStartnode.id !== innernode.id) { //const innernode = outersub.actions.find(action => action.id === param.value)
setSubworkflowStartnode(innernode) //console.log("FOUND NODE: ", innernode)
} //if (innernode !== undefined && subworkflowStartnode.id !== innernode.id) {
//setSubworkflowStartnode(JSON.parse(JSON.stringify(param.value)))
setSubworkflowStartnode(param.value)
//}
/* /*
const sub = responseJson.find(data => data.id === param.value) const sub = responseJson.find(data => data.id === param.value)
setSubworkflow(sub) setSubworkflow(sub)
@@ -780,9 +784,10 @@ const AngularWorkflow = (props) => {
} }
} }
const saveWorkflow = (curworkflow) => { const saveWorkflow = (curworkflow, executionArgument, startNode) => {
var success = false var success = false
if (isCloud && !isLoggedIn) { if (isCloud && !isLoggedIn) {
console.log("Should redirect to register with redirect.") console.log("Should redirect to register with redirect.")
window.location.href = `/register?view=/workflows/${props.match.params.key}&message=You need sign up to use workflows with Shuffle` window.location.href = `/register?view=/workflows/${props.match.params.key}&message=You need sign up to use workflows with Shuffle`
@@ -914,6 +919,12 @@ const AngularWorkflow = (props) => {
return response.json() return response.json()
}) })
.then((responseJson) => { .then((responseJson) => {
if (executionArgument !== undefined && startNode !== undefined) {
console.log("Running execution AFTER saving")
executeWorkflow(executionArgument, startNode, true)
return
}
if (!responseJson.success) { if (!responseJson.success) {
console.log(responseJson) console.log(responseJson)
alert.error("Failed to save: "+responseJson.reason) alert.error("Failed to save: "+responseJson.reason)
@@ -993,17 +1004,20 @@ const AngularWorkflow = (props) => {
return true return true
} }
const executeWorkflow = (executionArgument, startNode) => { const executeWorkflow = (executionArgument, startNode, hasSaved) => {
if (!lastSaved) { if (hasSaved === false) {
//alert.error("You might have forgotten to save before executing.") //alert.error("You might have forgotten to save before executing.")
//const saveWorkflow = (curworkflow) => {
setExecutionRequestStarted(true)
saveWorkflow(workflow, executionArgument, startNode)
console.log("FIXME: Might have forgotten to save before executing.") console.log("FIXME: Might have forgotten to save before executing.")
return
} }
if (workflow.public) { if (workflow.public) {
alert.info("Save it to get a new version") alert.info("Save it to get a new version")
} }
var returncheck = monitorUpdates() var returncheck = monitorUpdates()
if (!returncheck) { if (!returncheck) {
alert.error("No startnode set.") alert.error("No startnode set.")
@@ -1012,7 +1026,6 @@ const AngularWorkflow = (props) => {
setVisited([]) setVisited([])
setExecutionRequest({}) setExecutionRequest({})
setExecutionRequestStarted(true)
stop() stop()
var curelements = cy.elements() var curelements = cy.elements()
@@ -1908,7 +1921,7 @@ const AngularWorkflow = (props) => {
// cy.getElementById(currentNode.data.id).remove() // cy.getElementById(currentNode.data.id).remove()
// } // }
//} //}
} else if (data.buttonType === "set_startnode") { } else if (data.buttonType === "set_startnode" && data.type !== "TRIGGER") {
const parentNode = cy.getElementById(data.attachedTo) const parentNode = cy.getElementById(data.attachedTo)
if (parentNode !== null && parentNode !== undefined) { if (parentNode !== null && parentNode !== undefined) {
var oldstartnode = cy.getElementById(workflow.start) var oldstartnode = cy.getElementById(workflow.start)
@@ -2640,6 +2653,30 @@ const AngularWorkflow = (props) => {
} }
if (nodedata.type === "ACTION") { if (nodedata.type === "ACTION") {
/*
const tmpView = localStorage.getItem(appSorter)
const nodekey = nodedata.id
if (tmpView === null || tmpView === undefined) {
const basedata = {}
basedata[nodekey] = 1
localStorage.setItem(appSorter, JSON.stringify(basedata))
} else {
try {
var parsed = JSON.parse(tmpView)
try {
parsed[nodekey] += 1
} catch {
parsed[nodekey] = 1
}
localStorage.setItem(appSorter, JSON.stringify(parsed))
} catch {
console.log("Bad data in tmpView: ", tmpView)
}
}
console.log("FAVORITeS: ", tmpView)
*/
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 = {
@@ -2694,6 +2731,12 @@ const AngularWorkflow = (props) => {
setWorkflow(workflow) setWorkflow(workflow)
} else if (nodedata.type === "TRIGGER") { } else if (nodedata.type === "TRIGGER") {
if (nodedata.is_valid === false) {
alert.info("This trigger is not available to you")
node.remove()
return
}
if (workflow.triggers === undefined) { if (workflow.triggers === undefined) {
workflow.triggers = [nodedata] workflow.triggers = [nodedata]
} else { } else {
@@ -2794,8 +2837,7 @@ const AngularWorkflow = (props) => {
// } // }
//} else { //} else {
// //console.log("Shouldnt re-add info? ") // //console.log("Shouldnt re-add info? ")
//} //}
} }
const onEdgeRemoved = (event) => { const onEdgeRemoved = (event) => {
@@ -4085,6 +4127,19 @@ const AngularWorkflow = (props) => {
"description": "Simple HTTP webhook", "description": "Simple HTTP webhook",
"long_description": "Execute a workflow with an unauthicated POST request", "long_description": "Execute a workflow with an unauthicated POST request",
}, },
{
"name": "Schedule",
"type": "TRIGGER",
"status": "uninitialized",
"description": "Schedule execution time",
"trigger_type": "SCHEDULE",
"errors": null,
"large_image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAAAAABVicqIAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfjCB8QNSt2pVcCAAAIxUlEQVRo3u2aa4xV1RXH/2vtfWeAYQbBBwpUBqGkjQLKw4LQ1NqmDy2RxmKJSGxiaatttbWhabQPSFuT2i+NqdFKbVqjjDZGYxqgxFbbWgHlNSkBChQj8ii+ZV4Mc/be/34459w5995zH4zYpA3709x7z9m/vdbae6/XCPH+D/0vMM5AzkDOQBoY9hSfJ4n4khCISGMvySlcKww0UvYNpAFdNAxhEAXQc/T1g2/2RFJoOW/8OeNHAaDXepwGIYEGOL5146a9/z5R/LJp7KRp86+4UOJf3yskUKVv/ZN/OQoAogIIQQYAaJ117aL2ehjWHcEF7lsxEQK1RgeNLaLGKgSti5919L76DPUhzvPAV0cAanL3khgDyMf+GOjCUCHB8Z0VI6GFGsYVq8Cnt1cXpg7Eez7ZXiKEiKgxqqqSFUcx7M5+uqFAHLuWQwYRYqzNfsjAjWLmdka5Kqu5u5ztvOkfNoTko4oHICNHtzSHqK+rywMwCEyZruX+ZV5zLFcL4uzTy7qtT24RZUDh4ivmTL2wdbgN/mTvkZd3bO58F2KKTwT+aGXIu2uq6yribxQmMYRRYMZPO8uVfmTNouGx4QFALW6OQqX5q0McV8MkR0wNdOEzAyRd5H2Ih3cuMHD3N0ZB0+ea8MUBhoYhER9GcimJUXz0eTJEvvx9H/nAA19pQrwFRApY6iueqgZxXF9ItCsWZz0Y6KocNu8Ct8xBqjKL2+kbg3juH5vao4D5/6SrcgRiDPu/J4nYanF/+XnJhwT2z0v8mRjc0l/jyojldvz9qHhRotL81zJKPsTxjoShBj+uefklq4q4KRXd4NKeUuMjn7E21ZXFPVWOcdkY4PaxScRgcUepKHmQwJ5Liqta1RiDjLi5LaaImL+VUPIgjj+LlSUWt1Saw3vvK7cpGbEjsb7BfJdVWA4k8Nj5UAHEYt5JNiZHTFmZWNLgt1lRciCOK2FFAEHLjvLdGHhi+eev/8J112ytOA0MwX08VrPi0uzBr4QEvj4BEhvwbkYVv3adC4HiDznOw3P7SKgAMOjI/F7p8AI6DlsCUDf9NlTGB9oMaw3yAgd1l92exqSrs8FppSBuNgwAUTxeudrA7gugUKzNc4OBr10YvyzmpUF9VkhCbN4qAYCGuYvz1pveaHkeSPx5X4MAoPonUHRVOZCnYeOfbxWfM1F/BIJVInXFstFOABDrnWEVCI1/BgGA+kmfy5mJ6Pf5q0tEmXAtFACxcweqQrBnFwIAwWdH+0qdCOqF8tcjAKDBCwhVIS9GhgCIhVVmqRnYKha0J4Z+oWi3Sqm3xSsO4y8fSoYkvnV+bHp09qVGKZuHBjuT72eOCQ3mOGVjbiLvkWPIhwA9h0EAgukYYtllNrwA1BP7qkCI195EbJIZQ4MIJoyGAFAcqirJWz0ggICx+ecNI5sACFxVyLjk6sOR9Dsbrx+gAEDQ4xACQnsWSEr65uAwAmH1PSbUs5M/j6bv2XSO9LLoSyLXEaOgjWa3pRqXtuSv3hLIu7CuRwHAjetKfjFvjxgQFlrAUOgbMbxyruqYpmSKgYy6gm5dYk2/gBA2DcADII5/UgBqE2GOT3tqOCuFCrWz6+wqSHr+LqP28tkUk3YP3tqBPRdAIZj5HENuNOa5EAaAxQ3pa4gd7mNGraqKDKYXoiKipoCp+zOeNrB7AgQQmGUH6XN9ypUJZHnqcpCEAB2an3gWcNG+rHsKfOccWADG4Oyf91XGfYH+kgTyw9R5Iw001qjmeCiDSbvLXGC4pxWqcTo6fV2FzjwPnYXYzT9YBmHEx4ya8j1r0b67Ml751xKBUYEayOL99CUYx01ITvz6UnWlGtPSjK+Ai/ZUunIXuGE21ApgDNpW9ZbozPGXsZfH8AMlhk8ppnRTWkzZmxcueMeT950LNRCxig894TM7w/FGGACKD/aloVcmWonYYTIFH7GYvK9KZu48jy63MCqiRnDN7mIkF9jVDgVgcF3x5WxIVLrHCphSjRHXWzYuiFNSNWi+N5XFcV186Vr8ohgZlsRdA+wwYlJdTd7L2ulVeGgcjAGkGb9KH3W8KTGJbCkqsTS4i7hGjYEILCbVZCQ6+3oTjLH41ODWezX1JtOiog7LIsiIHUaNqEX7rjoMMjjP7VdBTWFTuuiId8PGBv3u4PvlYWpsfYuJ9Rmxzvyjk/Ht9NnAYx+AojxMrYiFI3YYg8m7G2GQdI5v/eRQqpiId8IKAItP1EwdIj5e3x5ZnYXidJ7bW9KsY01mhpwkKOKvX2qYQTKkSWUI0VVpEnRZ7SSI9GTdnDpvRFyVuHODh+ukcyy9vxvmRVwTuyOxWFAvMS0XyzeaYm9sjXM5Eft8ydrqQTx39IdGhBngtrGIfYXFd+oXC0qW9xDuyvWypSNE3DhY9pje1UDZI8NYrYovdderSjjHx9riEwLBsL83VMApMh6BqsWcnTWF8Y4nVkBt6iEeaKwUlbycuDGD1ntdmZfNIgI3zoLR1EN8q9GiWsx4NHFiRvGRZ8ngqpQHv9wEW4xIbwwNlwdJz4Nj0kaRGshn1p4k6SJXVujcdWsb1CYBtcWSUyl0koFrmpEWIo0CF6/aVm6Zw49cMywtgYsYi5tdzoavVXwOuuGGtwsuU3y2H55/+ZT21hE2hP7eI/s7X+w8DjFJCVyUIb/4XLOM7s3+pVuSMrqARjwBtI5qbeZAb/fxAMBISDppYtzIB5bmltHrNQR6bwNsMbQULekBZD6INZi1o8p5qt/a2DC1rD8jqqpamiEZg+HfPzG01gYZHLt/0AYxtZo0RoGrO4fcpCHpPF/5ZhugNie9E1FrAblyHd9Du4mxg335rilp4yyrN2MNBK1LnvM1a8cNtwBP/OmpP78aLz4WiHF3pm3u1Ysm1mkBnkozs3vbxk17jmabmRfNmD9vwmlqZsYLhwHQe/SNV97ojrTQcv74MRPaAIRwutqyCYdl853uBnM6LdNqxPvUKh/y+P/594UzkDOQ/3HIfwCAE6puXSx5zQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxOS0wOC0zMVQxNjo1Mzo0My0wNDowMGtSg1gAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTktMDgtMzFUMTY6NTM6NDMtMDQ6MDAaDzvkAAAAAElFTkSuQmCC",
"label": "Schedule",
"is_valid": true,
"environment": "onprem",
"long_description": "Create a schedule based on cron",
},
{ {
"name": "Shuffle Workflow", "name": "Shuffle Workflow",
"type": "TRIGGER", "type": "TRIGGER",
@@ -4106,24 +4161,11 @@ const AngularWorkflow = (props) => {
"description": "Wait for user input", "description": "Wait for user input",
"trigger_type": "USERINPUT", "trigger_type": "USERINPUT",
"errors": null, "errors": null,
"is_valid": true, "is_valid": cloudSyncEnabled || isCloud ? true : false,
"label": "User input", "label": "User input",
"environment": "cloud", "environment": "cloud",
"long_description": "Take user input to continue execution", "long_description": "Take user input to continue execution",
}, },
{
"name": "Schedule",
"type": "TRIGGER",
"status": "uninitialized",
"description": "Schedule execution time",
"trigger_type": "SCHEDULE",
"errors": null,
"large_image": "data:image/png;base64,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",
"label": "Schedule",
"is_valid": true,
"environment": "onprem",
"long_description": "Create a schedule based on cron",
},
{ {
"name": "Office365", "name": "Office365",
"type": "TRIGGER", "type": "TRIGGER",
@@ -5795,7 +5837,8 @@ const AngularWorkflow = (props) => {
: "https%3A%2F%2Fshuffler.io%2Fapi%2Fv1%2Ftriggers%2Foutlook%2Fregister" : "https%3A%2F%2Fshuffler.io%2Fapi%2Fv1%2Ftriggers%2Foutlook%2Fregister"
: "http%3A%2F%2Flocalhost:5001%2Fapi%2Fv1%2Ftriggers%2Foutlook%2Fregister" : "http%3A%2F%2Flocalhost:5001%2Fapi%2Fv1%2Ftriggers%2Foutlook%2Fregister"
const client_id = "fd55c175-aa30-4fa6-b303-09a29fb3f750" //const client_id = "fd55c175-aa30-4fa6-b303-09a29fb3f750"
const client_id = "bb4bff85-0d0b-4f5d-8a69-3cee8029b11a"
//isCloud ? userdata.username : //isCloud ? userdata.username :
const username = userdata.id const username = userdata.id
@@ -5808,9 +5851,12 @@ const AngularWorkflow = (props) => {
return return
} }
//console.log("SELECTED: ", selectedTrigger.
console.log("BRANCH: ", branch) console.log("BRANCH: ", branch)
const startnode = branch.destination_id const startnode = branch.destination_id
const url = `https://login.microsoftonline.com/common/oauth2/authorize?access_type=offline&client_id=${client_id}&redirect_uri=${redirectUri}&resource=https%3A%2F%2Fgraph.microsoft.com&response_type=code&scope=Mail.Read+User.Read+https%3A%2F%2Foutlook.office.com%2Fmail.read&state=workflow_id%3D${props.match.params.key}%26trigger_id%3D${selectedTrigger.id}username%3D${username}%26type%3Doutlook%26start%3d${startnode}&prompt=login` const url = `https://login.microsoftonline.com/common/oauth2/authorize?access_type=offline&client_id=${client_id}&redirect_uri=${redirectUri}&resource=https%3A%2F%2Fgraph.microsoft.com&response_type=code&scope=Mail.Read+User.Read+https%3A%2F%2Foutlook.office.com%2Fmail.read&prompt=login&state=workflow_id%3D${props.match.params.key}%26trigger_id%3D${selectedTrigger.id}%26username%3D${username}%26type%3Doutlook%26start%3d${startnode}`
//const url = `https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&prompt=consent&client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&scope=${scopes}&state=workflow_id%3D${props.match.params.key}%26trigger_id%3D${selectedTrigger.id}%26username%3D${username}%26type%3Dgmail%26start%3d${startnode}`
//const scopes = "https://www.googleapis.com/auth/gmail.readonly" //const scopes = "https://www.googleapis.com/auth/gmail.readonly"
//const url = `https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&prompt=consent&client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&scope=${scopes}&state=workflow_id%3D${props.match.params.key}%26trigger_id%3D${selectedTrigger.id}%26username%3D${username}%26type%3Dgmail%26start%3d${startnode}` //const url = `https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&prompt=consent&client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&scope=${scopes}&state=workflow_id%3D${props.match.params.key}%26trigger_id%3D${selectedTrigger.id}%26username%3D${username}%26type%3Dgmail%26start%3d${startnode}`
@@ -6331,7 +6377,7 @@ const AngularWorkflow = (props) => {
workflow.triggers[selectedTriggerIndex].parameters[1] = {"name": "argument", "value": ""} workflow.triggers[selectedTriggerIndex].parameters[1] = {"name": "argument", "value": ""}
workflow.triggers[selectedTriggerIndex].parameters[2] = {"name": "user_apikey", "value": ""} workflow.triggers[selectedTriggerIndex].parameters[2] = {"name": "user_apikey", "value": ""}
workflow.triggers[selectedTriggerIndex].parameters[3] = {"name": "startnode", "value": ""} workflow.triggers[selectedTriggerIndex].parameters[3] = {"name": "startnode", "value": ""}
workflow.triggers[selectedTriggerIndex].parameters[4] = {"name": "check_result", "value": "true"} workflow.triggers[selectedTriggerIndex].parameters[4] = {"name": "check_result", "value": "false"}
console.log("SETTINGS: ", userSettings) console.log("SETTINGS: ", userSettings)
if (userSettings !== undefined && userSettings !== null && userSettings.apikey !== null && userSettings.apikey !== undefined && userSettings.apikey.length > 0) { if (userSettings !== undefined && userSettings !== null && userSettings.apikey !== null && userSettings.apikey !== undefined && userSettings.apikey.length > 0) {
@@ -6411,24 +6457,23 @@ const AngularWorkflow = (props) => {
onChange={(e) => { onChange={(e) => {
setUpdate(Math.random()) setUpdate(Math.random())
workflow.triggers[selectedTriggerIndex].parameters[0].value = e.target.value.id workflow.triggers[selectedTriggerIndex].parameters[0].value = e.target.value.id
setSubworkflowStartnode(e.target.value.start) setSubworkflow(e.target.value)
// Sets the startnode // Sets the startnode
if (e.target.value.id !== workflow.id) { if (e.target.value.id !== workflow.id) {
console.log("WORKFLOW: ", e.target.value) console.log("WORKFLOW: ", e.target.value)
setSubworkflow(e.target.value)
const startnode = e.target.value.actions.find(action => action.id === e.target.value.start) const startnode = e.target.value.actions.find(action => action.id === e.target.value.start)
if (startnode !== undefined && startnode !== null) { if (startnode !== undefined && startnode !== null) {
//ddsetSubworkflowStartnode(innernode) console.log("STARTNODE: ", startnode)
setSubworkflowStartnode(startnode) setSubworkflowStartnode(startnode)
try { try {
workflow.triggers[selectedTriggerIndex].parameters[3].value = e.target.value.id workflow.triggers[selectedTriggerIndex].parameters[3].value = startnode.id
} catch { } catch {
workflow.triggers[selectedTriggerIndex].parameters[3] = { workflow.triggers[selectedTriggerIndex].parameters[3] = {
"name": "startnode", "name": "startnode",
"value": e.target.value.id, "value": startnode.id,
} }
} }
@@ -6437,7 +6482,6 @@ const AngularWorkflow = (props) => {
console.log("STARTNODE: ", startnode) console.log("STARTNODE: ", startnode)
} else { } else {
console.log("WORKFLOW: ", workflow) console.log("WORKFLOW: ", workflow)
setSubworkflow(e.target.value)
} }
setWorkflow(workflow) setWorkflow(workflow)
@@ -6471,7 +6515,8 @@ const AngularWorkflow = (props) => {
<b>Select the Startnode</b> <b>Select the Startnode</b>
</div> </div>
</div> </div>
<Select <Select
defaultValue={""}
value={subworkflowStartnode} value={subworkflowStartnode}
SelectDisplayProps={{ SelectDisplayProps={{
style: { style: {
@@ -6528,6 +6573,7 @@ const AngularWorkflow = (props) => {
cy.add(cybranch) cy.add(cybranch)
} }
console.log("Value to be set: ", e.target.value)
try { try {
workflow.triggers[selectedTriggerIndex].parameters[3].value = e.target.value.id workflow.triggers[selectedTriggerIndex].parameters[3].value = e.target.value.id
} catch { } catch {
@@ -6927,7 +6973,7 @@ const AngularWorkflow = (props) => {
const item = splitItem[key] const item = splitItem[key]
const curfolder = triggerFolders.find(a => a.displayName === item) const curfolder = triggerFolders.find(a => a.displayName === item)
if (curfolder === undefined) { if (curfolder === undefined) {
alert.error("Something went wrong with outlook folder: "+item) alert.error("Something went wrong with folder selection: "+item)
return return
} }
@@ -7002,7 +7048,6 @@ const AngularWorkflow = (props) => {
} }
const param = trigger.parameters.find(param => param.name === "auth_headers") const param = trigger.parameters.find(param => param.name === "auth_headers")
console.log("PARAM: ", param)
var auth = "" var auth = ""
if (param !== undefined && param !== null) { if (param !== undefined && param !== null) {
auth = param.value auth = param.value
@@ -7258,7 +7303,7 @@ const AngularWorkflow = (props) => {
}} }}
fullWidth fullWidth
color="primary" color="primary"
placeholder={"+474823212,+460203042"} placeholder={"+474823212132,+46020304242"}
defaultValue={workflow.triggers[selectedTriggerIndex].parameters[4].value} defaultValue={workflow.triggers[selectedTriggerIndex].parameters[4].value}
onBlur={(event) => { onBlur={(event) => {
workflow.triggers[selectedTriggerIndex].parameters[4].value = event.target.value workflow.triggers[selectedTriggerIndex].parameters[4].value = event.target.value
@@ -7633,7 +7678,7 @@ const AngularWorkflow = (props) => {
<Tooltip color="primary" title="Test Execution" placement="top"> <Tooltip color="primary" title="Test Execution" placement="top">
<span> <span>
<Button disabled={workflow.public || executionRequestStarted || !workflow.isValid} style={{height: boxSize, width: boxSize}} color="primary" variant="contained" onClick={() => { <Button disabled={workflow.public || executionRequestStarted || !workflow.isValid} style={{height: boxSize, width: boxSize}} color="primary" variant="contained" onClick={() => {
executeWorkflow(executionText, workflow.start) executeWorkflow(executionText, workflow.start, lastSaved)
}}> }}>
<PlayArrowIcon style={{ fontSize: 60}} /> <PlayArrowIcon style={{ fontSize: 60}} />
</Button> </Button>
@@ -8156,12 +8201,12 @@ const AngularWorkflow = (props) => {
</Breadcrumbs> </Breadcrumbs>
<Divider style={{backgroundColor: "rgba(255,255,255,0.6)", marginTop: 10, marginBottom: 10,}}/> <Divider style={{backgroundColor: "rgba(255,255,255,0.6)", marginTop: 10, marginBottom: 10,}}/>
<div style={{display: "flex"}}> <div style={{display: "flex"}}>
<h2>Workflow Results</h2> <h2>Execution info</h2>
<Tooltip color="primary" title="Rerun workflow" placement="top" style={{zIndex: 10011}}> <Tooltip color="primary" title="Rerun workflow" placement="top" style={{zIndex: 10011}}>
<span style={{}}> <span style={{}}>
<Button color="primary" style={{float: "right", marginTop: 20, marginLeft: 10,}} onClick={() => { <Button color="primary" style={{float: "right", marginTop: 20, marginLeft: 10,}} onClick={() => {
console.log("DATA: ", executionData) console.log("DATA: ", executionData)
executeWorkflow(executionData.execution_argument, executionData.start) executeWorkflow(executionData.execution_argument, executionData.start, lastSaved)
setExecutionModalOpen(false) setExecutionModalOpen(false)
//executionText, workflow.start) //executionText, workflow.start)
}}> }}>
@@ -8298,12 +8343,12 @@ const AngularWorkflow = (props) => {
if (triggers.length > 2) { if (triggers.length > 2) {
if (data.action.app_name === "shuffle-subflow") { if (data.action.app_name === "shuffle-subflow") {
const parsedImage = triggers[1].large_image const parsedImage = triggers[2].large_image
actionimg = <img alt={"Shuffle Subflow"} src={parsedImage} style={{marginRight: 20, width: imgsize, height: imgsize, border: `2px solid ${statusColor}`, borderRadius: executionData.start === data.action.id ? 25 : 5}} /> actionimg = <img alt={"Shuffle Subflow"} src={parsedImage} style={{marginRight: 20, width: imgsize, height: imgsize, border: `2px solid ${statusColor}`, borderRadius: executionData.start === data.action.id ? 25 : 5}} />
} }
if (data.action.app_name === "User Input") { if (data.action.app_name === "User Input") {
actionimg = <img alt={"Shuffle Subflow"} src={triggers[2].large_image} style={{marginRight: 20, width: imgsize, height: imgsize, border: `2px solid ${statusColor}`, borderRadius: executionData.start === data.action.id ? 25 : 5}} /> actionimg = <img alt={"Shuffle Subflow"} src={triggers[3].large_image} style={{marginRight: 20, width: imgsize, height: imgsize, border: `2px solid ${statusColor}`, borderRadius: executionData.start === data.action.id ? 25 : 5}} />
} }
} }
@@ -8439,7 +8484,7 @@ const AngularWorkflow = (props) => {
</Drawer> </Drawer>
// This sucks :) // This sucks :)
const curapp = !codeModalOpen ? {} : selectedResult.action.app_name === "shuffle-subflow" ? triggers[1] : selectedResult.action.app_name === "User Input" ? triggers[2] : apps.find(a => a.name === selectedResult.action.app_name && a.app_version === selectedResult.action.app_version) const curapp = !codeModalOpen ? {} : selectedResult.action.app_name === "shuffle-subflow" ? triggers[2] : selectedResult.action.app_name === "User Input" ? triggers[3] : apps.find(a => a.name === selectedResult.action.app_name && a.app_version === selectedResult.action.app_version)
const imgsize = 50 const imgsize = 50
const statusColor = !codeModalOpen ? "red" : selectedResult.status === "FINISHED" || selectedResult.status === "SUCCESS" ? green : selectedResult.status === "ABORTED" || selectedResult.status === "FAILURE" ? "red" : yellow const statusColor = !codeModalOpen ? "red" : selectedResult.status === "FINISHED" || selectedResult.status === "SUCCESS" ? green : selectedResult.status === "ABORTED" || selectedResult.status === "FAILURE" ? "red" : yellow
const validate = !codeModalOpen ? "" : validateJson(selectedResult.result.trim()) const validate = !codeModalOpen ? "" : validateJson(selectedResult.result.trim())
@@ -8904,16 +8949,20 @@ const AngularWorkflow = (props) => {
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button <Button
style={{borderRadius: "0px"}} style={{borderRadius: "0px"}}
onClick={() => { onClick={() => {
setNewVariableName("") setNewVariableName("")
setNewVariableDescription("") setNewVariableDescription("")
setNewVariableValue("") setNewVariableValue("")
setVariablesModalOpen(false) setVariablesModalOpen(false)
}} color="primary"> }} color="primary">
Cancel Cancel
</Button> </Button>
<Button style={{borderRadius: "0px"}} disabled={newVariableName.length === 0 || newVariableValue.length === 0} onClick={() => { <Button
style={{borderRadius: "0px"}}
disabled={newVariableName.length === 0 || newVariableValue.length === 0}
variant={"contained"}
onClick={() => {
if (workflow.workflow_variables === undefined || workflow.workflow_variables === null) { if (workflow.workflow_variables === undefined || workflow.workflow_variables === null) {
workflow.workflow_variables = [] workflow.workflow_variables = []
} }
@@ -8946,8 +8995,8 @@ const AngularWorkflow = (props) => {
setNewVariableDescription("") setNewVariableDescription("")
setNewVariableValue("") setNewVariableValue("")
}} color="primary"> }} color="primary">
Submit Submit
</Button> </Button>
</DialogActions> </DialogActions>
</FormControl> </FormControl>
</Dialog> </Dialog>
+13 -2
View File
@@ -707,6 +707,11 @@ const Workflows = (props) => {
useEffect(() => { useEffect(() => {
if (workflows.length <= 0 && firstrequest) { if (workflows.length <= 0 && firstrequest) {
const tmpView = localStorage.getItem('view');
if (tmpView !== undefined && tmpView !== null) {
setView(tmpView)
}
setFirstrequest(false) setFirstrequest(false)
getAvailableWorkflows() getAvailableWorkflows()
} }
@@ -1847,12 +1852,18 @@ const Workflows = (props) => {
: null*/} : null*/}
{view === "list" && ( {view === "list" && (
<Tooltip color="primary" title={"Grid View"} placement="top"> <Tooltip color="primary" title={"Grid View"} placement="top">
<Button color="primary" variant="text" onClick={() => setView("grid")}><GridOnIcon /></Button> <Button color="primary" variant="text" onClick={() => {
localStorage.setItem('view', "grid");
setView("grid")
}}><GridOnIcon /></Button>
</Tooltip> </Tooltip>
)} )}
{view === "grid" && ( {view === "grid" && (
<Tooltip color="primary" title={"List View"} placement="top"> <Tooltip color="primary" title={"List View"} placement="top">
<Button color="primary" variant="text" onClick={() => setView("list")}><ListIcon /></Button> <Button color="primary" variant="text" onClick={() => {
localStorage.setItem('view', "list");
setView("list")
}}><ListIcon /></Button>
</Tooltip> </Tooltip>
)} )}
<Tooltip color="primary" title={"Import workflows"} placement="top"> <Tooltip color="primary" title={"Import workflows"} placement="top">