diff --git a/backend/go-app/walkoff.go b/backend/go-app/walkoff.go index 5ba6c7f5..b9fde0ba 100644 --- a/backend/go-app/walkoff.go +++ b/backend/go-app/walkoff.go @@ -1182,7 +1182,6 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) { //Actions []Action `json:"actions" datastore:"actions,noindex"` - log.Printf("Hello") body, err := ioutil.ReadAll(request.Body) if err != nil { log.Printf("Failed hook unmarshaling: %s", err) @@ -1191,7 +1190,6 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) { return } - log.Printf("Hello2") var workflow Workflow err = json.Unmarshal([]byte(body), &workflow) //log.Printf(string(body)) @@ -1216,12 +1214,23 @@ func saveWorkflow(resp http.ResponseWriter, request *http.Request) { log.Println("Pre") for _, action := range workflow.Actions { allNodes = append(allNodes, action.ID) + if action.Environment == "" { resp.WriteHeader(401) resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "An environment for %s is required"}`, action.Label))) return action.IsValid = true } + + // FIXME: Have a good way of tracking errors. ID's or similar. + if !action.IsValid { + resp.WriteHeader(401) + resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Node %s is invalid and needs to be remade."}`, action.Label))) + return + action.IsValid = true + action.Errors = []string{} + } + newActions = append(newActions, action) } @@ -2653,6 +2662,65 @@ func deleteWorkflowApp(resp http.ResponseWriter, request *http.Request) { private = true } + q := datastore.NewQuery("workflow") + var workflows []Workflow + _, err = dbclient.GetAll(ctx, q, &workflows) + if err != nil { + resp.WriteHeader(401) + resp.Write([]byte(`{"success": false, "reason": "}`)) + return + } + + for _, workflow := range workflows { + found := false + + newActions := []Action{} + for _, action := range workflow.Actions { + if action.AppName == app.Name && action.AppVersion == app.AppVersion { + found = true + action.Errors = append(action.Errors, "App has been deleted") + action.IsValid = false + } + + newActions = append(newActions, action) + } + + if found { + workflow.IsValid = false + workflow.Errors = append(workflow.Errors, fmt.Sprintf("App %s_%s has been deleted", app.Name, app.AppVersion)) + workflow.Actions = newActions + + for _, trigger := range workflow.Triggers { + log.Printf("TRIGGER: %#v", trigger) + //err = deleteSchedule(ctx, scheduleId) + //if err != nil { + // if strings.Contains(err.Error(), "Job not found") { + // resp.WriteHeader(200) + // resp.Write([]byte(fmt.Sprintf(`{"success": true}`))) + // } else { + // resp.WriteHeader(401) + // resp.Write([]byte(fmt.Sprintf(`{"success": false, "reason": "Failed stopping schedule"}`))) + // } + // return + //} + } + + err = setWorkflow(ctx, workflow, workflow.ID) + if err != nil { + log.Printf("Failed setting workflow when deleting app: %s", err) + continue + } else { + log.Printf("Set %s (%s) to have errors", workflow.ID, workflow.Name) + } + + } + + } + + //resp.WriteHeader(200) + //resp.Write([]byte(`{"success": true}`)) + //return + // Not really deleting it, just removing from user cache if private { log.Printf("Deleting private app") @@ -2675,6 +2743,7 @@ func deleteWorkflowApp(resp http.ResponseWriter, request *http.Request) { return } } else { + log.Printf("Deleting public app") err = DeleteKey(ctx, "workflowapp", fileId) if err != nil { diff --git a/docker-compose.yml b/docker-compose.yml index 0fbc7c41..72dccb0c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: '3' services: frontend: - #build: ./frontend + build: ./frontend image: frikky/shuffle:frontend container_name: shuffle-frontend hostname: shuffle-frontend @@ -26,7 +26,7 @@ services: volumes: - ${DB_LOCATION}:/etc/shuffle backend: - #build: ./backend + build: ./backend image: frikky/shuffle:backend container_name: shuffle-backend hostname: ${BACKEND_HOSTNAME} diff --git a/frontend/src/AngularWorkflow.js b/frontend/src/AngularWorkflow.js index 4a135227..c1701c69 100644 --- a/frontend/src/AngularWorkflow.js +++ b/frontend/src/AngularWorkflow.js @@ -814,7 +814,7 @@ const AngularWorkflow = (props) => { //console.log("ACTION: ", selectedAction) //console.log("APP: ", selectedApp) setSelectedAction({}) - //setSelectedApp({}) + setSelectedApp({}) //setSelectedTrigger({}) //setSelectedEdge({}) @@ -848,6 +848,7 @@ const AngularWorkflow = (props) => { const onNodeSelect = (event) => { const data = event.target.data() + console.log("NODE: ", data) setLastSaved(false) //console.log(data) @@ -2564,10 +2565,16 @@ const AngularWorkflow = (props) => { const appApiView = Object.getOwnPropertyNames(selectedAction).length > 0 && Object.getOwnPropertyNames(selectedApp).length > 0 ?
-
-
-

{selectedAction.app_name}

+
+
+

{selectedAction.app_name}

What are apps? + {selectedAction.errors !== null && selectedAction.errors.length > 0 ? +
+ Errors: {selectedAction.errors.join("\n")} +
+ : null + }
+ + + + + : null + const appsModalLoad = loadAppsModalOpen ? { {appView} {modalView} {appsModalLoad} + {deleteModal}
:
diff --git a/frontend/src/Workflows.js b/frontend/src/Workflows.js index acb59584..ed7d6ed0 100644 --- a/frontend/src/Workflows.js +++ b/frontend/src/Workflows.js @@ -319,7 +319,7 @@ const Workflows = (props) => { // dropdown with copy etc I guess const WorkflowPaper = (props) => { - const { data } = props; + const { data } = props; const [open, setOpen] = React.useState(false); const [anchorEl, setAnchorEl] = React.useState(null); diff --git a/frontend/src/defaultCytoscapeStyle.js b/frontend/src/defaultCytoscapeStyle.js index 4e3c0b24..869dd6d7 100644 --- a/frontend/src/defaultCytoscapeStyle.js +++ b/frontend/src/defaultCytoscapeStyle.js @@ -101,10 +101,10 @@ const data = [{ }, }, { - selector: 'node[?hasErrors]', + selector: "node[!is_valid]", css: { - 'color': '#991818', - 'font-style': 'italic', + 'border-color': 'red', + 'border-width': '10px', }, }, {