enabled user input subflows and fixed bugs
This commit is contained in:
@@ -209,7 +209,7 @@ const Admin = (props) => {
|
||||
const [openEditor, setOpenEditor] = React.useState(false);
|
||||
const [renderTextBox, setRenderTextBox] = React.useState(false);
|
||||
const [openFileId, setOpenFileId] = React.useState(false);
|
||||
const allowedFileTypes = ["txt", "py", "yaml","yml","json"]
|
||||
const allowedFileTypes = ["txt", "py", "yaml", "yml","json", "html", "js", "csv",]
|
||||
|
||||
const runUpdateText = (text) =>{
|
||||
fetch(`${globalUrl}/api/v1/files/${openFileId}/edit`, {
|
||||
@@ -1017,6 +1017,36 @@ const Admin = (props) => {
|
||||
});
|
||||
};
|
||||
|
||||
const rerunCloudWorkflows = (environment) => {
|
||||
alert.info("Starting execution reruns. This can run in the background.")
|
||||
fetch(
|
||||
`${globalUrl}/api/v1/environments/${environment.id}/rerun`,
|
||||
{
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
}
|
||||
)
|
||||
.then((response) => {
|
||||
if (response.status !== 200) {
|
||||
console.log("Status not 200 for apps :O!");
|
||||
return;
|
||||
} else {
|
||||
alert.error(response.reason);
|
||||
//alert.info("Aborted all dangling workflows");
|
||||
}
|
||||
|
||||
return response.json();
|
||||
})
|
||||
.then((responseJson) => {
|
||||
console.log("Got response for execution: ", responseJson);
|
||||
//console.log("RESPONSE: ", responseJson)
|
||||
//setFiles(responseJson)
|
||||
})
|
||||
.catch((error) => {
|
||||
//alert.error(error.toString())
|
||||
});
|
||||
};
|
||||
|
||||
const abortEnvironmentWorkflows = (environment) => {
|
||||
//console.log("Aborting all workflows started >10 minutes ago, not finished");
|
||||
|
||||
@@ -3943,7 +3973,7 @@ const Admin = (props) => {
|
||||
<List>
|
||||
<ListItem>
|
||||
<ListItemText
|
||||
primary="Created"
|
||||
primary="Updated"
|
||||
style={{ maxWidth: 225, minWidth: 225 }}
|
||||
/>
|
||||
<ListItemText
|
||||
@@ -3989,7 +4019,8 @@ const Admin = (props) => {
|
||||
bgColor = "#1f2023";
|
||||
}
|
||||
|
||||
const isDisabledButton = isCloud || file.filesize < 100000 && file.status === ("active") && allowedFileTypes.includes(file.filename.split(".")[1]) === true
|
||||
const filenamesplit = file.filename.split(".")
|
||||
const iseditable = file.filesize < 100000 && file.status === "active" && allowedFileTypes.includes(filenamesplit[filenamesplit.length-1])
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
@@ -4006,7 +4037,7 @@ const Admin = (props) => {
|
||||
minWidth: 225,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
primary={new Date(file.created_at * 1000).toISOString()}
|
||||
primary={new Date(file.updated_at * 1000).toISOString()}
|
||||
/>
|
||||
<ListItemText
|
||||
style={{
|
||||
@@ -4099,13 +4130,13 @@ const Admin = (props) => {
|
||||
<ListItemText
|
||||
primary=<span style={{ display:"inline"}}>
|
||||
<Tooltip
|
||||
title={"Edit File"}
|
||||
title={`Edit File (${allowedFileTypes.join(", ")})`}
|
||||
style={{}}
|
||||
aria-label={"Edit"}
|
||||
>
|
||||
<span>
|
||||
<IconButton
|
||||
disabled={isDisabledButton ? false : true}
|
||||
disabled={!iseditable}
|
||||
style = {{padding: "6px"}}
|
||||
onClick={() => {
|
||||
setOpenEditor(true)
|
||||
@@ -4114,11 +4145,7 @@ const Admin = (props) => {
|
||||
}}
|
||||
>
|
||||
<EditIcon
|
||||
style={{
|
||||
color: isDisabledButton === true
|
||||
? "white"
|
||||
: "grey",
|
||||
}}
|
||||
style={{color: iseditable ? "white" : "grey",}}
|
||||
/>
|
||||
</IconButton>
|
||||
</span>
|
||||
@@ -4888,9 +4915,7 @@ const Admin = (props) => {
|
||||
>
|
||||
<div style={{ display: "flex" }}>
|
||||
<Button
|
||||
variant={
|
||||
environment.archived ? "contained" : "outlined"
|
||||
}
|
||||
variant={environment.archived ? "contained" : "outlined"}
|
||||
style={{ borderRadius: "0px" }}
|
||||
onClick={() => deleteEnvironment(environment)}
|
||||
color="primary"
|
||||
@@ -4900,16 +4925,19 @@ const Admin = (props) => {
|
||||
<Button
|
||||
variant={"outlined"}
|
||||
style={{ borderRadius: "0px" }}
|
||||
disabled={isCloud && environment.Name.toLowerCase() !== "cloud"}
|
||||
onClick={() => {
|
||||
console.log(
|
||||
"Should clear executions for: ",
|
||||
environment
|
||||
);
|
||||
abortEnvironmentWorkflows(environment);
|
||||
console.log("Should clear executions for: ", environment);
|
||||
|
||||
if (isCloud && environment.Name.toLowerCase() === "cloud") {
|
||||
rerunCloudWorkflows(environment);
|
||||
} else {
|
||||
abortEnvironmentWorkflows(environment);
|
||||
}
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
Clear
|
||||
{isCloud && environment.Name.toLowerCase() === "cloud" ? "Rerun" : "Clear"}
|
||||
</Button>
|
||||
</div>
|
||||
</ListItemText>
|
||||
|
||||
@@ -274,6 +274,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
const [triggerAuthentication, setTriggerAuthentication] = React.useState({});
|
||||
const [triggerFolders, setTriggerFolders] = React.useState([]);
|
||||
const [workflows, setWorkflows] = React.useState([]);
|
||||
const [parentWorkflows, setParentWorkflows] = React.useState([]);
|
||||
const [showEnvironment, setShowEnvironment] = React.useState(false);
|
||||
const [editWorkflowDetails, setEditWorkflowDetails] = React.useState(false);
|
||||
|
||||
@@ -487,7 +488,6 @@ const AngularWorkflow = (defaultprops) => {
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (responseJson !== undefined) {
|
||||
setWorkflows(responseJson);
|
||||
|
||||
// Sets up subflow trigger with the right info
|
||||
if (trigger_index > -1) {
|
||||
@@ -529,6 +529,37 @@ const AngularWorkflow = (defaultprops) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (workflows.length === 0) {
|
||||
//console.log("First request. Checking for parent trigger (if this is subflow")
|
||||
var parentworkflows = []
|
||||
for (let workflowkey in responseJson) {
|
||||
const innerworkflow = responseJson[workflowkey]
|
||||
|
||||
for (let triggerkey in innerworkflow.triggers) {
|
||||
const trigger = innerworkflow.triggers[triggerkey]
|
||||
if (trigger.trigger_type === "SUBFLOW") {
|
||||
|
||||
for (let paramkey in trigger.parameters) {
|
||||
const param = trigger.parameters[paramkey]
|
||||
if (param.name === "workflow" && param.value === props.match.params.key) {
|
||||
parentworkflows.push({
|
||||
id: innerworkflow.id,
|
||||
name: innerworkflow.name,
|
||||
image: innerworkflow.image,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parentworkflows.length > 0) {
|
||||
setParentWorkflows(parentworkflows.filter(wf => wf.id !== props.match.params.key))
|
||||
}
|
||||
}
|
||||
|
||||
setWorkflows(responseJson);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
@@ -2324,54 +2355,85 @@ const AngularWorkflow = (defaultprops) => {
|
||||
((nodedata.app_name !== "Shuffle Tools" &&
|
||||
nodedata.app_name !== "Testing" &&
|
||||
nodedata.app_name !== "Shuffle Workflow" &&
|
||||
nodedata.app_name !== "User Input" &&
|
||||
nodedata.app_name !== "Webhook" &&
|
||||
nodedata.app_name !== "Schedule" &&
|
||||
nodedata.app_name !== "Email") ||
|
||||
nodedata.app_name !== "User Input") ||
|
||||
nodedata.isStartNode)
|
||||
) {
|
||||
const allNodes = cy.nodes().jsons();
|
||||
var found = false;
|
||||
for (let nodekey in allNodes) {
|
||||
const currentNode = allNodes[nodekey];
|
||||
if (
|
||||
currentNode.data.attachedTo === nodedata.id &&
|
||||
currentNode.data.isDescriptor
|
||||
) {
|
||||
found = true;
|
||||
console.log("FOUND THE NODE!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
const allNodes = cy.nodes().jsons();
|
||||
var found = false;
|
||||
for (let nodekey in allNodes) {
|
||||
const currentNode = allNodes[nodekey];
|
||||
if (
|
||||
currentNode.data.attachedTo === nodedata.id &&
|
||||
currentNode.data.isDescriptor
|
||||
) {
|
||||
found = true;
|
||||
console.log("FOUND THE NODE!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Readding the icon after moving the node
|
||||
if (!found) {
|
||||
const iconInfo = GetIconInfo(nodedata);
|
||||
const svg_pin = `<svg width="${svgSize}" height="${svgSize}" viewBox="0 0 ${svgSize} ${svgSize}" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="${iconInfo.icon}" fill="${iconInfo.iconColor}"></path></svg>`;
|
||||
const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin);
|
||||
if (nodedata.app_name === "Webhook" || nodedata.app_name === "Schedule" || nodedata.app_name === "Gmail" || nodedata.app_name === "Office365") {
|
||||
console.log("Found triggers. Add!")
|
||||
|
||||
const offset = nodedata.isStartNode ? 36 : 44;
|
||||
const decoratorNode = {
|
||||
position: {
|
||||
x: event.target.position().x + offset,
|
||||
y: event.target.position().y + offset,
|
||||
},
|
||||
locked: true,
|
||||
data: {
|
||||
isDescriptor: true,
|
||||
isValid: true,
|
||||
is_valid: true,
|
||||
label: "",
|
||||
image: svgpin_Url,
|
||||
imageColor: iconInfo.iconBackgroundColor,
|
||||
attachedTo: nodedata.id,
|
||||
},
|
||||
};
|
||||
if (!found) {
|
||||
console.log("Find amount of executions for the specific nodetype: ", nodedata.app_name, "Executions: ", workflowExecutions)
|
||||
// Find how many executions it has
|
||||
var executions = 0
|
||||
const matchingExecutions = workflowExecutions.filter((execution => execution.execution_source === nodedata.app_name.toLowerCase()))
|
||||
console.log("Matches: ", matchingExecutions.length)
|
||||
const color = matchingExecutions.length > 0 ? "#34a853" : "#ea4436"
|
||||
const decoratorNode = {
|
||||
position: {
|
||||
x: event.target.position().x + 44,
|
||||
y: event.target.position().y + 44,
|
||||
},
|
||||
locked: true,
|
||||
data: {
|
||||
isDescriptor: true,
|
||||
isValid: true,
|
||||
is_valid: true,
|
||||
isTrigger: true,
|
||||
label: `${matchingExecutions.length}`,
|
||||
attachedTo: nodedata.id,
|
||||
imageColor: color,
|
||||
hasExecutions: true,
|
||||
},
|
||||
};
|
||||
|
||||
cy.add(decoratorNode).unselectify();
|
||||
} else {
|
||||
console.log("Node already exists - don't add descriptor node");
|
||||
}
|
||||
cy.add(decoratorNode)
|
||||
}
|
||||
} else {
|
||||
|
||||
|
||||
// Readding the icon after moving the node
|
||||
if (!found) {
|
||||
const iconInfo = GetIconInfo(nodedata);
|
||||
const svg_pin = `<svg width="${svgSize}" height="${svgSize}" viewBox="0 0 ${svgSize} ${svgSize}" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="${iconInfo.icon}" fill="${iconInfo.iconColor}"></path></svg>`;
|
||||
const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin);
|
||||
|
||||
const offset = nodedata.isStartNode ? 36 : 44;
|
||||
const decoratorNode = {
|
||||
position: {
|
||||
x: event.target.position().x + offset,
|
||||
y: event.target.position().y + offset,
|
||||
},
|
||||
locked: true,
|
||||
data: {
|
||||
isDescriptor: true,
|
||||
isValid: true,
|
||||
is_valid: true,
|
||||
label: "",
|
||||
image: svgpin_Url,
|
||||
imageColor: iconInfo.iconBackgroundColor,
|
||||
attachedTo: nodedata.id,
|
||||
},
|
||||
};
|
||||
|
||||
cy.add(decoratorNode).unselectify();
|
||||
} else {
|
||||
console.log("Node already exists - don't add descriptor node");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
originalLocation = {
|
||||
@@ -2676,6 +2738,11 @@ const AngularWorkflow = (defaultprops) => {
|
||||
return;
|
||||
} else if (data.isDescriptor) {
|
||||
console.log("Can't select descriptor");
|
||||
if (data.isTrigger) {
|
||||
console.log("But maybe we can select trigger descriptor? Maybe open execution tab?")
|
||||
setExecutionModalOpen(true)
|
||||
}
|
||||
|
||||
event.target.unselect();
|
||||
return;
|
||||
}
|
||||
@@ -4211,6 +4278,11 @@ const AngularWorkflow = (defaultprops) => {
|
||||
});
|
||||
};
|
||||
|
||||
const addRunCountButton = (event) => {
|
||||
// Count executions?
|
||||
// Maybe it shouldn't be onclick?
|
||||
}
|
||||
|
||||
const addCopyButton = (event) => {
|
||||
var parentNode = cy.$("#" + event.target.data("id"));
|
||||
if (parentNode.data("isButton") || parentNode.data("buttonId")) return;
|
||||
@@ -4379,7 +4451,52 @@ const AngularWorkflow = (defaultprops) => {
|
||||
//if (parentNode.data("isButton") || parentNode.data("buttonId")) return;
|
||||
|
||||
if (nodedata.app_name !== undefined && !workflow.public === true) {
|
||||
const allNodes = cy.nodes().jsons();
|
||||
const allNodes = cy.nodes().jsons();
|
||||
|
||||
if (nodedata.app_name === "Webhook" || nodedata.app_name === "Schedule" || nodedata.app_name === "Gmail" || nodedata.app_name === "Office365") {
|
||||
console.log("In this :)")
|
||||
|
||||
var found = false;
|
||||
for (let nodekey in allNodes) {
|
||||
const currentNode = allNodes[nodekey];
|
||||
if (
|
||||
currentNode.data.attachedTo === nodedata.id &&
|
||||
currentNode.data.isDescriptor
|
||||
) {
|
||||
found = true;
|
||||
console.log("FOUND THE NODE!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
console.log("Find amount of executions for the specific nodetype: ", nodedata.app_name, "Executions: ", workflowExecutions)
|
||||
// Find how many executions it has
|
||||
var executions = 0
|
||||
const matchingExecutions = workflowExecutions.filter((execution => execution.execution_source === nodedata.app_name.toLowerCase()))
|
||||
console.log("Matches: ", matchingExecutions.length)
|
||||
const color = matchingExecutions.length > 0 ? "#34a853" : "#ea4436"
|
||||
const decoratorNode = {
|
||||
position: {
|
||||
x: event.target.position().x + 44,
|
||||
y: event.target.position().y + 44,
|
||||
},
|
||||
locked: true,
|
||||
data: {
|
||||
isDescriptor: true,
|
||||
isValid: true,
|
||||
is_valid: true,
|
||||
isTrigger: true,
|
||||
label: `${matchingExecutions.length}`,
|
||||
attachedTo: nodedata.id,
|
||||
imageColor: color,
|
||||
hasExecutions: true,
|
||||
},
|
||||
};
|
||||
|
||||
cy.add(decoratorNode)
|
||||
}
|
||||
}
|
||||
|
||||
var found = false;
|
||||
for (var _key in allNodes) {
|
||||
@@ -4413,7 +4530,10 @@ const AngularWorkflow = (defaultprops) => {
|
||||
if (nodedata.type === "TRIGGER") {
|
||||
if (nodedata.trigger_type === "SUBFLOW" || nodedata.trigger_type === "USERINPUT") {
|
||||
addCopyButton(event);
|
||||
}
|
||||
} else {
|
||||
// Check how many executions from the source
|
||||
addRunCountButton(event);
|
||||
}
|
||||
} else {
|
||||
addCopyButton(event);
|
||||
addStartnodeButton(event);
|
||||
@@ -4467,7 +4587,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
// locked: true,
|
||||
// })
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.target !== undefined && event.target !== null) {
|
||||
event.target.animate(
|
||||
@@ -4722,6 +4842,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
return decoratorNode;
|
||||
});
|
||||
|
||||
|
||||
const triggers = workflow.triggers.map((trigger) => {
|
||||
const node = {};
|
||||
node.position = trigger.position;
|
||||
@@ -5017,14 +5138,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
}
|
||||
|
||||
// App length necessary cus of cy initialization
|
||||
if (
|
||||
// First load - gets the workflow
|
||||
elements.length === 0 &&
|
||||
workflow.actions !== undefined &&
|
||||
!graphSetup &&
|
||||
Object.getOwnPropertyNames(workflow).length > 0
|
||||
) {
|
||||
|
||||
if (elements.length === 0 && workflow.actions !== undefined && !graphSetup && Object.getOwnPropertyNames(workflow).length > 0) {
|
||||
setGraphSetup(true);
|
||||
setupGraph();
|
||||
console.log("In graph setup")
|
||||
@@ -10073,6 +10187,10 @@ const AngularWorkflow = (defaultprops) => {
|
||||
name: "custom_response_body",
|
||||
value: "",
|
||||
};
|
||||
workflow.triggers[selectedTriggerIndex].parameters[4] = {
|
||||
name: "await_response",
|
||||
value: "v1",
|
||||
};
|
||||
setWorkflow(workflow);
|
||||
} else {
|
||||
// Always update
|
||||
@@ -11065,26 +11183,6 @@ const AngularWorkflow = (defaultprops) => {
|
||||
style={{ paddingLeft: 10, backgroundColor: inputColor }}
|
||||
row
|
||||
>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={
|
||||
workflow.triggers[selectedTriggerIndex].parameters[2] !==
|
||||
undefined &&
|
||||
workflow.triggers[
|
||||
selectedTriggerIndex
|
||||
].parameters[2].value.includes("subflow")
|
||||
}
|
||||
onChange={() => {
|
||||
setTriggerOptionsWrapper("subflow");
|
||||
}}
|
||||
color="primary"
|
||||
value="subflow"
|
||||
disabled
|
||||
/>
|
||||
}
|
||||
label={<div style={{ color: "white" }}>Subflow</div>}
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
@@ -11119,12 +11217,23 @@ const AngularWorkflow = (defaultprops) => {
|
||||
}
|
||||
label={<div style={{ color: "white" }}>SMS</div>}
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={workflow.triggers[selectedTriggerIndex].parameters[2] !== undefined && workflow.triggers[selectedTriggerIndex].parameters[2].value.includes("subflow")}
|
||||
onChange={() => {
|
||||
setTriggerOptionsWrapper("subflow");
|
||||
}}
|
||||
color="primary"
|
||||
value="subflow"
|
||||
/>
|
||||
}
|
||||
label={<div style={{ color: "white" }}>Subflow</div>}
|
||||
/>
|
||||
</FormGroup>
|
||||
{workflow.triggers[selectedTriggerIndex].parameters[2] !==
|
||||
undefined &&
|
||||
workflow.triggers[
|
||||
selectedTriggerIndex
|
||||
].parameters[2].value.includes("email") ? (
|
||||
workflow.triggers[selectedTriggerIndex].parameters[2].value.includes("email") ? (
|
||||
<TextField
|
||||
style={{
|
||||
backgroundColor: inputColor,
|
||||
@@ -11187,11 +11296,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
{workflow.triggers[selectedTriggerIndex].parameters[2] !==
|
||||
undefined &&
|
||||
workflow.triggers[
|
||||
selectedTriggerIndex
|
||||
].parameters[2].value.includes("subflow") ? (
|
||||
{workflow.triggers[selectedTriggerIndex].parameters[2] !== undefined && workflow.triggers[selectedTriggerIndex].parameters[2].value.includes("subflow") ? (
|
||||
<TextField
|
||||
style={{
|
||||
backgroundColor: inputColor,
|
||||
@@ -11213,8 +11318,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
workflow.triggers[selectedTriggerIndex].parameters[5].value
|
||||
}
|
||||
onBlur={(event) => {
|
||||
workflow.triggers[selectedTriggerIndex].parameters[5].value =
|
||||
event.target.value;
|
||||
workflow.triggers[selectedTriggerIndex].parameters[5].value = event.target.value;
|
||||
setWorkflow(workflow);
|
||||
setUpdate(Math.random());
|
||||
}}
|
||||
@@ -11565,6 +11669,36 @@ const AngularWorkflow = (defaultprops) => {
|
||||
<h2 style={{ margin: 0 }}>{workflow.name}</h2>
|
||||
</Breadcrumbs>
|
||||
</div>
|
||||
<div style={{display: "flex", marginLeft: 10, }}>
|
||||
{parentWorkflows.slice(0,5).map((wf, index) => {
|
||||
return (
|
||||
<a href={`/workflows/${wf.id}`} target="_blank" rel="noopener noreferrer" key={index}>
|
||||
<Tooltip arrow placement="left" title={
|
||||
<span style={{}}>
|
||||
{wf.image !== undefined && wf.image !== null && wf.image.length > 0 ?
|
||||
<img
|
||||
src={wf.image}
|
||||
alt={wf.name}
|
||||
style={{ backgroundColor: theme.palette.surfaceColor, maxHeight: 200, minHeigth: 200, borderRadius: theme.palette.borderRadius, }}
|
||||
|
||||
/>
|
||||
: null}
|
||||
<Typography>
|
||||
Parent workflow: '{wf.name}'
|
||||
</Typography>
|
||||
</span>
|
||||
|
||||
} placement="bottom">
|
||||
<span onClick={() => {
|
||||
console.log("Click: ", wf)
|
||||
}}>
|
||||
<img src={theme.palette.defaultImage} style={{height: 25, width: 25, cursor: "pointer", border: 15, marginRight: 5, marginTop: 5, filter: "grayscale(90%)", }} />
|
||||
</span>
|
||||
</Tooltip>
|
||||
</a>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -14146,6 +14280,7 @@ const AngularWorkflow = (defaultprops) => {
|
||||
width: imgsize,
|
||||
height: imgsize,
|
||||
border: `2px solid ${statusColor}`,
|
||||
filter: curapp === undefined ? "grayscale(100%)" : null,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -222,22 +222,23 @@ const parseCurl = (s) => {
|
||||
return out;
|
||||
};
|
||||
|
||||
// Basically CRUD for each category + special
|
||||
export const appCategories = [
|
||||
{
|
||||
"name": "Communication",
|
||||
"color": "#FFC107",
|
||||
"icon": "communication",
|
||||
"action_labels": ["List Messages", "Send Message",],
|
||||
"action_labels": ["List Messages", "Send Message", "Get Message", "Search messages"],
|
||||
}, {
|
||||
"name": "SIEM",
|
||||
"color": "#FFC107",
|
||||
"icon": "siem",
|
||||
"action_labels": ["Get alerts", "Search", "Create detection",],
|
||||
"action_labels": ["List Alerts", "Search", "Create detection", "Add hash to lookup_list",],
|
||||
}, {
|
||||
"name": "Eradication",
|
||||
"color": "#FFC107",
|
||||
"icon": "eradication",
|
||||
"action_labels": ["List tickets", "Update ticket", "Block hash", "Isolate host"],
|
||||
"action_labels": ["List Alerts", "Update Alert", "Create detection", "Block hash", "Search Hosts", "Isolate host"],
|
||||
}, {
|
||||
"name": "Cases",
|
||||
"color": "#FFC107",
|
||||
@@ -247,27 +248,27 @@ export const appCategories = [
|
||||
"name": "Assets",
|
||||
"color": "#FFC107",
|
||||
"icon": "assets",
|
||||
"action_labels": [],
|
||||
"action_labels": ["List Assets", "Get Asset", "Search Assets", "Search Users", "Search endpoints", "Search vulnerabilities"],
|
||||
}, {
|
||||
"name": "Intel",
|
||||
"color": "#FFC107",
|
||||
"icon": "intel",
|
||||
"action_labels": [],
|
||||
"action_labels": ["Get IOC", "Search IOC", "Create IOC", "Update IOC", "Delete IOC", "Add IOC",],
|
||||
}, {
|
||||
"name": "IAM",
|
||||
"color": "#FFC107",
|
||||
"icon": "iam",
|
||||
"action_labels": [],
|
||||
"action_labels": ["Get Identity", "Get Asset", "Search Identity", "Reset Password", "Disable user", ],
|
||||
}, {
|
||||
"name": "Network",
|
||||
"color": "#FFC107",
|
||||
"icon": "network",
|
||||
"action_labels": ["Block IP",],
|
||||
"action_labels": ["Get Rules", "Allow IP", "Block IP",],
|
||||
}, {
|
||||
"name": "Other",
|
||||
"color": "#FFC107",
|
||||
"icon": "other",
|
||||
"action_labels": [],
|
||||
"action_labels": ["Update Info", "Get Info", "Get Status", "Get Version", "Get Health", "Get Config", "Get Configs", "Get Configs by type", "Get Configs by name", "Run script"],
|
||||
},
|
||||
]
|
||||
|
||||
@@ -3152,11 +3153,15 @@ const AppCreator = (defaultprops) => {
|
||||
<Select
|
||||
fullWidth
|
||||
onChange={(e) => {
|
||||
console.log("Should change: ", e.target.value)
|
||||
console.log("Should change: ", e.target.value, " Index: ", index)
|
||||
|
||||
actions[index].action_label = e.target.value
|
||||
setActions(actions)
|
||||
setUpdate(Math.random());
|
||||
const foundIndex = actions.findIndex((action) => action.name === data.name)
|
||||
console.log("Found index: ", foundIndex)
|
||||
if (foundIndex !== undefined && foundIndex !== null && foundIndex >= 0) {
|
||||
actions[foundIndex].action_label = e.target.value
|
||||
setActions(actions)
|
||||
setUpdate(Math.random())
|
||||
}
|
||||
}}
|
||||
value={data.action_label}
|
||||
style={{
|
||||
|
||||
@@ -99,6 +99,7 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
const [description, setDescription] = useState("");
|
||||
const [video, setVideo] = useState("");
|
||||
const [blogpost, setBlogpost] = useState("");
|
||||
const [workflowOutline, setWorkflowOutline] = useState("");
|
||||
|
||||
const [selectedWorkflows, setSelectedWorkflows] = useState([])
|
||||
const [firstLoad, setFirstLoad] = useState(true)
|
||||
@@ -188,6 +189,11 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
parsedUsecase.mitre = mitreTags
|
||||
}
|
||||
|
||||
if (workflowOutline !== inputUsecase.workflow_outline) {
|
||||
inputUsecase.workflow_outline = workflowOutline
|
||||
parsedUsecase.workflow_outline = workflowOutline
|
||||
}
|
||||
|
||||
fetch(globalUrl + "/api/v1/workflows/usecases", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
@@ -303,6 +309,10 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
if (inputUsecase.extra_buttons !== undefined && inputUsecase.extra_buttons !== null) {
|
||||
subcase.extra_buttons = inputUsecase.extra_buttons
|
||||
}
|
||||
|
||||
if (inputUsecase.workflow_outline !== undefined && inputUsecase.workflow_outline !== null) {
|
||||
subcase.workflow_outline = inputUsecase.workflow_outline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,6 +443,12 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
if (subcase.mitre !== undefined && subcase.mitre !== null) {
|
||||
setMitreTags(subcase.mitre)
|
||||
}
|
||||
|
||||
if (subcase.workflow_outline !== undefined && subcase.workflow_outline !== null) {
|
||||
setWorkflowOutline(subcase.workflow_outline)
|
||||
} else {
|
||||
setWorkflowOutline("")
|
||||
}
|
||||
}}
|
||||
>
|
||||
<EditIcon style={{ color: usecase.color }} />
|
||||
@@ -502,9 +518,6 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
<div style={{marginTop: 25, display: "flex", minHeight: 400, maxHeight: 400, marginRight: 15, }}>
|
||||
{editing ?
|
||||
<div style={{flex: 1, marginRight: 50, }}>
|
||||
<Typography variant="h6">
|
||||
Editing!
|
||||
</Typography>
|
||||
<TextField
|
||||
style={{
|
||||
marginTop: 10,
|
||||
@@ -553,6 +566,26 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
}}
|
||||
id="videoEditing"
|
||||
/>
|
||||
<TextField
|
||||
style={{
|
||||
marginTop: 10,
|
||||
marginRight: 10,
|
||||
}}
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
color="primary"
|
||||
label="Workflow Outline"
|
||||
placeholder={"Workflow Outline"}
|
||||
value={workflowOutline}
|
||||
multiline
|
||||
minRows={3}
|
||||
onChange={(event) => {
|
||||
setWorkflowOutline(event.target.value)
|
||||
}}
|
||||
id="workflowOutline"
|
||||
tabIndex="-1"
|
||||
/>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
@@ -573,6 +606,7 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
setDescription("")
|
||||
setVideo("")
|
||||
setBlogpost("")
|
||||
setWorkflowOutline("")
|
||||
setEditing(false)
|
||||
}}
|
||||
>
|
||||
@@ -590,10 +624,11 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
cursor: "pointer"
|
||||
}}
|
||||
onClick={(event) => {
|
||||
setEditing(false)
|
||||
setUsecaseItem(inputUsecase)
|
||||
setEditing(false)
|
||||
setDescription("")
|
||||
setVideo("")
|
||||
setWorkflowOutline("")
|
||||
setBlogpost("")
|
||||
}}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user