#285: Made apps send available versions and mapped them in workflow view
This commit is contained in:
@@ -3,6 +3,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
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -10,14 +11,15 @@ require (
|
|||||||
cloud.google.com/go/datastore v1.4.0
|
cloud.google.com/go/datastore v1.4.0
|
||||||
cloud.google.com/go/pubsub v1.3.1
|
cloud.google.com/go/pubsub v1.3.1
|
||||||
cloud.google.com/go/storage v1.12.0
|
cloud.google.com/go/storage v1.12.0
|
||||||
|
github.com/Masterminds/semver v1.5.0 // indirect
|
||||||
github.com/Microsoft/go-winio v0.4.14 // indirect
|
github.com/Microsoft/go-winio v0.4.14 // indirect
|
||||||
github.com/basgys/goxml2json v1.1.0
|
github.com/basgys/goxml2json v1.1.0
|
||||||
github.com/frikky/kin-openapi v0.38.0
|
|
||||||
github.com/carlescere/scheduler v0.0.0-20170109141437-ee74d2f83d82
|
github.com/carlescere/scheduler v0.0.0-20170109141437-ee74d2f83d82
|
||||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||||
github.com/docker/docker v1.13.1
|
github.com/docker/docker v1.13.1
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/docker/go-units v0.4.0 // indirect
|
github.com/docker/go-units v0.4.0 // indirect
|
||||||
|
github.com/frikky/kin-openapi v0.38.0
|
||||||
github.com/frikky/shuffle-shared v0.0.23
|
github.com/frikky/shuffle-shared v0.0.23
|
||||||
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
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
|
|||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
|
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||||
|
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||||
|
|||||||
@@ -6189,11 +6189,11 @@ func initHandlers() {
|
|||||||
// From here down isnt checked for org specific
|
// From here down isnt checked for org specific
|
||||||
r.HandleFunc("/api/v1/apps/{appId}", shuffle.UpdateWorkflowAppConfig).Methods("PATCH", "OPTIONS")
|
r.HandleFunc("/api/v1/apps/{appId}", shuffle.UpdateWorkflowAppConfig).Methods("PATCH", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/apps/{appId}", shuffle.DeleteWorkflowApp).Methods("DELETE", "OPTIONS")
|
r.HandleFunc("/api/v1/apps/{appId}", shuffle.DeleteWorkflowApp).Methods("DELETE", "OPTIONS")
|
||||||
|
r.HandleFunc("/api/v1/apps/{appId}/config", shuffle.GetWorkflowAppConfig).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/apps/run_hotload", handleAppHotloadRequest).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/apps/run_hotload", handleAppHotloadRequest).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/apps/get_existing", loadSpecificApps).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/apps/get_existing", loadSpecificApps).Methods("POST", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/apps/download_remote", loadSpecificApps).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/apps/download_remote", loadSpecificApps).Methods("POST", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/apps/validate", validateAppInput).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/apps/validate", validateAppInput).Methods("POST", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/apps/{appId}/config", getWorkflowAppConfig).Methods("GET", "OPTIONS")
|
|
||||||
r.HandleFunc("/api/v1/apps", getWorkflowApps).Methods("GET", "OPTIONS")
|
r.HandleFunc("/api/v1/apps", getWorkflowApps).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/apps", setNewWorkflowApp).Methods("PUT", "OPTIONS")
|
r.HandleFunc("/api/v1/apps", setNewWorkflowApp).Methods("PUT", "OPTIONS")
|
||||||
r.HandleFunc("/api/v1/apps/search", getSpecificApps).Methods("POST", "OPTIONS")
|
r.HandleFunc("/api/v1/apps/search", getSpecificApps).Methods("POST", "OPTIONS")
|
||||||
|
|||||||
@@ -3396,113 +3396,6 @@ func deleteWorkflowApp(resp http.ResponseWriter, request *http.Request) {
|
|||||||
resp.Write([]byte(`{"success": true}`))
|
resp.Write([]byte(`{"success": true}`))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getWorkflowAppConfig(resp http.ResponseWriter, request *http.Request) {
|
|
||||||
cors := handleCors(resp, request)
|
|
||||||
if cors {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
location := strings.Split(request.URL.String(), "/")
|
|
||||||
var fileId string
|
|
||||||
if location[1] == "api" {
|
|
||||||
if len(location) <= 4 {
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fileId = location[4]
|
|
||||||
}
|
|
||||||
|
|
||||||
app, err := shuffle.GetApp(ctx, fileId, shuffle.User{})
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("[WARNING] Error getting app %s (app config): %s", fileId, err)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false, "reason": "App doesn't exist"}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//if IsValid bool `json:"is_valid" yaml:"is_valid" required:true datastore:"is_valid"`
|
|
||||||
// Sharing bool `json:"sharing" yaml:"sharing" required:false datastore:"sharing"`
|
|
||||||
//log.Printf("Sharing: %s", app.Sharing)
|
|
||||||
//log.Printf("Generated: %s", app.Generated)
|
|
||||||
//log.Printf("Downloaded: %s", app.Downloaded)
|
|
||||||
|
|
||||||
// FIXME - Handle sharing and such PROPERLY
|
|
||||||
if app.Sharing && app.Generated {
|
|
||||||
log.Printf("CAN SHARE APP!")
|
|
||||||
parsedApi, err := getOpenApiDatastore(ctx, fileId)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("[WARNING] OpenApi doesn't exist for: %s - err: %s", fileId, err)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(parsedApi.ID) > 0 {
|
|
||||||
parsedApi.Success = true
|
|
||||||
} else {
|
|
||||||
parsedApi.Success = false
|
|
||||||
}
|
|
||||||
|
|
||||||
//log.Printf("PARSEDAPI: %#v", parsedApi)
|
|
||||||
data, err := json.Marshal(parsedApi)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("[WARNING] Error parsing api json: %s", err)
|
|
||||||
resp.WriteHeader(422)
|
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed marshalling new parsed swagger: %s"}`, err)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.WriteHeader(200)
|
|
||||||
resp.Write(data)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user, userErr := shuffle.HandleApiAuthentication(resp, request)
|
|
||||||
if userErr != nil {
|
|
||||||
log.Printf("[WARNING] Api authentication failed in get app: %s", userErr)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if user.Id != app.Owner {
|
|
||||||
log.Printf("[WARNING] Wrong user (%s) for app %s", user.Username, app.Name)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("[INFO] Getting app %s (OpenAPI)", fileId)
|
|
||||||
parsedApi, err := getOpenApiDatastore(ctx, fileId)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("OpenApi doesn't exist for: %s - err: %s", fileId, err)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//log.Printf("Parsed API: %#v", parsedApi)
|
|
||||||
if len(parsedApi.ID) > 0 {
|
|
||||||
parsedApi.Success = true
|
|
||||||
} else {
|
|
||||||
parsedApi.Success = false
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := json.Marshal(parsedApi)
|
|
||||||
if err != nil {
|
|
||||||
resp.WriteHeader(422)
|
|
||||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed marshalling new parsed swagger: %s"}`, err)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.WriteHeader(200)
|
|
||||||
resp.Write(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getWorkflowApps(resp http.ResponseWriter, request *http.Request) {
|
func getWorkflowApps(resp http.ResponseWriter, request *http.Request) {
|
||||||
cors := handleCors(resp, request)
|
cors := handleCors(resp, request)
|
||||||
if cors {
|
if cors {
|
||||||
@@ -3525,34 +3418,6 @@ func getWorkflowApps(resp http.ResponseWriter, request *http.Request) {
|
|||||||
//return
|
//return
|
||||||
}
|
}
|
||||||
|
|
||||||
//if item, err := memcache.Get(ctx, memcacheName); err == memcache.ErrCacheMiss {
|
|
||||||
// // Not in cache
|
|
||||||
// log.Printf("Apps not in cache.")
|
|
||||||
//} else if err != nil {
|
|
||||||
// log.Printf("Error getting item: %v", err)
|
|
||||||
//} else {
|
|
||||||
// // FIXME - verify if value is ok? Can unmarshal etc.
|
|
||||||
// allApps := item.Value
|
|
||||||
|
|
||||||
// if userErr == nil && len(user.PrivateApps) > 0 {
|
|
||||||
// var parsedApps []WorkflowApp
|
|
||||||
// err = json.Unmarshal(allApps, &parsedApps)
|
|
||||||
// if err == nil {
|
|
||||||
// log.Printf("Shouldve added %d apps", len(user.PrivateApps))
|
|
||||||
// user.PrivateApps = append(user.PrivateApps, parsedApps...)
|
|
||||||
|
|
||||||
// tmpApps, err := json.Marshal(user.PrivateApps)
|
|
||||||
// if err == nil {
|
|
||||||
// allApps = tmpApps
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// resp.WriteHeader(200)
|
|
||||||
// resp.Write(allApps)
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
|
|
||||||
workflowapps, err := shuffle.GetAllWorkflowApps(ctx, 500)
|
workflowapps, err := shuffle.GetAllWorkflowApps(ctx, 500)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed getting apps (getworkflowapps): %s", err)
|
log.Printf("Failed getting apps (getworkflowapps): %s", err)
|
||||||
@@ -3560,52 +3425,8 @@ func getWorkflowApps(resp http.ResponseWriter, request *http.Request) {
|
|||||||
resp.Write([]byte(`{"success": false}`))
|
resp.Write([]byte(`{"success": false}`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//log.Printf("Length: %d", len(workflowapps))
|
|
||||||
|
|
||||||
// FIXME - this is really garbage, but is here to protect again null values etc.
|
|
||||||
|
|
||||||
newapps := workflowapps
|
newapps := workflowapps
|
||||||
/*
|
|
||||||
skipApps := []string{"Shuffle Subflow"}
|
|
||||||
newapps := []WorkflowApp{}
|
|
||||||
baseApps := []WorkflowApp{}
|
|
||||||
for _, workflowapp := range workflowapps {
|
|
||||||
//if !workflowapp.Activated && workflowapp.Generated {
|
|
||||||
// continue
|
|
||||||
//}
|
|
||||||
|
|
||||||
if workflowapp.Owner != user.Id && user.Role != "admin" && !workflowapp.Sharing {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
continueOuter := false
|
|
||||||
for _, skip := range skipApps {
|
|
||||||
if workflowapp.Name == skip {
|
|
||||||
continueOuter = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if continueOuter {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
//workflowapp.Environment = "cloud"
|
|
||||||
newactions := []WorkflowAppAction{}
|
|
||||||
for _, action := range workflowapp.Actions {
|
|
||||||
//action.Environment = workflowapp.Environment
|
|
||||||
if len(action.Parameters) == 0 {
|
|
||||||
action.Parameters = []WorkflowAppActionParameter{}
|
|
||||||
}
|
|
||||||
|
|
||||||
newactions = append(newactions, action)
|
|
||||||
}
|
|
||||||
|
|
||||||
workflowapp.Actions = newactions
|
|
||||||
newapps = append(newapps, workflowapp)
|
|
||||||
baseApps = append(baseApps, workflowapp)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if len(user.PrivateApps) > 0 {
|
if len(user.PrivateApps) > 0 {
|
||||||
found := false
|
found := false
|
||||||
@@ -3625,7 +3446,6 @@ func getWorkflowApps(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
// Double unmarshal because of user apps
|
// Double unmarshal because of user apps
|
||||||
newbody, err := json.Marshal(newapps)
|
newbody, err := json.Marshal(newapps)
|
||||||
//newbody, err := json.Marshal(workflowapps)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed unmarshalling all newapps: %s", err)
|
log.Printf("Failed unmarshalling all newapps: %s", err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
@@ -3633,33 +3453,6 @@ func getWorkflowApps(resp http.ResponseWriter, request *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//basebody, err := json.Marshal(baseApps)
|
|
||||||
////newbody, err := json.Marshal(workflowapps)
|
|
||||||
//if err != nil {
|
|
||||||
// log.Printf("Failed unmarshalling all baseapps: %s", err)
|
|
||||||
// resp.WriteHeader(401)
|
|
||||||
// resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed unpacking workflow apps"}`)))
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Refreshed every hour
|
|
||||||
//item := &memcache.Item{
|
|
||||||
// Key: memcacheName,
|
|
||||||
// Value: basebody,
|
|
||||||
// Expiration: time.Minute * 60,
|
|
||||||
//}
|
|
||||||
//if err := memcache.Add(ctx, item); err == memcache.ErrNotStored {
|
|
||||||
// if err := memcache.Set(ctx, item); err != nil {
|
|
||||||
// log.Printf("Error setting item: %v", err)
|
|
||||||
// }
|
|
||||||
//} else if err != nil {
|
|
||||||
// log.Printf("error adding item: %v", err)
|
|
||||||
//} else {
|
|
||||||
// log.Printf("Set cache for %s", item.Key)
|
|
||||||
//}
|
|
||||||
|
|
||||||
//log.Println(string(body))
|
|
||||||
//log.Println(string(newbody))
|
|
||||||
resp.WriteHeader(200)
|
resp.WriteHeader(200)
|
||||||
resp.Write(newbody)
|
resp.Write(newbody)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1302,9 +1302,10 @@ const AngularWorkflow = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const curapp = apps.find(a => a.name === curaction.app_name && a.app_version === curaction.app_version)
|
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)))
|
||||||
if (!curapp || curapp === undefined) {
|
if (!curapp || curapp === undefined) {
|
||||||
alert.error("App "+curaction.app_name+" not found. Is it activated?")
|
alert.error(`App ${curaction.app_name}:${curaction.app_version} not found. Is it activated?`)
|
||||||
//return
|
//return
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -2169,9 +2170,9 @@ const AngularWorkflow = (props) => {
|
|||||||
<div style={variableScrollStyle}>
|
<div style={variableScrollStyle}>
|
||||||
What are <a rel="norefferer" target="_blank" href="https://shuffler.io/docs/workflows#workflow_variables" target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>WORKFLOW variables?</a>
|
What are <a rel="norefferer" target="_blank" href="https://shuffler.io/docs/workflows#workflow_variables" target="_blank" style={{textDecoration: "none", color: "#f85a3e"}}>WORKFLOW variables?</a>
|
||||||
{workflow.workflow_variables === null ?
|
{workflow.workflow_variables === null ?
|
||||||
null : workflow.workflow_variables.map(variable=> {
|
null : workflow.workflow_variables.map((variable, index) => {
|
||||||
return (
|
return (
|
||||||
<div key={variable.name} >
|
<div key={index} >
|
||||||
<Paper square style={paperVariableStyle} onClick={() => {
|
<Paper square style={paperVariableStyle} onClick={() => {
|
||||||
}}>
|
}}>
|
||||||
<div style={{marginLeft: "10px", marginTop: "5px", marginBottom: "5px", width: "2px", backgroundColor: yellow, marginRight: "5px"}} />
|
<div style={{marginLeft: "10px", marginTop: "5px", marginBottom: "5px", width: "2px", backgroundColor: yellow, marginRight: "5px"}} />
|
||||||
@@ -2906,7 +2907,6 @@ const AngularWorkflow = (props) => {
|
|||||||
id="appsearch"
|
id="appsearch"
|
||||||
onKeyPress={(event) => {
|
onKeyPress={(event) => {
|
||||||
if (event.key === "Enter") {
|
if (event.key === "Enter") {
|
||||||
console.log("ENTER!")
|
|
||||||
runSearch(event.target.value)
|
runSearch(event.target.value)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@@ -4215,6 +4215,66 @@ const AngularWorkflow = (props) => {
|
|||||||
borderRadius: borderRadius,
|
borderRadius: borderRadius,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getApp = (appId, setApp) => {
|
||||||
|
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(responseJson)
|
||||||
|
|
||||||
|
if (setApp && responseJson.actions !== undefined && responseJson.actions !== null) {
|
||||||
|
if (selectedApp.versions !== undefined && selectedApp.versions !== null) {
|
||||||
|
responseJson.versions = selectedApp.versions
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedApp.loop_versions !== undefined && selectedApp.loop_versions !== null) {
|
||||||
|
responseJson.loop_versions = selectedApp.loop_versions
|
||||||
|
}
|
||||||
|
|
||||||
|
var foundAction = responseJson.actions.find(action => action.name === selectedAction.name)
|
||||||
|
console.log("Old : ", selectedAction)
|
||||||
|
console.log("Found: ", foundAction)
|
||||||
|
if (foundAction !== null && foundAction !== undefined) {
|
||||||
|
for (var paramkey in foundAction.parameters) {
|
||||||
|
const param = foundAction.parameters[paramkey]
|
||||||
|
|
||||||
|
const foundParam = selectedAction.parameters.find(item => item.name === param.name)
|
||||||
|
if (foundParam === undefined) {
|
||||||
|
console.log("COULDNT find Param: ", param)
|
||||||
|
} else {
|
||||||
|
console.log("FoundP: ", foundParam)
|
||||||
|
foundAction.parameters[paramkey] = foundParam
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert.error("Couldn't find action "+selectedAction.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updating params for the new action
|
||||||
|
selectedAction.parameters = foundAction.parameters
|
||||||
|
selectedAction.app_id = appId
|
||||||
|
selectedAction.app_version = responseJson.app_version
|
||||||
|
|
||||||
|
setSelectedAction(selectedAction)
|
||||||
|
setSelectedApp(responseJson)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
alert.error(error.toString())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const innerTextfieldStyle = {
|
const innerTextfieldStyle = {
|
||||||
color: "white",
|
color: "white",
|
||||||
@@ -4267,16 +4327,42 @@ const AngularWorkflow = (props) => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div style={{display: "flex", flexDirection: "column",}}>
|
||||||
{selectedAction.id === workflow.start ? null :
|
{selectedAction.id === workflow.start ? null :
|
||||||
<Tooltip color="primary" title={"Make this node the start action"} placement="top">
|
<Tooltip color="primary" title={"Make this node the start action"} placement="top">
|
||||||
<Button style={{zIndex: 5000, marginTop: "15px",}} color="primary" variant="outlined" onClick={(e) => {
|
<Button style={{zIndex: 5000, marginTop: 10,}} color="primary" variant="outlined" onClick={(e) => {
|
||||||
defineStartnode(e)
|
defineStartnode(e)
|
||||||
}}>
|
}}>
|
||||||
<KeyboardArrowRightIcon />
|
<KeyboardArrowRightIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
}
|
}
|
||||||
|
{selectedApp.versions !== null && selectedApp.versions !== undefined && selectedApp.versions.length > 0 ?
|
||||||
|
<Select
|
||||||
|
defaultValue={selectedAction.app_version}
|
||||||
|
onChange={(event) => {
|
||||||
|
const newversion = selectedApp.versions.find(tmpApp => tmpApp.version == event.target.value)
|
||||||
|
if (newversion !== undefined && newversion !== null) {
|
||||||
|
getApp(newversion.id, true)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{marginTop: 10, backgroundColor: theme.palette.surfaceColor, backgroundColor: inputColor, color: "white", height: 35, marginleft: 10,}}
|
||||||
|
SelectDisplayProps={{
|
||||||
|
style: {
|
||||||
|
marginLeft: 10,
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{selectedApp.versions.map((data, index) => {
|
||||||
|
return (
|
||||||
|
<MenuItem key={index} style={{backgroundColor: inputColor, color: "white"}} value={data.version}>
|
||||||
|
{data.version}
|
||||||
|
|
||||||
|
</MenuItem>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</Select>
|
||||||
|
: null }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Divider style={{marginBottom: "10px", marginTop: "10px", height: "1px", width: "100%", backgroundColor: "rgb(91, 96, 100)"}}/>
|
<Divider style={{marginBottom: "10px", marginTop: "10px", height: "1px", width: "100%", backgroundColor: "rgb(91, 96, 100)"}}/>
|
||||||
|
|||||||
@@ -631,6 +631,37 @@ const Apps = (props) => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{selectedApp.versions !== null && selectedApp.versions !== undefined && selectedApp.versions.length > 0 ?
|
||||||
|
<Select
|
||||||
|
defaultValue={selectedApp.app_version}
|
||||||
|
onChange={(event) => {
|
||||||
|
console.log("Changing version to index "+event.target.value)
|
||||||
|
const newversion = selectedApp.versions.find(tmpApp => tmpApp.version == event.target.value)
|
||||||
|
console.log("New version: ", newversion)
|
||||||
|
selectedApp.app_version = selectedApp.app_version
|
||||||
|
setSelectedApp(selectedApp)
|
||||||
|
|
||||||
|
if (newversion !== undefined && newversion !== null) {
|
||||||
|
getApp(newversion.id, true)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{position: "absolute", top: -10, right: isCloud ? 50 : 0, backgroundColor: theme.palette.surfaceColor, backgroundColor: inputColor, color: "white", height: 35, marginleft: 10,}}
|
||||||
|
SelectDisplayProps={{
|
||||||
|
style: {
|
||||||
|
marginLeft: 10,
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{selectedApp.versions.map((data, index) => {
|
||||||
|
return (
|
||||||
|
<MenuItem key={data.version} style={{backgroundColor: inputColor, color: "white"}} value={data.version}>
|
||||||
|
{data.version}
|
||||||
|
|
||||||
|
</MenuItem>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</Select>
|
||||||
|
: null }
|
||||||
{isCloud ?
|
{isCloud ?
|
||||||
<a href={"https://shuffler.io/apps/"+selectedApp.id} style={{textDecoration: "none", color: "#f85a3e"}} target="_blank">
|
<a href={"https://shuffler.io/apps/"+selectedApp.id} style={{textDecoration: "none", color: "#f85a3e"}} target="_blank">
|
||||||
<IconButton style={{top: -10, right: 0, position: "absolute", color: "#f85a3e"}} >
|
<IconButton style={{top: -10, right: 0, position: "absolute", color: "#f85a3e"}} >
|
||||||
@@ -835,7 +866,7 @@ const Apps = (props) => {
|
|||||||
var tmpapps = searchableApps.filter(data => data.name.toLowerCase().includes(searchfield) || data.description.toLowerCase().includes(searchfield))
|
var tmpapps = searchableApps.filter(data => data.name.toLowerCase().includes(searchfield) || data.description.toLowerCase().includes(searchfield))
|
||||||
newapps.push(...tmpapps)
|
newapps.push(...tmpapps)
|
||||||
|
|
||||||
console.log(newapps)
|
//console.log(newapps)
|
||||||
setFilteredApps(newapps)
|
setFilteredApps(newapps)
|
||||||
//if ((newapps.length === 0 || searchBackend) && !appSearchLoading) {
|
//if ((newapps.length === 0 || searchBackend) && !appSearchLoading) {
|
||||||
|
|
||||||
@@ -1108,7 +1139,7 @@ const Apps = (props) => {
|
|||||||
setValidation(true)
|
setValidation(true)
|
||||||
|
|
||||||
var cors = "cors"
|
var cors = "cors"
|
||||||
if (openApi.includes("localhost")) {
|
if (openApi.includes("= localhost")) {
|
||||||
cors = "no-cors"
|
cors = "no-cors"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1126,6 +1157,48 @@ const Apps = (props) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getApp = (appId, setApp) => {
|
||||||
|
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(responseJson)
|
||||||
|
|
||||||
|
if (setApp) {
|
||||||
|
if (selectedApp.versions !== undefined && selectedApp.versions !== null) {
|
||||||
|
responseJson.versions = selectedApp.versions
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedApp.loop_versions !== undefined && selectedApp.loop_versions !== null) {
|
||||||
|
responseJson.loop_versions = selectedApp.loop_versions
|
||||||
|
}
|
||||||
|
|
||||||
|
//alert.info("Should set app to selected")
|
||||||
|
if (responseJson.actions !== undefined && responseJson.actions !== null && responseJson.actions.length > 0) {
|
||||||
|
setSelectedAction(responseJson.actions[0])
|
||||||
|
} else {
|
||||||
|
setSelectedAction({})
|
||||||
|
}
|
||||||
|
setSelectedApp(responseJson)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
alert.error(error.toString())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const deleteApp = (appId) => {
|
const deleteApp = (appId) => {
|
||||||
alert.info("Attempting to delete app")
|
alert.info("Attempting to delete app")
|
||||||
fetch(globalUrl+"/api/v1/apps/"+appId, {
|
fetch(globalUrl+"/api/v1/apps/"+appId, {
|
||||||
|
|||||||
Reference in New Issue
Block a user