#287: Basic import configuration done
This commit is contained in:
+6
-49
@@ -1506,49 +1506,6 @@ func getUserCount() (int, error) {
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleGetSchedules(resp http.ResponseWriter, request *http.Request) {
|
|
||||||
cors := handleCors(resp, request)
|
|
||||||
if cors {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := shuffle.HandleApiAuthentication(resp, request)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Api authentication failed in set new workflowhandler: %s", err)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.Role != "admin" {
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false, "reason": "Admin required"}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
schedules, err := getAllSchedules(ctx, user.ActiveOrg.Id)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed getting schedules: %s", err)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false, "reason": "Couldn't get schedules"}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
newjson, err := json.Marshal(schedules)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed unmarshal: %s", err)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed unpacking environments"}`)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//log.Printf("Existing environments: %s", string(newjson))
|
|
||||||
|
|
||||||
resp.WriteHeader(200)
|
|
||||||
resp.Write(newjson)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkAdminLogin(resp http.ResponseWriter, request *http.Request) {
|
func checkAdminLogin(resp http.ResponseWriter, request *http.Request) {
|
||||||
cors := handleCors(resp, request)
|
cors := handleCors(resp, request)
|
||||||
if cors {
|
if cors {
|
||||||
@@ -5379,7 +5336,7 @@ func runInit(ctx context.Context) {
|
|||||||
|
|
||||||
// Gets schedules and starts them
|
// Gets schedules and starts them
|
||||||
log.Printf("Relaunching schedules")
|
log.Printf("Relaunching schedules")
|
||||||
schedules, err := getAllSchedules(ctx, "ALL")
|
schedules, err := shuffle.GetAllSchedules(ctx, "ALL")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed getting schedules during service init: %s", err)
|
log.Printf("Failed getting schedules during service init: %s", err)
|
||||||
} else {
|
} else {
|
||||||
@@ -6214,18 +6171,18 @@ func initHandlers() {
|
|||||||
/* Everything below here increases the counters*/
|
/* Everything below here increases the counters*/
|
||||||
r.HandleFunc("/api/v1/workflows", shuffle.GetWorkflows).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows", shuffle.GetWorkflows).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/workflows", shuffle.SetNewWorkflow).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows", shuffle.SetNewWorkflow).Methods("POST", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/workflows/{key}", shuffle.GetSpecificWorkflow).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows/schedules", shuffle.HandleGetSchedules).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/workflows/{key}", shuffle.SaveWorkflow).Methods("PUT", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows/{key}/executions", shuffle.GetWorkflowExecutions).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/workflows/schedules", handleGetSchedules).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows/{key}/executions/{key}/abort", shuffle.AbortExecution).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/workflows/{key}/schedule", scheduleWorkflow).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows/{key}/schedule", scheduleWorkflow).Methods("POST", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/workflows/download_remote", loadSpecificWorkflows).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows/download_remote", loadSpecificWorkflows).Methods("POST", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/workflows/{key}/execute", executeWorkflow).Methods("GET", "POST", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows/{key}/execute", executeWorkflow).Methods("GET", "POST", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/workflows/{key}/schedule/{schedule}", stopSchedule).Methods("DELETE", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows/{key}/schedule/{schedule}", stopSchedule).Methods("DELETE", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/workflows/{key}/outlook", createOutlookSub).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows/{key}/outlook", createOutlookSub).Methods("POST", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/workflows/{key}/outlook/{triggerId}", handleDeleteOutlookSub).Methods("DELETE", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows/{key}/outlook/{triggerId}", handleDeleteOutlookSub).Methods("DELETE", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/workflows/{key}/executions", shuffle.GetWorkflowExecutions).Methods("GET", "OPTIONS")
|
|
||||||
r.HandleFunc("/api/v1/workflows/{key}/executions/{key}/abort", shuffle.AbortExecution).Methods("GET", "OPTIONS")
|
|
||||||
r.HandleFunc("/api/v1/workflows/{key}", deleteWorkflow).Methods("DELETE", "OPTIONS")
|
r.HandleFunc("/api/v1/workflows/{key}", deleteWorkflow).Methods("DELETE", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/workflows/{key}", shuffle.SaveWorkflow).Methods("PUT", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/workflows/{key}", shuffle.GetSpecificWorkflow).Methods("GET", "OPTIONS")
|
||||||
|
|
||||||
// Triggers
|
// Triggers
|
||||||
r.HandleFunc("/api/v1/hooks/new", shuffle.HandleNewHook).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/hooks/new", shuffle.HandleNewHook).Methods("POST", "OPTIONS")
|
||||||
|
|||||||
+2
-183
@@ -1079,7 +1079,7 @@ func handleWorkflowQueue(resp http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if actionResult.Status == "WAITING" && actionResult.Action.AppName == "User Input" {
|
if actionResult.Status == "WAITING" && actionResult.Action.AppName == "User Input" {
|
||||||
log.Printf("SHOULD WAIT A BIT AND RUN CLOUD STUFF WITH USER INPUT! WAITING!")
|
log.Printf("[INFO] SHOULD WAIT A BIT AND RUN CLOUD STUFF WITH USER INPUT! WAITING!")
|
||||||
|
|
||||||
var trigger shuffle.Trigger
|
var trigger shuffle.Trigger
|
||||||
err = json.Unmarshal([]byte(actionResult.Result), &trigger)
|
err = json.Unmarshal([]byte(actionResult.Result), &trigger)
|
||||||
@@ -4919,187 +4919,6 @@ func getWorkflowExecutions(resp http.ResponseWriter, request *http.Request) {
|
|||||||
resp.Write(newjson)
|
resp.Write(newjson)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllSchedules(ctx context.Context, orgId string) ([]ScheduleOld, error) {
|
|
||||||
var schedules []ScheduleOld
|
|
||||||
|
|
||||||
q := datastore.NewQuery("schedules").Filter("org = ", orgId)
|
|
||||||
if orgId == "ALL" {
|
|
||||||
q = datastore.NewQuery("schedules")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := dbclient.GetAll(ctx, q, &schedules)
|
|
||||||
if err != nil {
|
|
||||||
return []ScheduleOld{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return schedules, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//FIXME: Add cursor
|
|
||||||
//func shuffle.GetAllWorkflowApps(ctx context.Context, maxLen int) ([]shuffle.WorkflowApp, error) {
|
|
||||||
// var apps []WorkflowApp
|
|
||||||
// query := datastore.NewQuery("workflowapp").Order("-edited").Limit(10)
|
|
||||||
// //query := datastore.NewQuery("workflowapp").Order("-edited").Limit(40)
|
|
||||||
//
|
|
||||||
// cacheKey := fmt.Sprintf("workflowapps-sorted-%d", maxLen)
|
|
||||||
// if value, found := requestCache.Get(cacheKey); found {
|
|
||||||
// parsedValue := value.(*[]WorkflowApp)
|
|
||||||
// log.Printf("[INFO] Returning %d apps from cache", len(*parsedValue))
|
|
||||||
// return *parsedValue, nil
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// cursorStr := ""
|
|
||||||
//
|
|
||||||
// // NOT BEING UPDATED
|
|
||||||
// // FIXME: Update the app with the correct actions. HOW DOES THIS WORK??
|
|
||||||
// // Seems like only actions are wrong. Could get the app individually.
|
|
||||||
// // Guessing it's a memory issue.
|
|
||||||
// //Actions []WorkflowAppAction `json:"actions" yaml:"actions" required:true datastore:"actions,noindex"`
|
|
||||||
// //errors.New(nil)
|
|
||||||
// var err error
|
|
||||||
// for {
|
|
||||||
// it := dbclient.Run(ctx, query)
|
|
||||||
// //_, err = it.Next(&app)
|
|
||||||
// for {
|
|
||||||
// var app WorkflowApp
|
|
||||||
// _, err := it.Next(&app)
|
|
||||||
// if err != nil {
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if app.Name == "Shuffle Subflow" {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// found := false
|
|
||||||
// //log.Printf("ACTIONS: %d - %s", len(app.Actions), app.Name)
|
|
||||||
// for _, innerapp := range apps {
|
|
||||||
// if innerapp.Name == app.Name {
|
|
||||||
// found = true
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if !found {
|
|
||||||
// apps = append(apps, app)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if err != iterator.Done {
|
|
||||||
// //log.Printf("[INFO] Failed fetching results: %v", err)
|
|
||||||
// //break
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Get the cursor for the next page of results.
|
|
||||||
// nextCursor, err := it.Cursor()
|
|
||||||
// if err != nil {
|
|
||||||
// log.Printf("Cursorerror: %s", err)
|
|
||||||
// break
|
|
||||||
// } else {
|
|
||||||
// //log.Printf("NEXTCURSOR: %s", nextCursor)
|
|
||||||
// nextStr := fmt.Sprintf("%s", nextCursor)
|
|
||||||
// if cursorStr == nextStr {
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// cursorStr = nextStr
|
|
||||||
// query = query.Start(nextCursor)
|
|
||||||
// //cursorStr = nextCursor
|
|
||||||
// //break
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if len(apps) > maxLen {
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if len(apps) > 20 {
|
|
||||||
// log.Printf("[INFO] Setting %d apps in cache", len(apps))
|
|
||||||
// requestCache.Set(cacheKey, &apps, cache.DefaultExpiration)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// //var allworkflowapps []WorkflowApp
|
|
||||||
// //_, err := dbclient.GetAll(ctx, query, &allworkflowapps)
|
|
||||||
// //if err != nil {
|
|
||||||
// // if strings.Contains(fmt.Sprintf("%s", err), "ResourceExhausted") {
|
|
||||||
// // //datastore.NewQuery("workflowapp").Limit(30).Order("-edited")
|
|
||||||
// // query = datastore.NewQuery("workflowapp").Order("-edited").Limit(25)
|
|
||||||
// // //q := q.Limit(25)
|
|
||||||
// // _, err := dbclient.GetAll(ctx, query, &allworkflowapps)
|
|
||||||
// // if err != nil {
|
|
||||||
// // return []WorkflowApp{}, err
|
|
||||||
// // }
|
|
||||||
// // } else {
|
|
||||||
// // return []WorkflowApp{}, err
|
|
||||||
// // }
|
|
||||||
// //}
|
|
||||||
//
|
|
||||||
// return apps, nil
|
|
||||||
//}
|
|
||||||
|
|
||||||
//func shuffle.GetAllWorkflowAppAuth(ctx context.Context, OrgId string) ([]shuffle.AppAuthenticationStorage, error) {
|
|
||||||
// var allworkflowapps []AppAuthenticationStorage
|
|
||||||
// q := datastore.NewQuery("workflowappauth").Filter("org_id = ", OrgId)
|
|
||||||
//
|
|
||||||
// _, err := dbclient.GetAll(ctx, q, &allworkflowapps)
|
|
||||||
// if err != nil {
|
|
||||||
// return []AppAuthenticationStorage{}, err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return allworkflowapps, nil
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func getWorkflowAppAuthDatastore(ctx context.Context, id string) (*AppAuthenticationStorage, error) {
|
|
||||||
//
|
|
||||||
// key := datastore.NameKey("workflowappauth", id, nil)
|
|
||||||
// appAuth := &AppAuthenticationStorage{}
|
|
||||||
// // New struct, to not add body, author etc
|
|
||||||
// if err := dbclient.Get(ctx, key, appAuth); err != nil {
|
|
||||||
// return &AppAuthenticationStorage{}, err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return appAuth, nil
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func shuffle.SetWorkflowAppAuthDatastore(ctx context.Context, workflowappauth AppAuthenticationStorage, id string) error {
|
|
||||||
// timeNow := int64(time.Now().Unix())
|
|
||||||
// if workflowappauth.Created == 0 {
|
|
||||||
// workflowappauth.Created = timeNow
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// workflowappauth.Edited = timeNow
|
|
||||||
//
|
|
||||||
// key := datastore.NameKey("workflowappauth", id, nil)
|
|
||||||
//
|
|
||||||
// // New struct, to not add body, author etc
|
|
||||||
// if _, err := dbclient.Put(ctx, key, &workflowappauth); err != nil {
|
|
||||||
// log.Printf("Error adding workflow app auth: %s", err)
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return nil
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//// Hmm, so I guess this should use uuid :(
|
|
||||||
//// Consistency PLX
|
|
||||||
//func SetWorkflowAppDatastore(ctx context.Context, workflowapp WorkflowApp, id string) error {
|
|
||||||
// timeNow := int64(time.Now().Unix())
|
|
||||||
// if workflowapp.Created == 0 {
|
|
||||||
// workflowapp.Created = timeNow
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// workflowapp.Edited = timeNow
|
|
||||||
// key := datastore.NameKey("workflowapp", id, nil)
|
|
||||||
//
|
|
||||||
// // New struct, to not add body, author etc
|
|
||||||
// if _, err := dbclient.Put(ctx, key, &workflowapp); err != nil {
|
|
||||||
// log.Printf("Error adding workflow app: %s", err)
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return nil
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Starts a new webhook
|
// Starts a new webhook
|
||||||
func handleStopHook(resp http.ResponseWriter, request *http.Request) {
|
func handleStopHook(resp http.ResponseWriter, request *http.Request) {
|
||||||
cors := handleCors(resp, request)
|
cors := handleCors(resp, request)
|
||||||
@@ -5372,7 +5191,7 @@ func handleUserInput(trigger shuffle.Trigger, organizationId string, workflowId
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Should send email to %s during execution.", email)
|
log.Printf("[INFO] Should send email to %s during execution.", email)
|
||||||
}
|
}
|
||||||
if strings.Contains(triggerType, "sms") {
|
if strings.Contains(triggerType, "sms") {
|
||||||
action := shuffle.CloudSyncJob{
|
action := shuffle.CloudSyncJob{
|
||||||
|
|||||||
@@ -1,13 +1,24 @@
|
|||||||
import React, {useState} from 'react';
|
import React, {useState} from 'react';
|
||||||
|
|
||||||
import {Typography, } from '@material-ui/core';
|
import { InputAdornment, Tooltip, TextField, CircularProgress, ButtonGroup, Button, Avatar, ListItemAvatar, Typography, List, ListItem, ListItemText} from '@material-ui/core';
|
||||||
|
import {FavoriteBorder as FavoriteBorderIcon} from '@material-ui/icons';
|
||||||
|
|
||||||
|
// Handles workflow updates on first open to highlight the issues of the workflow
|
||||||
|
// Variables
|
||||||
|
// Action (exists, missing fields)
|
||||||
|
// Action auth
|
||||||
|
// Triggers
|
||||||
|
//
|
||||||
|
// Specifically used for UNSAVED workflows only?
|
||||||
const Workflow = (props) => {
|
const Workflow = (props) => {
|
||||||
const { workflow, appAuthentication, apps } = props
|
const { globalUrl, theme, workflow, appAuthentication, setSelectedAction, setAuthenticationModalOpen, setSelectedApp, apps, selectedAction,setConfigureWorkflowModalOpen, saveWorkflow, newWebhook, submitSchedule, referenceUrl, isCloud, } = props
|
||||||
const [requiredActions, setRequiredActions] = React.useState([])
|
const [requiredActions, setRequiredActions] = React.useState([])
|
||||||
|
const [requiredVariables, setRequiredVariables] = React.useState([])
|
||||||
|
const [requiredTriggers, setRequiredTriggers] = React.useState([])
|
||||||
|
const [previousAuth, setPreviousAuth] = React.useState(appAuthentication)
|
||||||
const [firstLoad, setFirstLoad] = React.useState("")
|
const [firstLoad, setFirstLoad] = React.useState("")
|
||||||
|
var finished = false
|
||||||
// Rofl
|
|
||||||
if (workflow === undefined || workflow === null) {
|
if (workflow === undefined || workflow === null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -20,63 +31,349 @@ const Workflow = (props) => {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getApp = (actionId, appId) => {
|
||||||
|
fetch(globalUrl+"/api/v1/apps/"+appId+"/config?openapi=false", {
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
},
|
||||||
|
credentials: "include",
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
//alert.success("Successfully GOT app "+appId)
|
||||||
|
} else {
|
||||||
|
alert.error("Failed getting app")
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json()
|
||||||
|
})
|
||||||
|
.then((responseJson) => {
|
||||||
|
console.log("ACTION: ", responseJson)
|
||||||
|
if (responseJson.actions !== undefined && responseJson.actions !== null) {
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
alert.error(error.toString())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (firstLoad.length === 0 || firstLoad !== workflow.id) {
|
if (firstLoad.length === 0 || firstLoad !== workflow.id) {
|
||||||
|
if (finished) {
|
||||||
|
setConfigureWorkflowModalOpen(false)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
setFirstLoad(workflow.id)
|
setFirstLoad(workflow.id)
|
||||||
const newactions = []
|
const newactions = []
|
||||||
for (var key in workflow.actions) {
|
for (var key in workflow.actions) {
|
||||||
|
const action = workflow.actions[key]
|
||||||
var newaction = {
|
var newaction = {
|
||||||
"large_image": "",
|
"large_image": action.large_image,
|
||||||
"app_name": "",
|
"app_name": action.app_name,
|
||||||
"app_version": "",
|
"app_version": action.app_version,
|
||||||
|
"activation_done": false,
|
||||||
"must_activate": false,
|
"must_activate": false,
|
||||||
"must_authenticate": false,
|
"must_authenticate": false,
|
||||||
|
"auth_done": false,
|
||||||
"action_ids": [],
|
"action_ids": [],
|
||||||
|
"action": action,
|
||||||
|
"app": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
const action = workflow.actions[key]
|
const app = apps.find(app => app.name === action.app_name && (app.app_version === action.app_version || app.loop_versions.includes(action.app_version)))
|
||||||
console.log(action)
|
|
||||||
const app = apps.find(app => app.name === action.app_name && app.app_version === action.app_version)
|
|
||||||
if (app === undefined || app === null) {
|
if (app === undefined || app === null) {
|
||||||
console.log("COULDNT FIND APP - SEARCH BACKEND")
|
console.log("App not found!")
|
||||||
|
|
||||||
newaction.app_name = action.app_name
|
newaction.must_activate = true
|
||||||
newaction.app_version = action.app_version
|
|
||||||
} else {
|
} else {
|
||||||
newaction.app_name = app.name
|
|
||||||
newaction.app_version = app.app_version
|
|
||||||
|
|
||||||
console.log("APP: ", app)
|
|
||||||
if (action.authentication_id === "" && app.authentication.required === true) {
|
if (action.authentication_id === "" && app.authentication.required === true) {
|
||||||
console.log("Requires auth!")
|
|
||||||
newaction.must_authenticate = true
|
newaction.must_authenticate = true
|
||||||
newaction.action_ids.push(action.id)
|
newaction.action_ids.push(action.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
//newaction.app_name = action.app_name
|
newaction.app = app
|
||||||
//newaction.app_name = action.app_version
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.errors !== undefined && action.errors !== null && action.errors.length > 0) {
|
if (action.errors !== undefined && action.errors !== null && action.errors.length > 0) {
|
||||||
console.log("Has errors!")
|
console.log("Node has errors!: ", action.errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("NEWACTION: ", newaction)
|
if (newaction.must_authenticate) {
|
||||||
if (newaction.must_authenticate || newaction.must_activate) {
|
var authenticationOptions = []
|
||||||
newactions.push(newaction)
|
for (var key in appAuthentication) {
|
||||||
|
const auth = appAuthentication[key]
|
||||||
|
if (auth.app.name === app.name && auth.active) {
|
||||||
|
console.log("Found auth: ", auth)
|
||||||
|
authenticationOptions.push(auth)
|
||||||
|
newaction.authenticationId = auth.id
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("APPAUTH: ", app.authentication, action)
|
||||||
|
if (newaction.authenticationId === null || newaction.authenticationId === undefined || newaction.authenticationId.length === "") {
|
||||||
|
console.log("FAILED to authentication node!")
|
||||||
|
newactions.push(newaction)
|
||||||
|
} else {
|
||||||
|
console.log("Skipping node as it's already authenticated.")
|
||||||
|
newaction.authentication = authenticationOptions
|
||||||
|
workflow.actions[key] = newaction
|
||||||
|
}
|
||||||
|
} else if (newaction.must_activate) {
|
||||||
|
|
||||||
|
if (newactions.find(tmpaction => tmpaction.app_id === newaction.app_id && tmpaction.app_name === newaction.app_name) !== undefined) {
|
||||||
|
console.log("Action already found.")
|
||||||
|
} else {
|
||||||
|
newactions.push(newaction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (var key in workflow.workflow_variables) {
|
||||||
|
const variable = workflow.workflow_variables[key]
|
||||||
|
if (variable.value === undefined || variable.value === undefined || variable.value.length < 2) {
|
||||||
|
variable.value = ""
|
||||||
|
variable.index = key
|
||||||
|
requiredVariables.push(variable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var key in workflow.triggers) {
|
||||||
|
var trigger = workflow.triggers[key]
|
||||||
|
trigger.index = key
|
||||||
|
|
||||||
|
if (trigger.status === "running") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trigger.trigger_type === "SUBFLOW" || trigger.trigger_type === "USERINPUT") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
requiredTriggers.push(trigger)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requiredTriggers.length === 0 && requiredVariables.length === 0 && newactions.length === 0) {
|
||||||
|
setConfigureWorkflowModalOpen(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("VARIABLES: ", requiredVariables)
|
||||||
console.log("ACTIONS: ", newactions)
|
console.log("ACTIONS: ", newactions)
|
||||||
|
setRequiredTriggers(requiredTriggers)
|
||||||
|
setRequiredVariables(requiredVariables)
|
||||||
setRequiredActions(newactions)
|
setRequiredActions(newactions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("AUTH: ", appAuthentication)
|
||||||
|
if (appAuthentication.length !== previousAuth.length) {
|
||||||
|
console.log("APP AUTH CHANGED!")
|
||||||
|
var newactions = []
|
||||||
|
for (var actionkey in requiredActions) {
|
||||||
|
var newaction = requiredActions[actionkey]
|
||||||
|
const app = newaction.app
|
||||||
|
|
||||||
|
for (var key in appAuthentication) {
|
||||||
|
const auth = appAuthentication[key]
|
||||||
|
if (auth.app.name === app.name && auth.active) {
|
||||||
|
console.log("FOUND AUTH FOR: ", auth.app.name)
|
||||||
|
newaction.auth_done = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newactions.push(newaction)
|
||||||
|
}
|
||||||
|
|
||||||
|
setRequiredActions(newactions)
|
||||||
|
setPreviousAuth(appAuthentication)
|
||||||
|
// Set auth done to true
|
||||||
|
//"auth_done": false
|
||||||
|
}
|
||||||
|
|
||||||
|
const TriggerSection = (props) => {
|
||||||
|
const {trigger} = props
|
||||||
|
|
||||||
|
console.log(trigger)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar variant="rounded">
|
||||||
|
<img alt={trigger.label} src={trigger.large_image} style={{width: 50}} />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText
|
||||||
|
primary={trigger.name}
|
||||||
|
secondary={trigger.description}
|
||||||
|
style={{}}
|
||||||
|
/>
|
||||||
|
{trigger.trigger_type === "WEBHOOK" && trigger.status !== "running" ?
|
||||||
|
<Button disabled={trigger.status === "running"} color="primary" variant="contained" onClick={() => {
|
||||||
|
workflow.triggers[trigger.index].status = "running"
|
||||||
|
if (workflow.triggers[trigger.index].parameters === null) {
|
||||||
|
workflow.triggers[trigger.index].parameters = [
|
||||||
|
{"name": "url", "value": referenceUrl+"webhook_"+trigger.id},
|
||||||
|
{"name": "tmp", "value": "webhook_"+trigger.id},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
newWebhook(workflow.triggers[trigger.index])
|
||||||
|
saveWorkflow(workflow)
|
||||||
|
}}>
|
||||||
|
{trigger.status !== "running" ? "Start" : "Running"}
|
||||||
|
</Button>
|
||||||
|
:
|
||||||
|
trigger.trigger_type === "SCHEDULE" && trigger.status !== "running" ?
|
||||||
|
<Button disabled={trigger.status === "running"} color="primary" variant="contained" onClick={() => {
|
||||||
|
workflow.triggers[trigger.index].status = "running"
|
||||||
|
if (workflow.triggers[trigger.index].parameters === null) {
|
||||||
|
workflow.triggers[trigger.index].parameters = [
|
||||||
|
{"name": "cron", "value": isCloud ? "*/15 * * * *" : "120"},
|
||||||
|
{"name": "execution_argument", "value": '{"example": {"json": "is cool"}}'},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
submitSchedule(workflow.triggers[trigger.index], trigger.index)
|
||||||
|
saveWorkflow(workflow)
|
||||||
|
}}>
|
||||||
|
{trigger.status !== "running" ? "Start" : "Running"}
|
||||||
|
</Button>
|
||||||
|
:
|
||||||
|
null}
|
||||||
|
{/*
|
||||||
|
<ListItemText
|
||||||
|
primary={
|
||||||
|
<TextField
|
||||||
|
style={{backgroundColor: theme.palette.inputColor, borderRadius: 5,}}
|
||||||
|
InputProps={{
|
||||||
|
style:{
|
||||||
|
color: "white",
|
||||||
|
minHeight: 50,
|
||||||
|
marginLeft: 5,
|
||||||
|
maxWidth: "95%",
|
||||||
|
fontSize: "1em",
|
||||||
|
},
|
||||||
|
endAdornment: (
|
||||||
|
<InputAdornment position="end">
|
||||||
|
</InputAdornment>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
fullWidth
|
||||||
|
color="primary"
|
||||||
|
type={"text"}
|
||||||
|
placeholder={`New value for ${trigger.name}`}
|
||||||
|
onChange={(event) => {
|
||||||
|
console.log("NEW VALUE ON INDEX", trigger.value)
|
||||||
|
}}
|
||||||
|
onBlur={(event) => {
|
||||||
|
//workflow.variables[variable.index] = event.target.value
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
style={{}}
|
||||||
|
/>
|
||||||
|
*/}
|
||||||
|
</ListItem>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const VariableSection = (props) => {
|
||||||
|
const {variable} = props
|
||||||
|
|
||||||
|
//<Typography variant="body2">Name: {variable.name} - {variable.value}. </Typography>
|
||||||
|
return (
|
||||||
|
<ListItem>
|
||||||
|
<ListItemAvatar>
|
||||||
|
<Avatar>
|
||||||
|
<FavoriteBorderIcon />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText
|
||||||
|
primary={variable.name}
|
||||||
|
secondary={variable.description}
|
||||||
|
style={{}}
|
||||||
|
/>
|
||||||
|
<ListItemText
|
||||||
|
primary={
|
||||||
|
<TextField
|
||||||
|
style={{backgroundColor: theme.palette.inputColor, borderRadius: 5,}}
|
||||||
|
InputProps={{
|
||||||
|
style:{
|
||||||
|
color: "white",
|
||||||
|
minHeight: 50,
|
||||||
|
marginLeft: 5,
|
||||||
|
maxWidth: "95%",
|
||||||
|
fontSize: "1em",
|
||||||
|
},
|
||||||
|
endAdornment: (
|
||||||
|
<InputAdornment position="end">
|
||||||
|
</InputAdornment>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
fullWidth
|
||||||
|
color="primary"
|
||||||
|
type={"text"}
|
||||||
|
placeholder={`New value for ${variable.name}`}
|
||||||
|
onChange={(event) => {
|
||||||
|
console.log("NEW VALUE ON INDEX", variable.index, variable.value)
|
||||||
|
}}
|
||||||
|
onBlur={(event) => {
|
||||||
|
workflow.workflow_variables[variable.index].value = event.target.value
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
style={{}}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const AppSection = (props) => {
|
const AppSection = (props) => {
|
||||||
const {action} = props
|
const {action} = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<ListItem>
|
||||||
<Typography variant="body2">Name: {action.app_name}:{action.app_version}. </Typography>
|
<ListItemAvatar>
|
||||||
</div>
|
<Avatar variant="rounded">
|
||||||
|
<img alt={action.app_name} src={action.large_image} style={{width: 50}} />
|
||||||
|
</Avatar>
|
||||||
|
</ListItemAvatar>
|
||||||
|
<ListItemText
|
||||||
|
primary={action.app_name}
|
||||||
|
secondary={action.app_version}
|
||||||
|
style={{minWidth: 175, maxWidth: 175, marginLeft: 10}}
|
||||||
|
/>
|
||||||
|
{action.must_authenticate ?
|
||||||
|
action.auth_done ?
|
||||||
|
<div>
|
||||||
|
<Button color="primary" variant="outlined" onClick={() => {
|
||||||
|
}}>
|
||||||
|
Finished
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
selectedAction.app_name === action.app_name ?
|
||||||
|
<CircularProgress />
|
||||||
|
:
|
||||||
|
<Button color="primary" variant="contained" onClick={() => {
|
||||||
|
setSelectedAction(action.action)
|
||||||
|
setSelectedApp(action.app)
|
||||||
|
setAuthenticationModalOpen(true)
|
||||||
|
}}>
|
||||||
|
Authenticate
|
||||||
|
</Button>
|
||||||
|
:
|
||||||
|
null}
|
||||||
|
{action.must_activate ?
|
||||||
|
<Button color="primary" variant="contained" onClick={() => {
|
||||||
|
console.log("SHOULD ACTIVATE: ", action)
|
||||||
|
}}>
|
||||||
|
Activate
|
||||||
|
</Button>
|
||||||
|
: null}
|
||||||
|
</ListItem>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,12 +381,62 @@ const Workflow = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Typography variant="h6">Workflow: {workflow.id}</Typography>
|
<Typography variant="h6">{workflow.name}</Typography>
|
||||||
{requiredActions.map((data, index) => {
|
<Typography variant="body1" color="textSecondary">
|
||||||
return (
|
The following configuration makes the workflow ready immediately.
|
||||||
<AppSection key={index} action={data} />
|
</Typography>
|
||||||
)
|
{requiredActions.length > 0 ?
|
||||||
})}
|
<span>
|
||||||
|
<Typography variant="body1" style={{marginTop: 10}}>Actions</Typography>
|
||||||
|
<List>
|
||||||
|
{requiredActions.map((data, index) => {
|
||||||
|
return (
|
||||||
|
<AppSection key={index} action={data} />
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</List>
|
||||||
|
</span>
|
||||||
|
: null}
|
||||||
|
|
||||||
|
{requiredVariables.length > 0 ?
|
||||||
|
<span>
|
||||||
|
<Typography variant="body1" style={{marginTop: 10}}>Variables</Typography>
|
||||||
|
{requiredVariables.map((data, index) => {
|
||||||
|
return (
|
||||||
|
<VariableSection key={index} variable={data} />
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
: null}
|
||||||
|
|
||||||
|
|
||||||
|
{requiredTriggers.length > 0 ?
|
||||||
|
<span>
|
||||||
|
<Typography variant="body1" style={{marginTop: 10}}>Triggers</Typography>
|
||||||
|
{requiredTriggers.map((data, index) => {
|
||||||
|
return (
|
||||||
|
<TriggerSection key={index} trigger={data} />
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
: null }
|
||||||
|
<div style={{textAlign: "center", display: "flex", marginTop: 20, }}>
|
||||||
|
<ButtonGroup style={{margin: "auto",}}>
|
||||||
|
<Button color="primary" variant={"outlined"} style={{
|
||||||
|
}} onClick={() => {
|
||||||
|
setConfigureWorkflowModalOpen(false)
|
||||||
|
}}>
|
||||||
|
Skip
|
||||||
|
</Button>
|
||||||
|
<Button color="primary" variant={"contained"} style={{
|
||||||
|
}} onClick={() => {
|
||||||
|
saveWorkflow(workflow)
|
||||||
|
window.location.reload()
|
||||||
|
}}>
|
||||||
|
Finish setup
|
||||||
|
</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -459,9 +459,9 @@ const Admin = (props) => {
|
|||||||
|
|
||||||
|
|
||||||
// FIXME: Set up features
|
// FIXME: Set up features
|
||||||
Object.keys(responseJson.sync_features).map(function(key, index) {
|
//Object.keys(responseJson.sync_features).map(function(key, index) {
|
||||||
//console.log(responseJson.sync_features[key])
|
// //console.log(responseJson.sync_features[key])
|
||||||
})
|
//})
|
||||||
|
|
||||||
//setOrgName(responseJson.name)
|
//setOrgName(responseJson.name)
|
||||||
//setOrgDescription(responseJson.description)
|
//setOrgDescription(responseJson.description)
|
||||||
@@ -849,7 +849,6 @@ const Admin = (props) => {
|
|||||||
return response.json()
|
return response.json()
|
||||||
})
|
})
|
||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
console.log(responseJson)
|
|
||||||
setSchedules(responseJson)
|
setSchedules(responseJson)
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
@@ -988,34 +987,45 @@ const Admin = (props) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const views = {
|
||||||
|
0: "organization",
|
||||||
|
1: "users",
|
||||||
|
2: "app_auth",
|
||||||
|
3: "files",
|
||||||
|
4: "schedules",
|
||||||
|
5: "environments",
|
||||||
|
6: "categories",
|
||||||
|
}
|
||||||
const setConfig = (event, newValue) => {
|
const setConfig = (event, newValue) => {
|
||||||
|
console.log("Value: ", newValue)
|
||||||
|
|
||||||
|
setCurTab(parseInt(newValue))
|
||||||
if (newValue === 1) {
|
if (newValue === 1) {
|
||||||
|
document.title = "Shuffle - admin - users"
|
||||||
getUsers()
|
getUsers()
|
||||||
} else if (newValue === 2) {
|
} else if (newValue === 2) {
|
||||||
|
document.title = "Shuffle - admin - app authentication"
|
||||||
getAppAuthentication()
|
getAppAuthentication()
|
||||||
} else if (newValue === 3) {
|
} else if (newValue === 3) {
|
||||||
|
document.title = "Shuffle - admin - files"
|
||||||
getFiles()
|
getFiles()
|
||||||
} else if (newValue === 4) {
|
} else if (newValue === 4) {
|
||||||
|
document.title = "Shuffle - admin - schedules"
|
||||||
getSchedules()
|
getSchedules()
|
||||||
} else if (newValue === 5) {
|
} else if (newValue === 5) {
|
||||||
|
document.title = "Shuffle - admin - environments"
|
||||||
getEnvironments()
|
getEnvironments()
|
||||||
} else if (newValue === 6) {
|
} else if (newValue === 6) {
|
||||||
|
document.title = "Shuffle - admin - orgs"
|
||||||
getOrgs()
|
getOrgs()
|
||||||
|
} else {
|
||||||
|
document.title = "Shuffle - admin"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newValue === 6) {
|
if (newValue === 6) {
|
||||||
console.log("Should get apps for categories.")
|
console.log("Should get apps for categories.")
|
||||||
}
|
}
|
||||||
|
|
||||||
const views = {
|
|
||||||
0: "organization",
|
|
||||||
1: "users",
|
|
||||||
2: "app_auth",
|
|
||||||
3: "environments",
|
|
||||||
4: "schedules",
|
|
||||||
5: "files",
|
|
||||||
6: "categories",
|
|
||||||
}
|
|
||||||
|
|
||||||
//var theURL = window.location.pathname
|
//var theURL = window.location.pathname
|
||||||
//FIXME: Add url edits
|
//FIXME: Add url edits
|
||||||
@@ -1027,33 +1037,21 @@ const Admin = (props) => {
|
|||||||
//window.location.pathame = newpath
|
//window.location.pathame = newpath
|
||||||
|
|
||||||
setModalUser({})
|
setModalUser({})
|
||||||
setCurTab(newValue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (firstRequest) {
|
if (firstRequest) {
|
||||||
setFirstRequest(false)
|
setFirstRequest(false)
|
||||||
|
document.title = "Shuffle - admin"
|
||||||
if (!isCloud) {
|
if (!isCloud) {
|
||||||
getUsers()
|
getUsers()
|
||||||
} else {
|
} else {
|
||||||
getSettings()
|
getSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
const views = {
|
|
||||||
"organization": 0,
|
|
||||||
"users": 1,
|
|
||||||
"app_auth": 2,
|
|
||||||
"environments": 3,
|
|
||||||
"schedules": 4,
|
|
||||||
"files": 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.match.params.key !== undefined) {
|
if (props.match.params.key !== undefined) {
|
||||||
const tmpitem = views[props.match.params.key]
|
//const tmpitem = views[props.match.params.key]
|
||||||
if (tmpitem !== undefined) {
|
setConfig("", props.match.params.key)
|
||||||
//setCurTab(tmpitem)
|
|
||||||
setConfig("", tmpitem)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2092,11 +2090,13 @@ const Admin = (props) => {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
:
|
:
|
||||||
<Tooltip title={"Go to workflow"} style={{}} aria-label={"Download"}>
|
<Tooltip title={"Go to workflow"} style={{}} aria-label={"Download"}>
|
||||||
<a style={{textDecoration: "none", color: "#f85a3e"}} href={`/workflows/${file.workflow_id}`} target="_blank">
|
<span>
|
||||||
<IconButton disabled={file.workflow_id === "global"}>
|
<a style={{textDecoration: "none", color: "#f85a3e"}} href={`/workflows/${file.workflow_id}`} target="_blank">
|
||||||
<OpenInNewIcon style={{color: file.workflow_id !== "global" ? "white" : "grey",}} />
|
<IconButton disabled={file.workflow_id === "global"}>
|
||||||
</IconButton>
|
<OpenInNewIcon style={{color: file.workflow_id !== "global" ? "white" : "grey",}} />
|
||||||
</a>
|
</IconButton>
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
}
|
}
|
||||||
style={{minWidth: 100, maxWidth: 100, overflow: "hidden"}}
|
style={{minWidth: 100, maxWidth: 100, overflow: "hidden"}}
|
||||||
@@ -2116,11 +2116,13 @@ const Admin = (props) => {
|
|||||||
<ListItemText
|
<ListItemText
|
||||||
primary=
|
primary=
|
||||||
<Tooltip title={"Download file"} style={{}} aria-label={"Download"}>
|
<Tooltip title={"Download file"} style={{}} aria-label={"Download"}>
|
||||||
<IconButton disabled={file.status !== "active"} onClick={() => {
|
<span>
|
||||||
downloadFile(file)
|
<IconButton disabled={file.status !== "active"} onClick={() => {
|
||||||
}}>
|
downloadFile(file)
|
||||||
<CloudDownloadIcon style={{color: file.status === "active" ? "white" : "grey",}} />
|
}}>
|
||||||
</IconButton>
|
<CloudDownloadIcon style={{color: file.status === "active" ? "white" : "grey",}} />
|
||||||
|
</IconButton>
|
||||||
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
style={{minWidth: 75, maxWidth: 75, overflow: "hidden"}}
|
style={{minWidth: 75, maxWidth: 75, overflow: "hidden"}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ const AngularWorkflow = (props) => {
|
|||||||
const [rightSideBarOpen, setRightSideBarOpen] = React.useState(false)
|
const [rightSideBarOpen, setRightSideBarOpen] = React.useState(false)
|
||||||
const [showSkippedActions, setShowSkippedActions] = React.useState(false)
|
const [showSkippedActions, setShowSkippedActions] = React.useState(false)
|
||||||
const [lastExecution, setLastExecution] = React.useState("")
|
const [lastExecution, setLastExecution] = React.useState("")
|
||||||
const [configureWorkflowModalOpen, setConfigureWorkflowModalOpen] = React.useState(false)
|
const [configureWorkflowModalOpen, setConfigureWorkflowModalOpen] = React.useState(true)
|
||||||
const [curpath, setCurpath] = useState(typeof window === 'undefined' || window.location === undefined ? "" : window.location.pathname)
|
const [curpath, setCurpath] = useState(typeof window === 'undefined' || window.location === undefined ? "" : window.location.pathname)
|
||||||
|
|
||||||
// 0 = normal, 1 = just done, 2 = normal
|
// 0 = normal, 1 = just done, 2 = normal
|
||||||
@@ -707,8 +707,10 @@ const AngularWorkflow = (props) => {
|
|||||||
newBranches.push(parsedElement)
|
newBranches.push(parsedElement)
|
||||||
} else {
|
} else {
|
||||||
if (type === "ACTION") {
|
if (type === "ACTION") {
|
||||||
// FIXME - check whether position is new to not fuck up params etc.
|
const cyelement = cyelements[key].data()
|
||||||
var curworkflowAction = useworkflow.actions.find(a => a.id === cyelements[key].data()["id"])
|
const elementid = cyelement.id === undefined || cyelement.id === null ? cyelement["_id"] : cyelement.id
|
||||||
|
|
||||||
|
var curworkflowAction = useworkflow.actions.find(a => a !== undefined && (a["id"] === elementid || a["_id"] === elementid))
|
||||||
if (curworkflowAction === undefined) {
|
if (curworkflowAction === undefined) {
|
||||||
curworkflowAction = cyelements[key].data()
|
curworkflowAction = cyelements[key].data()
|
||||||
}
|
}
|
||||||
@@ -1114,13 +1116,13 @@ const AngularWorkflow = (props) => {
|
|||||||
|
|
||||||
const getWorkflow = () => {
|
const getWorkflow = () => {
|
||||||
fetch(globalUrl+"/api/v1/workflows/"+props.match.params.key, {
|
fetch(globalUrl+"/api/v1/workflows/"+props.match.params.key, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
},
|
},
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
console.log("Status not 200 for workflows :O!")
|
console.log("Status not 200 for workflows :O!")
|
||||||
@@ -1146,6 +1148,12 @@ const AngularWorkflow = (props) => {
|
|||||||
|
|
||||||
setWorkflow(responseJson)
|
setWorkflow(responseJson)
|
||||||
setWorkflowDone(true)
|
setWorkflowDone(true)
|
||||||
|
|
||||||
|
//console.log(responseJson)
|
||||||
|
// Add error checks
|
||||||
|
if (!responseJson.public && (!responseJson.previously_saved || (!responseJson.is_valid || (responseJson.errors !== undefined || responseJson.errors !== null || responseJson.errors !== responseJson.errors.length > 0)))) {
|
||||||
|
setConfigureWorkflowModalOpen(true)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
alert.error(error.toString())
|
alert.error(error.toString())
|
||||||
@@ -1289,11 +1297,6 @@ const AngularWorkflow = (props) => {
|
|||||||
//console.log("BRANCHES: ", branch)
|
//console.log("BRANCHES: ", branch)
|
||||||
|
|
||||||
if (data.type === "ACTION") {
|
if (data.type === "ACTION") {
|
||||||
|
|
||||||
|
|
||||||
// FIXME - unselect
|
|
||||||
//console.log(cy.elements('[_id!="${data._id}"]`))
|
|
||||||
// Does it choose the wrong action?
|
|
||||||
var curaction = workflow.actions.find(a => a.id === data.id)
|
var curaction = workflow.actions.find(a => a.id === data.id)
|
||||||
if (!curaction || curaction === undefined) {
|
if (!curaction || curaction === undefined) {
|
||||||
//event.target.unselect()
|
//event.target.unselect()
|
||||||
@@ -1301,15 +1304,27 @@ const AngularWorkflow = (props) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//console.log(apps)
|
||||||
console.log(apps)
|
|
||||||
const curapp = apps.find(a => a.name === curaction.app_name && (a.app_version === curaction.app_version || a.loop_versions.includes(curaction.app_version)))
|
const curapp = apps.find(a => a.name === curaction.app_name && (a.app_version === curaction.app_version || a.loop_versions.includes(curaction.app_version)))
|
||||||
if (!curapp || curapp === undefined) {
|
if (!curapp || curapp === undefined) {
|
||||||
alert.error(`App ${curaction.app_name}:${curaction.app_version} not found. Is it activated?`)
|
alert.error(`App ${curaction.app_name}:${curaction.app_version} not found. Is it activated?`)
|
||||||
|
|
||||||
|
const tmpapp = {
|
||||||
|
name: curaction.app_name,
|
||||||
|
app_name: curaction.app_name,
|
||||||
|
app_version: curaction.app_version,
|
||||||
|
id: curaction.app_id,
|
||||||
|
actions: [curaction],
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(tmpapp)
|
||||||
|
console.log(curaction)
|
||||||
|
setSelectedApp(tmpapp)
|
||||||
|
setSelectedAction(curaction)
|
||||||
//return
|
//return
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
console.log("AUTHENTICATION: ", curapp.authentication)
|
//console.log("AUTHENTICATION: ", curapp.authentication)
|
||||||
setRequiresAuthentication(curapp.authentication.required && curapp.authentication.parameters !== undefined && curapp.authentication.parameters !== null)
|
setRequiresAuthentication(curapp.authentication.required && curapp.authentication.parameters !== undefined && curapp.authentication.parameters !== null)
|
||||||
if (curapp.authentication.required) {
|
if (curapp.authentication.required) {
|
||||||
// Setup auth here :)
|
// Setup auth here :)
|
||||||
@@ -2147,6 +2162,7 @@ const AngularWorkflow = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const deleteVariable = (variableName) => {
|
const deleteVariable = (variableName) => {
|
||||||
|
console.log("Delete:" ,variableName)
|
||||||
workflow.workflow_variables = workflow.workflow_variables.filter(data => data.name !== variableName)
|
workflow.workflow_variables = workflow.workflow_variables.filter(data => data.name !== variableName)
|
||||||
setWorkflow(workflow)
|
setWorkflow(workflow)
|
||||||
}
|
}
|
||||||
@@ -2208,7 +2224,7 @@ const AngularWorkflow = (props) => {
|
|||||||
setOpen(false)
|
setOpen(false)
|
||||||
setAnchorEl(null)
|
setAnchorEl(null)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
||||||
<MenuItem style={{backgroundColor: inputColor, color: "white"}} onClick={() => {
|
<MenuItem style={{backgroundColor: inputColor, color: "white"}} onClick={() => {
|
||||||
setOpen(false)
|
setOpen(false)
|
||||||
@@ -4232,8 +4248,6 @@ const AngularWorkflow = (props) => {
|
|||||||
return response.json()
|
return response.json()
|
||||||
})
|
})
|
||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
console.log(responseJson)
|
|
||||||
|
|
||||||
if (setApp && responseJson.actions !== undefined && responseJson.actions !== null) {
|
if (setApp && responseJson.actions !== undefined && responseJson.actions !== null) {
|
||||||
if (selectedApp.versions !== undefined && selectedApp.versions !== null) {
|
if (selectedApp.versions !== undefined && selectedApp.versions !== null) {
|
||||||
responseJson.versions = selectedApp.versions
|
responseJson.versions = selectedApp.versions
|
||||||
@@ -4244,17 +4258,14 @@ const AngularWorkflow = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var foundAction = responseJson.actions.find(action => action.name === selectedAction.name)
|
var foundAction = responseJson.actions.find(action => action.name === selectedAction.name)
|
||||||
console.log("Old : ", selectedAction)
|
|
||||||
console.log("Found: ", foundAction)
|
|
||||||
if (foundAction !== null && foundAction !== undefined) {
|
if (foundAction !== null && foundAction !== undefined) {
|
||||||
for (var paramkey in foundAction.parameters) {
|
for (var paramkey in foundAction.parameters) {
|
||||||
const param = foundAction.parameters[paramkey]
|
const param = foundAction.parameters[paramkey]
|
||||||
|
|
||||||
const foundParam = selectedAction.parameters.find(item => item.name === param.name)
|
const foundParam = selectedAction.parameters.find(item => item.name === param.name)
|
||||||
if (foundParam === undefined) {
|
if (foundParam === undefined) {
|
||||||
console.log("COULDNT find Param: ", param)
|
//console.log("COULDNT find Param: ", param)
|
||||||
} else {
|
} else {
|
||||||
console.log("FoundP: ", foundParam)
|
|
||||||
foundAction.parameters[paramkey] = foundParam
|
foundAction.parameters[paramkey] = foundParam
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7878,9 +7889,15 @@ const AngularWorkflow = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("Action: ", selectedAction)
|
||||||
selectedAction.authentication_id = authenticationOption.id
|
selectedAction.authentication_id = authenticationOption.id
|
||||||
selectedAction.selectedAuthentication = authenticationOption
|
selectedAction.selectedAuthentication = authenticationOption
|
||||||
selectedAction.authentication.push(authenticationOption)
|
if (selectedAction.authentication === undefined || selectedAction.authentication === null) {
|
||||||
|
selectedAction.authentication = [authenticationOption]
|
||||||
|
} else {
|
||||||
|
selectedAction.authentication.push(authenticationOption)
|
||||||
|
}
|
||||||
|
|
||||||
setSelectedAction(selectedAction)
|
setSelectedAction(selectedAction)
|
||||||
|
|
||||||
var newAuthOption = JSON.parse(JSON.stringify(authenticationOption))
|
var newAuthOption = JSON.parse(JSON.stringify(authenticationOption))
|
||||||
@@ -7898,6 +7915,12 @@ const AngularWorkflow = (props) => {
|
|||||||
setNewAppAuth(newAuthOption)
|
setNewAppAuth(newAuthOption)
|
||||||
//appAuthentication.push(newAuthOption)
|
//appAuthentication.push(newAuthOption)
|
||||||
//setAppAuthentication(appAuthentication)
|
//setAppAuthentication(appAuthentication)
|
||||||
|
//
|
||||||
|
|
||||||
|
if (configureWorkflowModalOpen) {
|
||||||
|
setSelectedAction({})
|
||||||
|
}
|
||||||
|
|
||||||
setUpdate(authenticationOption.id)
|
setUpdate(authenticationOption.id)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -8024,18 +8047,23 @@ const AngularWorkflow = (props) => {
|
|||||||
<Dialog
|
<Dialog
|
||||||
open={configureWorkflowModalOpen}
|
open={configureWorkflowModalOpen}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setConfigureWorkflowModalOpen(false)
|
//setConfigureWorkflowModalOpen(false)
|
||||||
}}
|
}}
|
||||||
PaperProps={{
|
PaperProps={{
|
||||||
style: {
|
style: {
|
||||||
backgroundColor: surfaceColor,
|
backgroundColor: surfaceColor,
|
||||||
color: "white",
|
color: "white",
|
||||||
minWidth: 600,
|
minWidth: 600,
|
||||||
padding: 15,
|
padding: 50,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ConfigureWorkflow workflow={workflow} appAuthentication={appAuthentication} apps={apps} />
|
<IconButton style={{zIndex: 5000, position: "absolute", top: 14, right: 14, color: "grey"}} onClick={() => {
|
||||||
|
setConfigureWorkflowModalOpen(false)
|
||||||
|
}}>
|
||||||
|
<CloseIcon />
|
||||||
|
</IconButton>
|
||||||
|
<ConfigureWorkflow theme={theme} globalUrl={globalUrl} workflow={workflow} setSelectedAction={setSelectedAction} setSelectedApp={setSelectedApp} setAuthenticationModalOpen={setAuthenticationModalOpen} appAuthentication={appAuthentication} selectedAction={selectedAction} apps={apps} setConfigureWorkflowModalOpen={setConfigureWorkflowModalOpen} saveWorkflow={saveWorkflow} newWebhook={newWebhook} submitSchedule={submitSchedule} referenceUrl={referenceUrl} isCloud={isCloud} />
|
||||||
</Dialog>
|
</Dialog>
|
||||||
: null
|
: null
|
||||||
|
|
||||||
@@ -8046,6 +8074,10 @@ const AngularWorkflow = (props) => {
|
|||||||
open={authenticationModalOpen}
|
open={authenticationModalOpen}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
//setAuthenticationModalOpen(false)
|
//setAuthenticationModalOpen(false)
|
||||||
|
//
|
||||||
|
if (configureWorkflowModalOpen) {
|
||||||
|
setSelectedAction({})
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
PaperProps={{
|
PaperProps={{
|
||||||
style: {
|
style: {
|
||||||
@@ -8056,6 +8088,14 @@ const AngularWorkflow = (props) => {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<IconButton style={{zIndex: 5000, position: "absolute", top: 14, right: 14, color: "grey"}} onClick={() => {
|
||||||
|
setAuthenticationModalOpen(false)
|
||||||
|
if (configureWorkflowModalOpen) {
|
||||||
|
setSelectedAction({})
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<CloseIcon />
|
||||||
|
</IconButton>
|
||||||
<DialogTitle><div style={{color: "white"}}>Authentication for {selectedApp.name}</div></DialogTitle>
|
<DialogTitle><div style={{color: "white"}}>Authentication for {selectedApp.name}</div></DialogTitle>
|
||||||
<AuthenticationData app={selectedApp} />
|
<AuthenticationData app={selectedApp} />
|
||||||
</Dialog> : null
|
</Dialog> : null
|
||||||
|
|||||||
@@ -585,7 +585,7 @@ const Workflows = (props) => {
|
|||||||
|
|
||||||
for (var subkey in data.actions[key].parameters) {
|
for (var subkey in data.actions[key].parameters) {
|
||||||
const param = data.actions[key].parameters[subkey]
|
const param = data.actions[key].parameters[subkey]
|
||||||
if (param.name.includes("key") || param.name.includes("user") || param.name.includes("pass") || param.name.includes("api") || param.name.includes("auth") || param.name.includes("secret")) {
|
if (param.name.includes("key") || param.name.includes("user") || param.name.includes("pass") || param.name.includes("api") || param.name.includes("auth") || param.name.includes("secret") || param.name.includes("domain") || param.name.includes("url")) {
|
||||||
// FIXME: This may be a vuln if api-keys are generated that start with $
|
// FIXME: This may be a vuln if api-keys are generated that start with $
|
||||||
if (param.value.startsWith("$")) {
|
if (param.value.startsWith("$")) {
|
||||||
console.log("Skipping field, as it's referencing a variable")
|
console.log("Skipping field, as it's referencing a variable")
|
||||||
@@ -645,8 +645,8 @@ const Workflows = (props) => {
|
|||||||
let exportFileDefaultName = data.name+'.json';
|
let exportFileDefaultName = data.name+'.json';
|
||||||
data = sanitizeWorkflow(data)
|
data = sanitizeWorkflow(data)
|
||||||
|
|
||||||
//console.log("EXPORT: ", data)
|
// Add correct ID's for triggers
|
||||||
//return
|
// Add mag
|
||||||
|
|
||||||
let dataStr = JSON.stringify(data)
|
let dataStr = JSON.stringify(data)
|
||||||
let dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr);
|
let dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr);
|
||||||
|
|||||||
Reference in New Issue
Block a user