#44: Added error check when deleting an app
This commit is contained in:
@@ -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 {
|
||||
|
||||
+2
-2
@@ -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}
|
||||
|
||||
@@ -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 ?
|
||||
<div style={appApiViewStyle}>
|
||||
<div style={{display: "flex", height: 40, marginBottom: 30}}>
|
||||
<div style={{flex: "1"}}>
|
||||
<h3 style={{marginBottom: "5px"}}>{selectedAction.app_name}</h3>
|
||||
<div style={{display: "flex", minHeight: 40, marginBottom: 30}}>
|
||||
<div style={{flex: 1}}>
|
||||
<h3 style={{marginBottom: 5}}>{selectedAction.app_name}</h3>
|
||||
<Link to="/docs/apps" style={{textDecoration: "none", color: "#f85a3e"}}>What are apps?</Link>
|
||||
{selectedAction.errors !== null && selectedAction.errors.length > 0 ?
|
||||
<div>
|
||||
Errors: {selectedAction.errors.join("\n")}
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
<div style={{flex: "1"}}>
|
||||
<Button disabled={selectedAction.id === workflow.start} style={{zIndex: 5000, marginTop: "15px",}} color="primary" variant="outlined" onClick={(e) => {
|
||||
|
||||
+34
-3
@@ -56,6 +56,7 @@ const Apps = (props) => {
|
||||
const [openApiData, setOpenApiData] = React.useState("")
|
||||
const [appValidation, setAppValidation] = React.useState("")
|
||||
const [loadAppsModalOpen, setLoadAppsModalOpen] = React.useState(false);
|
||||
const [deleteModalOpen, setDeleteModalOpen] = React.useState(false);
|
||||
const [openApiModal, setOpenApiModal] = React.useState(false);
|
||||
const [openApiModalType, setOpenApiModalType] = React.useState("");
|
||||
const [openApiError, setOpenApiError] = React.useState("")
|
||||
@@ -352,7 +353,7 @@ const Apps = (props) => {
|
||||
color="primary"
|
||||
style={{marginLeft: 5, marginTop: 10}}
|
||||
onClick={() => {
|
||||
deleteApp(selectedApp.id)
|
||||
setDeleteModalOpen(true)
|
||||
}}
|
||||
>
|
||||
<DeleteIcon />
|
||||
@@ -819,13 +820,42 @@ const Apps = (props) => {
|
||||
window.location.href = "/apps/new?id="+appValidation
|
||||
}
|
||||
|
||||
|
||||
|
||||
const handleGithubValidation = () => {
|
||||
getSpecificApps(openApi)
|
||||
setLoadAppsModalOpen(false)
|
||||
}
|
||||
|
||||
const deleteModal = deleteModalOpen ?
|
||||
<Dialog modal
|
||||
open={deleteModalOpen}
|
||||
onClose={() => {
|
||||
setDeleteModalOpen(false)
|
||||
}}
|
||||
PaperProps={{
|
||||
style: {
|
||||
backgroundColor: surfaceColor,
|
||||
color: "white",
|
||||
minWidth: 500,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DialogTitle>
|
||||
<div style={{textAlign: "center", color: "rgba(255,255,255,0.9)"}}>
|
||||
Are you sure? <div/>Some workflows may stop working.
|
||||
</div>
|
||||
</DialogTitle>
|
||||
<DialogContent style={{color: "rgba(255,255,255,0.65)", textAlign: "center"}}>
|
||||
<Button style={{}} onClick={() => {deleteApp(selectedApp.id); setDeleteModalOpen(false)}} color="primary">
|
||||
Yes
|
||||
</Button>
|
||||
<Button variant="outlined" style={{}} onClick={() => {setDeleteModalOpen(false)}} color="primary">
|
||||
No
|
||||
</Button>
|
||||
</DialogContent>
|
||||
|
||||
</Dialog>
|
||||
: null
|
||||
|
||||
const appsModalLoad = loadAppsModalOpen ?
|
||||
<Dialog modal
|
||||
open={loadAppsModalOpen}
|
||||
@@ -1006,6 +1036,7 @@ const Apps = (props) => {
|
||||
{appView}
|
||||
{modalView}
|
||||
{appsModalLoad}
|
||||
{deleteModal}
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user