Cache contains, Variables, App Activation and Subflow fixes
This commit is contained in:
+21
-29
@@ -842,7 +842,7 @@ func handleRemoteDownloadApp(resp http.ResponseWriter, ctx context.Context, user
|
|||||||
app := tmpapp{}
|
app := tmpapp{}
|
||||||
err := json.Unmarshal(respBody, &app)
|
err := json.Unmarshal(respBody, &app)
|
||||||
if err != nil || app.Success == false || len(app.OpenAPI) == 0 {
|
if err != nil || app.Success == false || len(app.OpenAPI) == 0 {
|
||||||
log.Printf("[ERROR] Failed app unmarshal during auto-download. Success%#v. Applength: %d: %s", app.Success, len(app.OpenAPI), err)
|
log.Printf("[ERROR] Failed app unmarshal during auto-download. Success: %#v. Applength: %d: %s", app.Success, len(app.OpenAPI), err)
|
||||||
resp.WriteHeader(401)
|
resp.WriteHeader(401)
|
||||||
resp.Write([]byte(`{"success": false, "reason": "App doesn't exist"}`))
|
resp.Write([]byte(`{"success": false, "reason": "App doesn't exist"}`))
|
||||||
return
|
return
|
||||||
@@ -960,37 +960,29 @@ func activateWorkflowAppDocker(resp http.ResponseWriter, request *http.Request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if app.Sharing || app.Public {
|
// Just making sure it's being built properly
|
||||||
org, err := shuffle.GetOrg(ctx, user.ActiveOrg.Id)
|
if app == nil {
|
||||||
if err == nil {
|
log.Printf("[WARNING] App is nil. This shouldn't happen. Starting remote download(3)")
|
||||||
added := false
|
handleRemoteDownloadApp(resp, ctx, user, fileId)
|
||||||
if !shuffle.ArrayContains(org.ActiveApps, app.ID) {
|
|
||||||
org.ActiveApps = append(org.ActiveApps, app.ID)
|
|
||||||
added = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if added {
|
|
||||||
err = shuffle.SetOrg(ctx, *org, org.Id)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("[WARNING] Failed setting org when autoadding apps on save: %s", err)
|
|
||||||
} else {
|
|
||||||
log.Printf("[INFO] Added public app %s (%s) to org %s (%s)", app.Name, app.ID, user.ActiveOrg.Name, user.ActiveOrg.Id)
|
|
||||||
cacheKey := fmt.Sprintf("apps_%s", user.Id)
|
|
||||||
shuffle.DeleteCache(ctx, cacheKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Printf("[WARNING] User is trying to activate %s which is NOT public", app.Name)
|
|
||||||
resp.WriteHeader(401)
|
|
||||||
resp.Write([]byte(`{"success": false}`))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] App %s (%s) activated for org %s by user %s", app.Name, app.ID, user.ActiveOrg.Id, user.Username)
|
// Check the app.. hmm
|
||||||
|
openApiApp, err := shuffle.GetOpenApiDatastore(ctx, app.ID)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[WARNING] Error getting app %s (openapi config): %s", app.ID, err)
|
||||||
|
resp.WriteHeader(401)
|
||||||
|
resp.Write([]byte(`{"success": false, "reason": "Couldn't find app OpenAPI"}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// If onprem, it should autobuild the container(s) from here
|
log.Printf("[INFO] User %s (%s) is activating %s. Public: %t, Shared: %t", user.Username, user.Id, app.Name, app.Public, app.Sharing)
|
||||||
|
buildSwaggerApp(resp, []byte(openApiApp.Body), user, true)
|
||||||
|
|
||||||
resp.WriteHeader(200)
|
//app.Active = true
|
||||||
resp.Write([]byte(`{"success": true}`))
|
//app.Generated = true
|
||||||
|
//app, err := shuffle.SetApp(ctx, app)
|
||||||
|
|
||||||
|
//resp.WriteHeader(200)
|
||||||
|
//resp.Write([]byte(`{"success": true}`))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ require (
|
|||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/h2non/filetype v1.1.3
|
github.com/h2non/filetype v1.1.3
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shuffle/shuffle-shared v0.4.1
|
github.com/shuffle/shuffle-shared v0.4.2
|
||||||
golang.org/x/crypto v0.3.0
|
golang.org/x/crypto v0.3.0
|
||||||
google.golang.org/api v0.103.0
|
google.golang.org/api v0.103.0
|
||||||
google.golang.org/appengine v1.6.7
|
google.golang.org/appengine v1.6.7
|
||||||
|
|||||||
@@ -1161,7 +1161,7 @@ func executeWorkflow(resp http.ResponseWriter, request *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[INFO] Starting execution of %s!", fileId)
|
log.Printf("[AUDIT] Starting execution of workflow '%s' by user %s (%s)!", fileId, user.Username, user.Id)
|
||||||
|
|
||||||
user.ActiveOrg.Users = []shuffle.UserMini{}
|
user.ActiveOrg.Users = []shuffle.UserMini{}
|
||||||
workflow.ExecutingOrg = user.ActiveOrg
|
workflow.ExecutingOrg = user.ActiveOrg
|
||||||
|
|||||||
@@ -146,17 +146,18 @@ const ConfigureWorkflow = (props) => {
|
|||||||
app: {},
|
app: {},
|
||||||
steps: [],
|
steps: [],
|
||||||
show_steps: false,
|
show_steps: false,
|
||||||
};
|
}
|
||||||
|
|
||||||
const app = apps.find(
|
//console.log("Action: ", key, keyval)
|
||||||
(app) =>
|
|
||||||
app.name === action.app_name &&
|
const app = apps.find((app) =>
|
||||||
(app.app_version === action.app_version ||
|
app.id === action.app_id ||
|
||||||
(app.loop_versions !== null &&
|
(app.name === action.app_name &&
|
||||||
app.loop_versions.includes(action.app_version)))
|
(app.app_version === action.app_version || (app.loop_versions !== null && app.loop_versions.includes(action.app_version))))
|
||||||
)
|
)
|
||||||
|
|
||||||
//newaction.steps = wazuhSteps
|
//console.log("FOUND APP: ", app)
|
||||||
|
|
||||||
if (app === undefined || app === null) {
|
if (app === undefined || app === null) {
|
||||||
const subapp = apps.find(app => app.name === action.app_name)
|
const subapp = apps.find(app => app.name === action.app_name)
|
||||||
if (subapp !== undefined && subapp !== null) {
|
if (subapp !== undefined && subapp !== null) {
|
||||||
@@ -265,17 +266,14 @@ const ConfigureWorkflow = (props) => {
|
|||||||
if (workflow.workflow_variables !== undefined && workflow.workflow_variables !== null && workflow.workflow_variables.length !== 0) {
|
if (workflow.workflow_variables !== undefined && workflow.workflow_variables !== null && workflow.workflow_variables.length !== 0) {
|
||||||
for (let [key,keyval] in Object.entries(workflow.workflow_variables)) {
|
for (let [key,keyval] in Object.entries(workflow.workflow_variables)) {
|
||||||
const variable = workflow.workflow_variables[key];
|
const variable = workflow.workflow_variables[key];
|
||||||
if (
|
if (variable.value === undefined || variable.value === undefined || variable.value.length === 0) {
|
||||||
variable.value === undefined ||
|
|
||||||
variable.value === undefined ||
|
|
||||||
variable.value.length < 2
|
|
||||||
) {
|
|
||||||
variable.value = "";
|
variable.value = "";
|
||||||
variable.index = key;
|
|
||||||
requiredVariables.push(variable);
|
requiredVariables.push(variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable.index = key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (workflow.triggers !== undefined && workflow.triggers !== null && workflow.triggers.length !== 0) {
|
if (workflow.triggers !== undefined && workflow.triggers !== null && workflow.triggers.length !== 0) {
|
||||||
for (let [key,keyval] in Object.entries(workflow.triggers)) {
|
for (let [key,keyval] in Object.entries(workflow.triggers)) {
|
||||||
@@ -1015,7 +1013,7 @@ const ConfigureWorkflow = (props) => {
|
|||||||
<List>
|
<List>
|
||||||
{requiredActions.map((data, index) => {
|
{requiredActions.map((data, index) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div key={index}>
|
||||||
{data.steps !== undefined && data.steps !== null && data.show_steps === true ?
|
{data.steps !== undefined && data.steps !== null && data.show_steps === true ?
|
||||||
<AppWrapper data={data} parentindex={index} />
|
<AppWrapper data={data} parentindex={index} />
|
||||||
:
|
:
|
||||||
|
|||||||
@@ -1909,7 +1909,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getWorkflow = (workflow_id, sourcenode) => {
|
const getWorkflow = (workflow_id, sourcenode) => {
|
||||||
fetch(globalUrl + "/api/v1/workflows/" + workflow_id, {
|
fetch(`${globalUrl}/api/v1/workflows/${workflow_id}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -1920,12 +1920,25 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
.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!");
|
||||||
window.location.pathname = "/workflows";
|
|
||||||
|
if (response.status >= 500) {
|
||||||
|
alert.info("Something went wrong while loading the workflow. Please reload.")
|
||||||
|
} else {
|
||||||
|
alert.info("You don't access to this workflow or loading failed.")
|
||||||
|
window.location.pathname = "/workflows";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read text from stream
|
||||||
|
//return response.text();
|
||||||
return response.json();
|
return response.json();
|
||||||
})
|
})
|
||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
|
// Load as JSON
|
||||||
|
//console.log("Got workflow TXT: ", responseText)
|
||||||
|
//const responseJson = JSON.parse(responseText)
|
||||||
|
//console.log("Got workflow JSON: ", responseJson)
|
||||||
|
|
||||||
// Not sure why this is necessary.
|
// Not sure why this is necessary.
|
||||||
if (responseJson.isValid === undefined) {
|
if (responseJson.isValid === undefined) {
|
||||||
responseJson.isValid = true;
|
responseJson.isValid = true;
|
||||||
@@ -2145,7 +2158,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
setWorkflowDone(true);
|
setWorkflowDone(true);
|
||||||
|
|
||||||
// Add error checks
|
// Add error checks
|
||||||
console.log("Workflow: ", responseJson);
|
|
||||||
if (!responseJson.public) {
|
if (!responseJson.public) {
|
||||||
if (
|
if (
|
||||||
!responseJson.previously_saved ||
|
!responseJson.previously_saved ||
|
||||||
@@ -2517,8 +2529,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
cy.add(decoratorNode)
|
cy.add(decoratorNode)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
||||||
// Readding the icon after moving the node
|
// Readding the icon after moving the node
|
||||||
if (!found) {
|
if (!found) {
|
||||||
const iconInfo = GetIconInfo(nodedata);
|
const iconInfo = GetIconInfo(nodedata);
|
||||||
@@ -3187,7 +3197,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const activateApp = (appid, refresh) => {
|
const activateApp = (appid, refresh) => {
|
||||||
fetch(globalUrl + "/api/v1/apps/" + appid + "/activate", {
|
fetch(`${globalUrl}/api/v1/apps/${appid}/activate`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -3204,11 +3214,10 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
})
|
})
|
||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
if (responseJson.success === false) {
|
if (responseJson.success === false) {
|
||||||
alert.error("Failed to activate the app")
|
alert.error("Failed to auto-activate the app. Go to /apps and activate it.")
|
||||||
} else {
|
} else {
|
||||||
alert.success("App activated for your organization! Refresh the page to use the app.")
|
|
||||||
|
|
||||||
if (refresh === true) {
|
if (refresh === true) {
|
||||||
|
alert.success("App activated for your organization! Refresh the page to use the app.")
|
||||||
getApps()
|
getApps()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3939,6 +3948,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
workflow.branches = workflow.branches.filter(
|
workflow.branches = workflow.branches.filter(
|
||||||
(a) => a.id !== edge.data().id
|
(a) => a.id !== edge.data().id
|
||||||
);
|
);
|
||||||
|
|
||||||
setWorkflow(workflow);
|
setWorkflow(workflow);
|
||||||
event.target.remove();
|
event.target.remove();
|
||||||
|
|
||||||
@@ -5591,7 +5601,9 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
display: "flex",
|
display: "flex",
|
||||||
};
|
};
|
||||||
|
|
||||||
const VariablesView = () => {
|
const VariableItem = (props) => {
|
||||||
|
const { variable, index, type } = props;
|
||||||
|
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
const [anchorEl, setAnchorEl] = React.useState(null);
|
const [anchorEl, setAnchorEl] = React.useState(null);
|
||||||
|
|
||||||
@@ -5600,29 +5612,148 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
setAnchorEl(event.currentTarget);
|
setAnchorEl(event.currentTarget);
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteVariable = (variableIndex) => {
|
const deleteVariable = (type, variableIndex) => {
|
||||||
//console.log("Delete:", variableName);
|
|
||||||
if (workflow.workflow_variables !== undefined && workflow.workflow_variables !== null && workflow.workflow_variables.length > variableIndex) {
|
|
||||||
workflow.workflow_variables.splice(variableIndex, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
//workflow.workflow_variables = workflow.workflow_variables.filter(
|
console.log("Delete type: ", type, variableIndex)
|
||||||
// (data) => data.name !== variableName
|
|
||||||
//);
|
if (type === "normal") {
|
||||||
setWorkflow(workflow);
|
if (workflow.workflow_variables !== undefined && workflow.workflow_variables !== null && workflow.workflow_variables.length > variableIndex) {
|
||||||
|
var vars = JSON.parse(JSON.stringify(workflow.workflow_variables))
|
||||||
|
vars.splice(variableIndex, 1)
|
||||||
|
workflow.workflow_variables = vars
|
||||||
|
|
||||||
|
console.log("Workflow after del: ", workflow)
|
||||||
|
|
||||||
|
setWorkflow(workflow);
|
||||||
|
setUpdate(Math.random());
|
||||||
|
}
|
||||||
|
} else if (type === "exec") {
|
||||||
|
if (workflow.execution_variables !== undefined && workflow.execution_variables !== null && workflow.execution_variables.length > variableIndex) {
|
||||||
|
var vars = JSON.parse(JSON.stringify(workflow.execution_variables))
|
||||||
|
vars.splice(variableIndex, 1)
|
||||||
|
workflow.execution_variables = vars
|
||||||
|
|
||||||
|
console.log("Workflow after del: ", workflow)
|
||||||
|
|
||||||
|
setWorkflow(workflow);
|
||||||
|
setUpdate(Math.random());
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteExecutionVariable = (variableIndex) => {
|
return (
|
||||||
if (workflow.execution_variables !== undefined && workflow.execution_variables !== null && workflow.execution_variables.length > variableIndex) {
|
<div key={index}>
|
||||||
workflow.execution_variables.splice(variableIndex, 1)
|
<Paper square style={paperVariableStyle} onClick={() => { }}>
|
||||||
}
|
<div
|
||||||
|
style={{
|
||||||
|
marginLeft: "10px",
|
||||||
|
marginTop: "5px",
|
||||||
|
marginBottom: "5px",
|
||||||
|
width: "2px",
|
||||||
|
backgroundColor: yellow,
|
||||||
|
marginRight: "5px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div style={{ display: "flex", width: "100%" }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: "10",
|
||||||
|
marginTop: "15px",
|
||||||
|
marginLeft: "10px",
|
||||||
|
overflow: "hidden",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setVariableInfo({
|
||||||
|
"name": variable.name,
|
||||||
|
"description": variable.description,
|
||||||
|
"value": variable.value,
|
||||||
|
"index": index,
|
||||||
|
})
|
||||||
|
|
||||||
//workflow.execution_variables = workflow.execution_variables.filter(
|
if (type === "normal") {
|
||||||
// (data) => data.name !== variableName
|
setVariablesModalOpen(true);
|
||||||
//);
|
} else if (type === "exec") {
|
||||||
setWorkflow(workflow);
|
setExecutionVariablesModalOpen(true);
|
||||||
};
|
} else {
|
||||||
|
console.log("Unknown type: ", type)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Name: {variable.name}
|
||||||
|
</div>
|
||||||
|
<div style={{ flex: "1", marginLeft: "0px" }}>
|
||||||
|
<IconButton
|
||||||
|
aria-label="more"
|
||||||
|
aria-controls="long-menu"
|
||||||
|
aria-haspopup="true"
|
||||||
|
onClick={menuClick}
|
||||||
|
style={{ color: "white" }}
|
||||||
|
>
|
||||||
|
<MoreVertIcon />
|
||||||
|
</IconButton>
|
||||||
|
<Menu
|
||||||
|
id="long-menu"
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
keepMounted
|
||||||
|
open={open}
|
||||||
|
PaperProps={{
|
||||||
|
style: {
|
||||||
|
backgroundColor: surfaceColor,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onClose={() => {
|
||||||
|
setOpen(false);
|
||||||
|
setAnchorEl(null);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MenuItem
|
||||||
|
style={{
|
||||||
|
backgroundColor: inputColor,
|
||||||
|
color: "white",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(false);
|
||||||
|
setVariableInfo({
|
||||||
|
"name": variable.name,
|
||||||
|
"description": variable.description,
|
||||||
|
"value": variable.value,
|
||||||
|
"index": index,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (type === "normal") {
|
||||||
|
setVariablesModalOpen(true);
|
||||||
|
} else if (type === "exec") {
|
||||||
|
setExecutionVariablesModalOpen(true);
|
||||||
|
} else {
|
||||||
|
console.log("Unknown type: ", type)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
key={"Edit"}
|
||||||
|
>
|
||||||
|
{"Edit"}
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
style={{
|
||||||
|
backgroundColor: inputColor,
|
||||||
|
color: "white",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
deleteVariable(type, index);
|
||||||
|
setOpen(false);
|
||||||
|
}}
|
||||||
|
key={"Delete"}
|
||||||
|
>
|
||||||
|
{"Delete"}
|
||||||
|
</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Paper>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const VariablesView = () => {
|
||||||
const variableScrollStyle = {
|
const variableScrollStyle = {
|
||||||
margin: 15,
|
margin: 15,
|
||||||
overflow: "scroll",
|
overflow: "scroll",
|
||||||
@@ -5642,108 +5773,20 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||||
>
|
>
|
||||||
WORKFLOW variables?
|
Workflow variables?
|
||||||
</a>
|
</a>
|
||||||
{workflow.workflow_variables === null
|
{workflow.workflow_variables === null
|
||||||
? null
|
? null
|
||||||
: workflow.workflow_variables.map((variable, index) => {
|
: workflow.workflow_variables.map((variable, varindex) => {
|
||||||
return (
|
return (
|
||||||
<div key={index}>
|
<VariableItem
|
||||||
<Paper square style={paperVariableStyle} onClick={() => { }}>
|
variable={variable}
|
||||||
<div
|
index={varindex}
|
||||||
style={{
|
type={"normal"}
|
||||||
marginLeft: "10px",
|
/>
|
||||||
marginTop: "5px",
|
|
||||||
marginBottom: "5px",
|
|
||||||
width: "2px",
|
|
||||||
backgroundColor: yellow,
|
|
||||||
marginRight: "5px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div style={{ display: "flex", width: "100%" }}>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
flex: "10",
|
|
||||||
marginTop: "15px",
|
|
||||||
marginLeft: "10px",
|
|
||||||
overflow: "hidden",
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
setVariableInfo({
|
|
||||||
"name": variable.name,
|
|
||||||
"description": variable.description,
|
|
||||||
"value": variable.value,
|
|
||||||
"index": index,
|
|
||||||
})
|
|
||||||
setVariablesModalOpen(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Name: {variable.name}
|
|
||||||
</div>
|
|
||||||
<div style={{ flex: "1", marginLeft: "0px" }}>
|
|
||||||
<IconButton
|
|
||||||
aria-label="more"
|
|
||||||
aria-controls="long-menu"
|
|
||||||
aria-haspopup="true"
|
|
||||||
onClick={menuClick}
|
|
||||||
style={{ color: "white" }}
|
|
||||||
>
|
|
||||||
<MoreVertIcon />
|
|
||||||
</IconButton>
|
|
||||||
<Menu
|
|
||||||
id="long-menu"
|
|
||||||
anchorEl={anchorEl}
|
|
||||||
keepMounted
|
|
||||||
open={open}
|
|
||||||
PaperProps={{
|
|
||||||
style: {
|
|
||||||
backgroundColor: surfaceColor,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
onClose={() => {
|
|
||||||
setOpen(false);
|
|
||||||
setAnchorEl(null);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MenuItem
|
|
||||||
style={{
|
|
||||||
backgroundColor: inputColor,
|
|
||||||
color: "white",
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
setOpen(false);
|
|
||||||
setVariableInfo({
|
|
||||||
"name": variable.name,
|
|
||||||
"description": variable.description,
|
|
||||||
"value": variable.value,
|
|
||||||
"index": index,
|
|
||||||
})
|
|
||||||
setVariablesModalOpen(true);
|
|
||||||
}}
|
|
||||||
key={"Edit"}
|
|
||||||
>
|
|
||||||
{"Edit"}
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem
|
|
||||||
style={{
|
|
||||||
backgroundColor: inputColor,
|
|
||||||
color: "white",
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
deleteVariable(index);
|
|
||||||
setOpen(false);
|
|
||||||
}}
|
|
||||||
key={"Delete"}
|
|
||||||
>
|
|
||||||
{"Delete"}
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Paper>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
||||||
<div style={{ flex: "1" }}>
|
<div style={{ flex: "1" }}>
|
||||||
<Button
|
<Button
|
||||||
fullWidth
|
fullWidth
|
||||||
@@ -5753,6 +5796,12 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setVariablesModalOpen(true);
|
setVariablesModalOpen(true);
|
||||||
setLastSaved(false);
|
setLastSaved(false);
|
||||||
|
|
||||||
|
setVariableInfo({
|
||||||
|
"name": "",
|
||||||
|
"description": "",
|
||||||
|
"value": "",
|
||||||
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
New workflow variable
|
New workflow variable
|
||||||
@@ -5774,109 +5823,18 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
style={{ textDecoration: "none", color: "#f85a3e" }}
|
style={{ textDecoration: "none", color: "#f85a3e" }}
|
||||||
>
|
>
|
||||||
EXECUTION variables?
|
Runtime variables?
|
||||||
</a>
|
</a>
|
||||||
{workflow.execution_variables === null ||
|
{workflow.execution_variables === null ||
|
||||||
workflow.execution_variables === undefined
|
workflow.execution_variables === undefined
|
||||||
? null
|
? null
|
||||||
: workflow.execution_variables.map((variable, index) => {
|
: workflow.execution_variables.map((variable, varindex2) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<VariableItem
|
||||||
<Paper square style={paperVariableStyle} onClick={() => { }}>
|
variable={variable}
|
||||||
<div
|
index={varindex2}
|
||||||
style={{
|
type={"exec"}
|
||||||
marginLeft: "10px",
|
/>
|
||||||
marginTop: "5px",
|
|
||||||
marginBottom: "5px",
|
|
||||||
width: "2px",
|
|
||||||
backgroundColor: yellow,
|
|
||||||
marginRight: "5px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div style={{ display: "flex", width: "100%" }}>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
flex: "10",
|
|
||||||
marginTop: "15px",
|
|
||||||
marginLeft: "10px",
|
|
||||||
overflow: "hidden",
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
//setNewVariableName(variable.name);
|
|
||||||
setVariableInfo({
|
|
||||||
"name": variable.name,
|
|
||||||
"description": variable.description,
|
|
||||||
"value": variable.value,
|
|
||||||
"index": index,
|
|
||||||
})
|
|
||||||
setExecutionVariablesModalOpen(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Name: {variable.name}
|
|
||||||
</div>
|
|
||||||
<div style={{ flex: "1", marginLeft: "0px" }}>
|
|
||||||
<IconButton
|
|
||||||
aria-label="more"
|
|
||||||
aria-controls="long-menu"
|
|
||||||
aria-haspopup="true"
|
|
||||||
onClick={menuClick}
|
|
||||||
style={{ color: "white" }}
|
|
||||||
>
|
|
||||||
<MoreVertIcon />
|
|
||||||
</IconButton>
|
|
||||||
<Menu
|
|
||||||
id="long-menu"
|
|
||||||
anchorEl={anchorEl}
|
|
||||||
keepMounted
|
|
||||||
open={open}
|
|
||||||
PaperProps={{
|
|
||||||
style: {
|
|
||||||
backgroundColor: surfaceColor,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
onClose={() => {
|
|
||||||
setOpen(false);
|
|
||||||
setAnchorEl(null);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MenuItem
|
|
||||||
style={{
|
|
||||||
backgroundColor: inputColor,
|
|
||||||
color: "white",
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
setOpen(false);
|
|
||||||
//setNewVariableName(variable.name);
|
|
||||||
setVariableInfo({
|
|
||||||
"name": variable.name,
|
|
||||||
"description": variable.description,
|
|
||||||
"value": variable.value,
|
|
||||||
"index": index,
|
|
||||||
})
|
|
||||||
setExecutionVariablesModalOpen(true);
|
|
||||||
}}
|
|
||||||
key={"Edit"}
|
|
||||||
>
|
|
||||||
{"Edit"}
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem
|
|
||||||
style={{
|
|
||||||
backgroundColor: inputColor,
|
|
||||||
color: "white",
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
deleteExecutionVariable(index);
|
|
||||||
setOpen(false);
|
|
||||||
}}
|
|
||||||
key={"Delete"}
|
|
||||||
>
|
|
||||||
{"Delete"}
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Paper>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<div style={{ flex: "1" }}>
|
<div style={{ flex: "1" }}>
|
||||||
@@ -5888,6 +5846,12 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setExecutionVariablesModalOpen(true);
|
setExecutionVariablesModalOpen(true);
|
||||||
setLastSaved(false);
|
setLastSaved(false);
|
||||||
|
|
||||||
|
setVariableInfo({
|
||||||
|
"name": "",
|
||||||
|
"description": "",
|
||||||
|
"value": "",
|
||||||
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
New execution variable
|
New execution variable
|
||||||
@@ -6401,6 +6365,13 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: overwrite category if the ACTION chosen has a different category
|
// FIXME: overwrite category if the ACTION chosen has a different category
|
||||||
|
//
|
||||||
|
|
||||||
|
if (!isCloud && (!app.is_valid || (!app.activated && app.generated))) {
|
||||||
|
console.log("NOT VALID: Activate!")
|
||||||
|
|
||||||
|
activateApp(app.id, false)
|
||||||
|
}
|
||||||
|
|
||||||
// const image = "url("+app.large_image+")"
|
// const image = "url("+app.large_image+")"
|
||||||
// FIXME - find the cytoscape offset position
|
// FIXME - find the cytoscape offset position
|
||||||
@@ -7539,11 +7510,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
example: "tmp",
|
example: "tmp",
|
||||||
})
|
})
|
||||||
|
|
||||||
if (
|
if (workflow.workflow_variables !== null && workflow.workflow_variables !== undefined && workflow.workflow_variables.length > 0) {
|
||||||
workflow.workflow_variables !== null &&
|
|
||||||
workflow.workflow_variables !== undefined &&
|
|
||||||
workflow.workflow_variables.length > 0
|
|
||||||
) {
|
|
||||||
for (let varkey in workflow.workflow_variables) {
|
for (let varkey in workflow.workflow_variables) {
|
||||||
const item = workflow.workflow_variables[varkey];
|
const item = workflow.workflow_variables[varkey];
|
||||||
actionlist.push({
|
actionlist.push({
|
||||||
@@ -14841,6 +14808,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
aria-labelledby="draggable-dialog-title"
|
aria-labelledby="draggable-dialog-title"
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setNewVariableName("");
|
setNewVariableName("");
|
||||||
|
setNewVariableValue("");
|
||||||
|
|
||||||
setExecutionVariablesModalOpen(false);
|
setExecutionVariablesModalOpen(false);
|
||||||
}}
|
}}
|
||||||
PaperProps={{
|
PaperProps={{
|
||||||
@@ -14849,7 +14818,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
backgroundColor: surfaceColor,
|
backgroundColor: surfaceColor,
|
||||||
color: "white",
|
color: "white",
|
||||||
border: theme.palette.defaultBorder,
|
border: theme.palette.defaultBorder,
|
||||||
maxWidth: "100%",
|
maxWidth: isMobile ? bodyWidth - 100 : 800,
|
||||||
|
minWidth: isMobile ? bodyWidth - 100 : 800,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -14879,15 +14849,32 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
margin="dense"
|
margin="dense"
|
||||||
|
label="Name"
|
||||||
fullWidth
|
fullWidth
|
||||||
defaultValue={newVariableName}
|
defaultValue={newVariableName}
|
||||||
/>
|
/>
|
||||||
|
<TextField
|
||||||
|
onBlur={(event) => setNewVariableValue(event.target.value)}
|
||||||
|
color="primary"
|
||||||
|
placeholder="Default Value (optional)"
|
||||||
|
style={{ marginTop: 25 }}
|
||||||
|
InputProps={{
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
margin="dense"
|
||||||
|
label="Default Value (optional)"
|
||||||
|
fullWidth
|
||||||
|
defaultValue={newVariableValue}
|
||||||
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button
|
<Button
|
||||||
style={{ borderRadius: "0px" }}
|
style={{ borderRadius: "0px" }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setNewVariableName("");
|
setNewVariableName("");
|
||||||
|
setNewVariableValue("");
|
||||||
setExecutionVariablesModalOpen(false);
|
setExecutionVariablesModalOpen(false);
|
||||||
}}
|
}}
|
||||||
color="primary"
|
color="primary"
|
||||||
@@ -14916,11 +14903,15 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
if (newVariableName.length > 0) {
|
if (newVariableName.length > 0) {
|
||||||
workflow.execution_variables[found].name = newVariableName;
|
workflow.execution_variables[found].name = newVariableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newVariableValue.length > 0) {
|
||||||
|
workflow.execution_variables[found].value = newVariableValue;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
workflow.execution_variables.push({
|
workflow.execution_variables.push({
|
||||||
name: newVariableName,
|
name: newVariableName,
|
||||||
|
value: newVariableValue,
|
||||||
description: "An execution variable",
|
description: "An execution variable",
|
||||||
value: "",
|
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ require (
|
|||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shuffle/shuffle-shared v0.3.75
|
github.com/shuffle/shuffle-shared v0.4.2
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|||||||
@@ -216,6 +216,8 @@ github.com/shuffle/shuffle-shared v0.3.51 h1:+JPEGw6R4a320who+SrGP/VqBxZdKPdcLw/
|
|||||||
github.com/shuffle/shuffle-shared v0.3.51/go.mod h1:jQrYySmvp/0De5ftrAaY6xwwr7TMfqBmBxQ2AX9yrjQ=
|
github.com/shuffle/shuffle-shared v0.3.51/go.mod h1:jQrYySmvp/0De5ftrAaY6xwwr7TMfqBmBxQ2AX9yrjQ=
|
||||||
github.com/shuffle/shuffle-shared v0.3.74 h1:i7M1Gug9j2Wa02WuSxKDbXoLvBWKW5Pxf/EpFy6v38Y=
|
github.com/shuffle/shuffle-shared v0.3.74 h1:i7M1Gug9j2Wa02WuSxKDbXoLvBWKW5Pxf/EpFy6v38Y=
|
||||||
github.com/shuffle/shuffle-shared v0.3.74/go.mod h1:jQrYySmvp/0De5ftrAaY6xwwr7TMfqBmBxQ2AX9yrjQ=
|
github.com/shuffle/shuffle-shared v0.3.74/go.mod h1:jQrYySmvp/0De5ftrAaY6xwwr7TMfqBmBxQ2AX9yrjQ=
|
||||||
|
github.com/shuffle/shuffle-shared v0.4.2 h1:GzDAOHN4YMMLzRmmToyO/KSYDziRuEuxLheawlAY3Rk=
|
||||||
|
github.com/shuffle/shuffle-shared v0.4.2/go.mod h1:jQrYySmvp/0De5ftrAaY6xwwr7TMfqBmBxQ2AX9yrjQ=
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
|||||||
+509
-209
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user