Minor fixes for workflow and usecase management UIs

This commit is contained in:
frikky
2023-02-16 22:44:20 +01:00
parent 808c3befbf
commit f604068619
6 changed files with 67 additions and 59 deletions
@@ -55,6 +55,7 @@ const ConfigureWorkflow = (props) => {
workflowExecutions, workflowExecutions,
getWorkflowExecution, getWorkflowExecution,
} = props; } = props;
const [requiredActions, setRequiredActions] = React.useState([]); const [requiredActions, setRequiredActions] = React.useState([]);
const [requiredVariables, setRequiredVariables] = React.useState([]); const [requiredVariables, setRequiredVariables] = React.useState([]);
const [requiredTriggers, setRequiredTriggers] = React.useState([]); const [requiredTriggers, setRequiredTriggers] = React.useState([]);
-2
View File
@@ -194,13 +194,11 @@ const ParsedAction = (props) => {
if (paramcheck.id === "TOGGLED"){ if (paramcheck.id === "TOGGLED"){
setHideBody(false) setHideBody(false)
setActivateHidingBodyButton(false) setActivateHidingBodyButton(false)
console.log("TOGGLED BODY!")
} else { } else {
setHideBody(true) setHideBody(true)
if (paramcheck.id === "UNTOGGLED") { if (paramcheck.id === "UNTOGGLED") {
setActivateHidingBodyButton(false) setActivateHidingBodyButton(false)
console.log("UNTOGGLED!")
} }
} }
} }
+1 -1
View File
@@ -625,7 +625,7 @@ const SearchField = props => {
const CustomDocHits = connectHits(DocHits) const CustomDocHits = connectHits(DocHits)
return ( return (
<div ref={node} style={{width: "100%", maxWidth: 425, margin: "auto", position: "relative", zIndex: 10050,}}> <div ref={node} style={{width: "100%", maxWidth: 425, margin: "auto", position: "relative", }}>
<InstantSearch searchClient={searchClient} indexName="appsearch" onClick={() => { <InstantSearch searchClient={searchClient} indexName="appsearch" onClick={() => {
console.log("CLICKED") console.log("CLICKED")
}}> }}>
+6 -2
View File
@@ -811,7 +811,7 @@ const Admin = (props) => {
}) })
.then((responseJson) => { .then((responseJson) => {
if (responseJson["success"] === false) { if (responseJson["success"] === false) {
alert.error("Failed getting your org: ", responseJson.readon); alert.error("Failed getting your org. If this persists, please contact support.");
} else { } else {
if ( if (
responseJson.sync_features === undefined || responseJson.sync_features === undefined ||
@@ -883,17 +883,21 @@ const Admin = (props) => {
response.json().then((responseJson) => { response.json().then((responseJson) => {
if (responseJson["success"] === false) { if (responseJson["success"] === false) {
setLoginInfo("Error: " + responseJson.reason); setLoginInfo("Error: " + responseJson.reason);
alert.error("Failed to send email (2). Please try again and contact support if this persists.")
} else { } else {
setLoginInfo(""); setLoginInfo("");
setModalOpen(false); setModalOpen(false);
setTimeout(() => { setTimeout(() => {
getUsers(); getUsers();
}, 1000); }, 1000);
alert.info("Invite sent! They will show up in the list when they have accepted the invite.")
} }
}) })
) )
.catch((error) => { .catch((error) => {
console.log("Error in userdata: ", error); console.log("Error in userdata: ", error);
alert.error("Failed to send email. Please try again and contact support if this persists.")
}); });
}; };
@@ -3267,7 +3271,7 @@ const Admin = (props) => {
<DialogContent> <DialogContent>
{curTab === 1 && isCloud ? ( {curTab === 1 && isCloud ? (
<Typography variant="body1" style={{ marginBottom: 10 }}> <Typography variant="body1" style={{ marginBottom: 10 }}>
We'll send an email to invite them to your organization. We will send an email to invite them to your organization.
</Typography> </Typography>
) : curTab === 6 ? ( ) : curTab === 6 ? (
<Typography variant="body1" style={{ marginBottom: 10 }}> <Typography variant="body1" style={{ marginBottom: 10 }}>
+31 -29
View File
@@ -1737,7 +1737,7 @@ const AngularWorkflow = (defaultprops) => {
}) })
.then((response) => { .then((response) => {
if (response.status !== 200) { if (response.status !== 200) {
console.log("Status not 200 for apps :O!"); //console.log("Status not 200 for apps :O!");
return; return;
} }
@@ -1762,7 +1762,8 @@ const AngularWorkflow = (defaultprops) => {
} }
}) })
.catch((error) => { .catch((error) => {
alert.error(error.toString()); //alert.error(error.toString());
console.log("Error loading files: ", error)
}); });
}; };
@@ -2529,7 +2530,6 @@ const AngularWorkflow = (defaultprops) => {
// https://stackoverflow.com/questions/16677856/cy-onselect-callback-only-once // https://stackoverflow.com/questions/16677856/cy-onselect-callback-only-once
// onNodeClick // onNodeClick
const onNodeSelect = (event, newAppAuth) => { const onNodeSelect = (event, newAppAuth) => {
console.log("App auth in select: ", newAppAuth)
// Forces all states to update at the same time, // Forces all states to update at the same time,
// Otherwise everything is SUPER slow // Otherwise everything is SUPER slow
ReactDOM.unstable_batchedUpdates(() => { ReactDOM.unstable_batchedUpdates(() => {
@@ -2800,7 +2800,7 @@ const AngularWorkflow = (defaultprops) => {
} }
const tmpAuth = JSON.parse(JSON.stringify(newAppAuth)); const tmpAuth = JSON.parse(JSON.stringify(newAppAuth));
console.log("FOUND AUTH OPTIONS: ", tmpAuth) //console.log("FOUND AUTH OPTIONS: ", tmpAuth)
const curappName = curapp.name.toLowerCase() const curappName = curapp.name.toLowerCase()
for (let tmpAuthKey in tmpAuth) { for (let tmpAuthKey in tmpAuth) {
@@ -2836,8 +2836,6 @@ const AngularWorkflow = (defaultprops) => {
} }
} }
console.log("Options: ", authenticationOptions)
curaction.authentication = authenticationOptions; curaction.authentication = authenticationOptions;
if ( if (
curaction.selectedAuthentication === null || curaction.selectedAuthentication === null ||
@@ -5958,13 +5956,11 @@ const AngularWorkflow = (defaultprops) => {
//const activateApp = (appid) => { //const activateApp = (appid) => {
if (newAppData.activated === false) { if (newAppData.activated === false) {
console.log("SHOULD ACTIVATE!")
activateApp(newAppData.app_id, false) activateApp(newAppData.app_id, false)
} }
// AUTHENTICATION // AUTHENTICATION
if (app.authentication !== undefined && app.authentication !== null && app.authentication.required === true) { if (app.authentication !== undefined && app.authentication !== null && app.authentication.required === true) {
console.log("App auth is required!")
// Setup auth here :) // Setup auth here :)
const authenticationOptions = []; const authenticationOptions = [];
@@ -6233,7 +6229,8 @@ const AngularWorkflow = (defaultprops) => {
app.large_image = theme.palette.defaultImage app.large_image = theme.palette.defaultImage
} }
const image = app.large_image; const image = app.large_image !== undefined && app.large_image !== null && app.large_image !== "" ? app.large_image : theme.palette.defaultImage
const newAppStyle = JSON.parse(JSON.stringify(paperAppStyle)); const newAppStyle = JSON.parse(JSON.stringify(paperAppStyle));
const pixelSize = !hover ? "2px" : "4px"; const pixelSize = !hover ? "2px" : "4px";
//newAppStyle.borderLeft = app.is_valid && app.actions !== null && app.actions !== undefined && app.actions.length > 0 && !(app.activated && app.generated) //newAppStyle.borderLeft = app.is_valid && app.actions !== null && app.actions !== undefined && app.actions.length > 0 && !(app.activated && app.generated)
@@ -6328,7 +6325,7 @@ const AngularWorkflow = (defaultprops) => {
name: app.actions[0].name, name: app.actions[0].name,
parameters: parameters, parameters: parameters,
isStartNode: false, isStartNode: false,
large_image: app.large_image, large_image: image,
run_magic_output: false, run_magic_output: false,
authentication: [], authentication: [],
execution_variable: undefined, execution_variable: undefined,
@@ -7653,7 +7650,7 @@ const AngularWorkflow = (defaultprops) => {
<div style={{ display: "flex" }}> <div style={{ display: "flex" }}>
<Tooltip <Tooltip
color="primary" color="primary"
title={conditionValue.configuration ? "Negated" : "Default"} title={conditionValue.configuration ? "Opposite" : "Default"}
placement="top" placement="top"
> >
<span <span
@@ -13494,34 +13491,39 @@ const AngularWorkflow = (defaultprops) => {
<div style={{ display: "flex", marginTop: 10, marginBottom: 30 }}> <div style={{ display: "flex", marginTop: 10, marginBottom: 30 }}>
<div> <div>
{executionData.status !== undefined && {executionData.status !== undefined &&
executionData.status !== "ABORTED" && executionData.status !== "ABORTED" &&
executionData.status !== "FINISHED" && executionData.status !== "FINISHED" &&
executionData.status !== "FAILURE" && executionData.status !== "FAILURE" &&
executionData.status !== "WAITING" && executionData.status !== "WAITING" &&
!( !(executionData.results === undefined || executionData.results === null || (executionData.results.length === 0 && executionData.status === "EXECUTING")) ? (
executionData.results === undefined ||
executionData.results === null ||
(executionData.results.length === 0 && // probably ment to be around the or's
executionData.status === "EXECUTING")
) ? (
<div style={{ display: "flex" }}> <div style={{ display: "flex" }}>
<CircularProgress style={{ height: 45, width: 45, marginLeft: 20, marginRight: 20, }} /> <CircularProgress style={{ height: 45, width: 45, marginLeft: 20, marginRight: 20, }} onClick={() => {
console.log(environments, defaultEnvironmentIndex, nonskippedResults)
}} />
{environments.length > 0 && defaultEnvironmentIndex < environments.length && nonskippedResults.length === 0 && environments[defaultEnvironmentIndex].Name !== "Cloud" ?
{!isCloud && environments.length > 0 && defaultEnvironmentIndex < environments.length && nonskippedResults.length === 0 ?
<Typography variant="body2" color="textSecondary" style={{}}> <Typography variant="body2" color="textSecondary" style={{}}>
No results yet. Is Orborus running for the "{environments[defaultEnvironmentIndex].Name}" environment? <a href="/admin?tab=environments" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>Learn more</a> No results yet. Is Orborus running for the "{environments[defaultEnvironmentIndex].Name}" environment? <a href="/admin?tab=environments" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>Learn more</a>. If the Workflow doesn't start within 30 seconds with Orborus running, contact support: <a href="mailto:support@shuffler.io" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>support@shuffler.io</a>
</Typography> </Typography>
: null} : null}
</div> </div>
) : null} ) : null}
</div> </div>
</div> </div>
{executionData.results === undefined || {
executionData.results === undefined ||
executionData.results === null || executionData.results === null ||
(executionData.results.length === 0 && (executionData.results.length === 0 && executionData.status === "EXECUTING") ? (
executionData.status === "EXECUTING") ? (
<CircularProgress /> <div style={{ display: "flex" }}>
<CircularProgress style={{ height: 45, width: 45, marginLeft: 20, marginRight: 20, }} />
{environments.length > 0 && defaultEnvironmentIndex < environments.length && nonskippedResults.length === 0 && environments[defaultEnvironmentIndex].Name !== "Cloud" ?
<Typography variant="body2" color="textSecondary" style={{}}>
No results yet. Is Orborus running for the "{environments[defaultEnvironmentIndex].Name}" environment? <a href="/admin?tab=environments" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>Learn more</a>. If the Workflow doesn't start within 30 seconds with Orborus running, contact support: <a href="mailto:support@shuffler.io" rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", color: "#f86a3e" }}>support@shuffler.io</a>
</Typography>
:
null}
</div>
) : ( ) : (
executionData.results.map((data, index) => { executionData.results.map((data, index) => {
if (executionData.results.length !== 1 && !showSkippedActions && (data.status === "SKIPPED")) { if (executionData.results.length !== 1 && !showSkippedActions && (data.status === "SKIPPED")) {
+28 -25
View File
@@ -560,6 +560,9 @@ const Workflows = (props) => {
const [firstLoad, setFirstLoad] = React.useState(true); const [firstLoad, setFirstLoad] = React.useState(true);
const [showMoreClicked, setShowMoreClicked] = React.useState(false); const [showMoreClicked, setShowMoreClicked] = React.useState(false);
const [usecases, setUsecases] = React.useState([]); const [usecases, setUsecases] = React.useState([]);
const [allUsecases, setAllUsecases] = React.useState({
"success": false,
});
const [appFramework, setAppFramework] = React.useState({}); const [appFramework, setAppFramework] = React.useState({});
const [drawerOpen, setDrawerOpen] = React.useState(false) const [drawerOpen, setDrawerOpen] = React.useState(false)
const [videoViewOpen, setVideoViewOpen] = React.useState(false) const [videoViewOpen, setVideoViewOpen] = React.useState(false)
@@ -615,6 +618,7 @@ const Workflows = (props) => {
console.log("Using filters: ", filters) console.log("Using filters: ", filters)
if (filters.length === 0) { if (filters.length === 0) {
setFilteredWorkflows(workflows); setFilteredWorkflows(workflows);
handleKeysetting(allUsecases, workflows)
return; return;
} }
@@ -684,7 +688,10 @@ const Workflows = (props) => {
} }
} }
console.log("Changing workflow filter, and finding new usecase mappings!")
if (newWorkflows.length !== workflows.length) { if (newWorkflows.length !== workflows.length) {
handleKeysetting(allUsecases, newWorkflows)
setFilteredWorkflows(newWorkflows); setFilteredWorkflows(newWorkflows);
} }
}; };
@@ -715,7 +722,7 @@ const Workflows = (props) => {
var newfilters = filters; var newfilters = filters;
if (index < 0) { if (index < 0) {
console.log("Can't handle index: ", index); console.log("Can't handle index (remove): ", index);
return; return;
} }
@@ -1037,9 +1044,6 @@ const Workflows = (props) => {
newarray.push(wf) newarray.push(wf)
} }
// Workflows are set in here
fetchUsecases(newarray)
var setProdFilter = false var setProdFilter = false
@@ -1068,22 +1072,22 @@ const Workflows = (props) => {
if (setProdFilter === true) { if (setProdFilter === true) {
setFilters(["status:production"]);
const newWorkflows = newarray.filter(workflow => workflow.status === "production") const newWorkflows = newarray.filter(workflow => workflow.status === "production")
console.log(newWorkflows)
if (newWorkflows !== undefined && newWorkflows !== null) { if (newWorkflows !== undefined && newWorkflows !== null) {
setFilteredWorkflows(newWorkflows); setFilteredWorkflows(newWorkflows);
} else { } else {
setFilteredWorkflows(newarray); setFilteredWorkflows(newarray);
} }
setFilters(["status:production"]);
} else { } else {
setFilteredWorkflows(newarray); setFilteredWorkflows(newarray);
} }
// Ensures the zooming happens only once per load // Ensures the zooming happens only once per load
setTimeout(() => { setTimeout(() => {
fetchUsecases(newarray)
setFirstLoad(false) setFirstLoad(false)
}, 100) }, 100)
} else { } else {
@@ -1100,9 +1104,6 @@ const Workflows = (props) => {
}; };
const handleKeysetting = (categorydata, workflows) => { const handleKeysetting = (categorydata, workflows) => {
//workflows[0].category = ["detect"]
//workflows[0].usecase_ids = ["Correlate tickets"]
if (workflows !== undefined && workflows !== null) { if (workflows !== undefined && workflows !== null) {
var newcategories = [] var newcategories = []
for (var key in categorydata) { for (var key in categorydata) {
@@ -1145,8 +1146,6 @@ const Workflows = (props) => {
} else { } else {
setUsecases(categorydata) setUsecases(categorydata)
} }
setWorkflows(workflows);
setWorkflowDone(true);
} }
const fetchUsecases = (workflows) => { const fetchUsecases = (workflows) => {
@@ -1166,12 +1165,13 @@ const Workflows = (props) => {
return response.json(); return response.json();
}) })
.then((responseJson) => { .then((responseJson) => {
setWorkflows(workflows);
setWorkflowDone(true);
if (responseJson.success !== false) { if (responseJson.success !== false) {
setAllUsecases(responseJson);
handleKeysetting(responseJson, workflows) handleKeysetting(responseJson, workflows)
} else { }
setWorkflows(workflows);
setWorkflowDone(true);
}
}) })
.catch((error) => { .catch((error) => {
//alert.error("ERROR: " + error.toString()); //alert.error("ERROR: " + error.toString());
@@ -2764,7 +2764,9 @@ const Workflows = (props) => {
return ( return (
<span key={index}> <span key={index}>
<ListSubheader <ListSubheader
style={{color: usecase.color}} style={{
color: usecase.color
}}
> >
{usecase.name} {usecase.name}
</ListSubheader> </ListSubheader>
@@ -3285,12 +3287,15 @@ const Workflows = (props) => {
<div style={{ display: "flex", }}> <div style={{ display: "flex", }}>
{usecases.map((usecase, index) => { {usecases.map((usecase, index) => {
//console.log(usecase) //console.log(usecase)
const percentDone = usecase.matches.length > 0 ? parseInt(usecase.matches.length/usecase.list.length*100) : 0
return ( return (
<Paper <Paper
key={usecase.name} key={usecase.name}
style={{ style={{
flex: 1, flex: 1,
backgroundColor: filters.includes(usecase.name.toLowerCase()) ? usecase.color : theme.palette.surfaceColor, backgroundImage: `linear-gradient(to right, ${usecase.color}, ${usecase.color} ${percentDone}%, transparent ${percentDone}%, transparent 100%)`,
backgroundColor: filters.includes(usecase.name.toLowerCase()) ? null : theme.palette.surfaceColor,
borderRadius: theme.palette.borderRadius, borderRadius: theme.palette.borderRadius,
marginRight: index === usecases.length-1 ? 0 : 10, marginRight: index === usecases.length-1 ? 0 : 10,
cursor: "pointer", cursor: "pointer",
@@ -3299,25 +3304,23 @@ const Workflows = (props) => {
padding: 10, padding: 10,
}} }}
onClick={() => { onClick={() => {
console.log("Clicked!") console.log("Filters: ", filters, usecase.name.toLowerCase())
return if (!filters.includes(usecase.name.toLowerCase())) {
if (filters.includes(usecase.name.toLowerCase())) {
addFilter(usecase.name) addFilter(usecase.name)
} else { } else {
const foundIndex = filters.indexOf(usecase.name.toLowerCase()) removeFilter(filters.indexOf(usecase.name.toLowerCase()))
removeFilter(foundIndex)
} }
}} }}
> >
<a href={`/usecases?selected=${usecase.name}`} rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", display: "flex", }}> <span style={{ textDecoration: "none", display: "flex", }}>
<Typography variant="body1" color="textPrimary" style={{flex: 4, }}> <Typography variant="body1" color="textPrimary" style={{flex: 4, }}>
{usecase.name} {usecase.name}
</Typography> </Typography>
<Typography variant="body2" color="textSecondary" style={{flex: 1, marginTop: 5,}}> <Typography variant="body2" color="textSecondary" style={{flex: 1, marginTop: 5,}}>
{usecase.matches.length}/{usecase.list.length} {usecase.matches.length}/{usecase.list.length}
</Typography> </Typography>
</a> </span>
</Paper> </Paper>
) )
})} })}