Added icons and better execution view
This commit is contained in:
@@ -84,13 +84,13 @@ There will be a major overhaul to the backend specifically. I'm currently moving
|
||||
- * Configuration - Write setup documentation - Did for docker
|
||||
- * Remove orborus? Can deploy straight, but that would be weird - Won't do this yet
|
||||
- * Full OpenAPI support with authentication schemes in App creator (not Oauth2 yet)
|
||||
- * Change workflow name
|
||||
- Workflows - IMPORT DEFAULT WORKFLOWS - Create some towards e.g. TheHive & MISP.
|
||||
- Documentation - General documentation /docs rewrite
|
||||
- API doc - 1. In Shuffle. 2. In e.g. python
|
||||
- Add random secret to orborus
|
||||
- Change workflow name
|
||||
- Fix scheduler
|
||||
- Use variables in e.g. JSON body
|
||||
- Add random secret to orborus
|
||||
|
||||
```
|
||||
# 1. export DATASTORE_EMULATOR_HOST=0.0.0.0:8000
|
||||
|
||||
@@ -24,7 +24,7 @@ import FormGroup from '@material-ui/core/FormGroup';
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||
import Checkbox from '@material-ui/core/Checkbox';
|
||||
|
||||
|
||||
import CreateIcon from '@material-ui/icons/Create';
|
||||
import PlayArrowIcon from '@material-ui/icons/PlayArrow';
|
||||
import AspectRatioIcon from '@material-ui/icons/AspectRatio';
|
||||
import MoreVertIcon from '@material-ui/icons/MoreVert';
|
||||
@@ -215,6 +215,8 @@ const AngularWorkflow = (props) => {
|
||||
});
|
||||
}
|
||||
|
||||
// Controls the colors and direction of execution results.
|
||||
// Style is in defaultCytoscapeStyle.js
|
||||
const handleUpdateResults = (responseJson) => {
|
||||
//console.log(responseJson)
|
||||
// Loop nodes and find results
|
||||
@@ -243,8 +245,8 @@ const AngularWorkflow = (props) => {
|
||||
currentnode.removeClass('success-highlight')
|
||||
currentnode.removeClass('failure-highlight')
|
||||
currentnode.removeClass('awaiting-data-highlight')
|
||||
currentnode.addClass('executing-highlight')
|
||||
incomingEdges.addClass('success-highlight')
|
||||
currentnode.addClass('executing-highlight')
|
||||
break
|
||||
case "WAITING":
|
||||
currentnode.removeClass('not-executing-highlight')
|
||||
@@ -325,11 +327,11 @@ const AngularWorkflow = (props) => {
|
||||
curelements[i].removeClass("executing-highlight")
|
||||
curelements[i].addClass("failure-highlight")
|
||||
} else {
|
||||
curelements[i].removeClass('not-executing-highlight')
|
||||
curelements[i].removeClass('executing-highlight')
|
||||
curelements[i].removeClass('success-highlight')
|
||||
curelements[i].removeClass('awaiting-data-highlight')
|
||||
curelements[i].removeClass('failure-highlight')
|
||||
//curelements[i].removeClass('not-executing-highlight')
|
||||
//curelements[i].removeClass('executing-highlight')
|
||||
//curelements[i].removeClass('success-highlight')
|
||||
//curelements[i].removeClass('awaiting-data-highlight')
|
||||
//curelements[i].removeClass('failure-highlight')
|
||||
}
|
||||
}
|
||||
} else if (responseJson.status === "FINISHED") {
|
||||
@@ -412,7 +414,7 @@ const AngularWorkflow = (props) => {
|
||||
|
||||
setLastSaved(true)
|
||||
fetch(globalUrl+"/api/v1/workflows/"+props.match.params.key, {
|
||||
method: 'PUT',
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
@@ -1378,7 +1380,7 @@ const AngularWorkflow = (props) => {
|
||||
|
||||
return (
|
||||
<div style={appViewStyle}>
|
||||
<div style={appScrollStyle}>
|
||||
<div style={variableScrollStyle}>
|
||||
{workflow.workflow_variables.map(variable=> {
|
||||
return (
|
||||
<div>
|
||||
@@ -2265,23 +2267,29 @@ const AngularWorkflow = (props) => {
|
||||
<div style={{flex: "10"}}>
|
||||
<b>{data.name}: </b>
|
||||
</div>
|
||||
<div style={{cursor: "pointer", color: staticcolor}} onClick={() => {
|
||||
changeActionParameterVariant("STATIC_VALUE", count)
|
||||
<Tooltip color="primary" title="Static data" placement="top">
|
||||
<div style={{cursor: "pointer", color: staticcolor}} onClick={() => {
|
||||
changeActionParameterVariant("STATIC_VALUE", count)
|
||||
}}>
|
||||
<CreateIcon />
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
|
||||
<Tooltip color="primary" title="Data from previous action" placement="top">
|
||||
<div style={{cursor: "pointer", color: actioncolor}} onClick={() => {
|
||||
changeActionParameterVariant("ACTION_RESULT", count)
|
||||
}}>
|
||||
static
|
||||
</div>
|
||||
<AppsIcon />
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
|
||||
<div style={{cursor: "pointer", color: actioncolor}} onClick={() => {
|
||||
changeActionParameterVariant("ACTION_RESULT", count)
|
||||
}}>
|
||||
action
|
||||
</div>
|
||||
|
|
||||
<div style={{cursor: "pointer", color: varcolor}} onClick={() => {
|
||||
changeActionParameterVariant("WORKFLOW_VARIABLE", count)
|
||||
}}>
|
||||
var
|
||||
</div>
|
||||
<Tooltip color="primary" title="Use local variable" placement="top">
|
||||
<div style={{cursor: "pointer", color: varcolor}} onClick={() => {
|
||||
changeActionParameterVariant("WORKFLOW_VARIABLE", count)
|
||||
}}>
|
||||
<FavoriteBorderIcon />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
{datafield}
|
||||
</div>
|
||||
@@ -3941,14 +3949,17 @@ const AngularWorkflow = (props) => {
|
||||
return null
|
||||
}
|
||||
|
||||
const cytoscapeViewWidths = 600
|
||||
const bottomBarStyle = {
|
||||
position: "fixed",
|
||||
right: 20,
|
||||
left: leftBarSize,
|
||||
bottom: 0,
|
||||
minWidth: "100%",
|
||||
minWidth: cytoscapeViewWidths,
|
||||
maxWidth: cytoscapeViewWidths,
|
||||
marginLeft: 20,
|
||||
marginBottom: 20,
|
||||
zIndex: 10,
|
||||
}
|
||||
|
||||
const topBarStyle= {
|
||||
@@ -3956,7 +3967,8 @@ const AngularWorkflow = (props) => {
|
||||
right: 0,
|
||||
left: leftBarSize,
|
||||
top: appBarSize,
|
||||
minWidth: "60%",
|
||||
minWidth: cytoscapeViewWidths,
|
||||
maxWidth: cytoscapeViewWidths,
|
||||
marginLeft: 20,
|
||||
marginBottom: 20,
|
||||
}
|
||||
|
||||
+2
-2
@@ -38,12 +38,12 @@ import AlertTemplate from "react-alert-template-basic";
|
||||
import { positions, Provider } from "react-alert";
|
||||
|
||||
// Testing - localhost
|
||||
//const globalUrl = "http://192.168.3.6:5001"
|
||||
const globalUrl = "http://192.168.3.6:5001"
|
||||
//console.log("HOST: ", process.env)
|
||||
|
||||
|
||||
// Production - backend proxy forwarding in nginx
|
||||
const globalUrl = window.location.origin
|
||||
//const globalUrl = window.location.origin
|
||||
|
||||
const surfaceColor = "#27292D"
|
||||
const inputColor = "#383B40"
|
||||
|
||||
+15
-3
@@ -8,6 +8,9 @@ import ListItem from '@material-ui/core/ListItem';
|
||||
|
||||
import Button from '@material-ui/core/Button';
|
||||
import HomeIcon from '@material-ui/icons/Home';
|
||||
import PolymerIcon from '@material-ui/icons/Polymer';
|
||||
import AppsIcon from '@material-ui/icons/Apps';
|
||||
import DescriptionIcon from '@material-ui/icons/Description';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
|
||||
const hoverColor = "#f85a3e"
|
||||
@@ -138,12 +141,18 @@ const Header = props => {
|
||||
<List style={{display: "flex", flexDirect: "row", flex: "1"}} component="nav">
|
||||
<ListItem style={{textAlign: "center"}}>
|
||||
<Link to="/workflows" style={hrefStyle}>
|
||||
<div onMouseOver={handleSoarHover} onMouseOut={handleSoarHoverOut} style={{color: SoarHoverColor, cursor: "pointer"}}>Workflows</div>
|
||||
<div onMouseOver={handleSoarHover} onMouseOut={handleSoarHoverOut} style={{color: SoarHoverColor, cursor: "pointer", display: "flex"}}>
|
||||
<PolymerIcon style={{marginRight: "5px"}} />
|
||||
<span style={{marginTop: 2}}>Workflows</span>
|
||||
</div>
|
||||
</Link>
|
||||
</ListItem>
|
||||
<ListItem style={{textAlign: "center"}}>
|
||||
<Link to="/apps" style={hrefStyle}>
|
||||
<div onMouseOver={handleHelpHover} onMouseOut={handleHelpHoverOut} style={{color: HelpHoverColor, cursor: "pointer"}}>Apps</div>
|
||||
<div onMouseOver={handleHelpHover} onMouseOut={handleHelpHoverOut} style={{color: HelpHoverColor, cursor: "pointer", display: "flex",}}>
|
||||
<AppsIcon style={{marginRight: "5px"}} />
|
||||
<span style={{marginTop: 2}}>Apps</span>
|
||||
</div>
|
||||
</Link>
|
||||
</ListItem>
|
||||
{/*
|
||||
@@ -155,7 +164,10 @@ const Header = props => {
|
||||
*/}
|
||||
<ListItem style={{textAlign: "center"}}>
|
||||
<Link to="/docs/about" style={hrefStyle}>
|
||||
<div onMouseOver={handleDocsHover} onMouseOut={handleDocsHoverOut} style={{color: DocsHoverColor, cursor: "pointer"}}>Docs</div>
|
||||
<div onMouseOver={handleDocsHover} onMouseOut={handleDocsHoverOut} style={{color: DocsHoverColor, cursor: "pointer", display: "flex"}}>
|
||||
<DescriptionIcon style={{marginRight: "5px"}} />
|
||||
<span style={{marginTop: 2}}>Docs</span>
|
||||
</div>
|
||||
</Link>
|
||||
</ListItem>
|
||||
{/*
|
||||
|
||||
+65
-28
@@ -3,6 +3,7 @@ import { useInterval } from 'react-powerhooks';
|
||||
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
import Divider from '@material-ui/core/Divider';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
@@ -10,10 +11,13 @@ import FormControl from '@material-ui/core/FormControl';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import Menu from '@material-ui/core/Menu';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
import MoreVertIcon from '@material-ui/icons/MoreVert';
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||
import Switch from '@material-ui/core/Switch';
|
||||
|
||||
import CachedIcon from '@material-ui/icons/Cached';
|
||||
import EditIcon from '@material-ui/icons/Edit';
|
||||
import MoreVertIcon from '@material-ui/icons/MoreVert';
|
||||
import PlayArrowIcon from '@material-ui/icons/PlayArrow';
|
||||
//import JSONPretty from 'react-json-pretty';
|
||||
//import JSONPrettyMon from 'react-json-pretty/dist/monikai'
|
||||
import ReactJson from 'react-json-view'
|
||||
@@ -43,8 +47,9 @@ const Workflows = (props) => {
|
||||
const [collapseJson, setCollapseJson] = React.useState(false)
|
||||
|
||||
const [modalOpen, setModalOpen] = React.useState(false);
|
||||
const [newWorkflowName, setNewWorkflowname] = React.useState("");
|
||||
const [newWorkflowName, setNewWorkflowName] = React.useState("");
|
||||
const [newWorkflowDescription, setNewWorkflowDescription] = React.useState("");
|
||||
const [editingWorkflow, setEditingWorkflow] = React.useState({})
|
||||
const { start, stop } = useInterval({
|
||||
duration: 5000,
|
||||
startImmediate: false,
|
||||
@@ -347,21 +352,28 @@ const Workflows = (props) => {
|
||||
aria-label="more"
|
||||
aria-controls="long-menu"
|
||||
aria-haspopup="true"
|
||||
style={{color: "white"}}
|
||||
onClick={menuClick}
|
||||
>
|
||||
<MoreVertIcon />
|
||||
</IconButton>
|
||||
<Menu
|
||||
id="long-menu"
|
||||
anchorEl={anchorEl}
|
||||
keepMounted
|
||||
open={open}
|
||||
onClose={() => {
|
||||
id="long-menu"
|
||||
anchorEl={anchorEl}
|
||||
keepMounted
|
||||
open={open}
|
||||
onClose={() => {
|
||||
setOpen(false)
|
||||
setAnchorEl(null)
|
||||
}}
|
||||
>
|
||||
>
|
||||
|
||||
<MenuItem style={{backgroundColor: surfaceColor, color: "white"}} onClick={() => {
|
||||
setModalOpen(true)
|
||||
setEditingWorkflow(data)
|
||||
setNewWorkflowName(data.name)
|
||||
setNewWorkflowDescription(data.description)
|
||||
}} key={"change"}>{"Change name"}</MenuItem>
|
||||
<MenuItem style={{backgroundColor: surfaceColor, color: "white"}} onClick={() => {
|
||||
copyWorkflow(data)
|
||||
setOpen(false)
|
||||
@@ -381,9 +393,17 @@ const Workflows = (props) => {
|
||||
<div style={{display: "flex", flex: "1"}}>
|
||||
<Grid item style={{flex: "1", justifyContent: "center"}}>
|
||||
<a href={"/workflows/"+data.id}>
|
||||
<Button style={{}} color="primary" variant="outlined" onClick={() => {}}>Edit</Button>
|
||||
<Tooltip color="primary" title="Edit workflow" placement="bottom">
|
||||
<Button style={{}} color="primary" variant="outlined" style={{marginRight: 10}} onClick={() => {}}>
|
||||
<EditIcon />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</a>
|
||||
<Button style={{}} color="primary" variant="outlined" onClick={() => executeWorkflow(data.id)}>Execute</Button>
|
||||
<Tooltip color="primary" title="Execute workflow" placement="bottom">
|
||||
<Button style={{}} color="primary" variant="outlined" onClick={() => executeWorkflow(data.id)}>
|
||||
<PlayArrowIcon />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Grid>
|
||||
</div>
|
||||
</Grid>
|
||||
@@ -504,7 +524,6 @@ const Workflows = (props) => {
|
||||
*/
|
||||
}
|
||||
|
||||
console.log(data)
|
||||
return (
|
||||
<Paper square style={resultPaperAppStyle} onClick={() => {}}>
|
||||
<div style={{marginLeft: "10px", marginTop: "5px", marginBottom: "5px", marginRight: "5px", width: boxWidth, backgroundColor: boxColor}}>
|
||||
@@ -555,7 +574,6 @@ const Workflows = (props) => {
|
||||
const ExecutionDetails = () => {
|
||||
var starttime = new Date(selectedExecution.started_at*1000)
|
||||
var endtime = new Date(selectedExecution.started_at*1000)
|
||||
console.log(selectedExecution)
|
||||
|
||||
const arg = selectedExecution.execution_argument !== undefined && selectedExecution.execution_argument.length > 0 ?
|
||||
<div>
|
||||
@@ -629,13 +647,24 @@ const Workflows = (props) => {
|
||||
if (newWorkflowName.length === 0) {
|
||||
return
|
||||
}
|
||||
var workflowdata = {
|
||||
"name": newWorkflowName,
|
||||
"description": newWorkflowDescription,
|
||||
|
||||
var method = "POST"
|
||||
var extraData = ""
|
||||
var workflowdata = {}
|
||||
|
||||
if (editingWorkflow.id !== undefined) {
|
||||
method = "PUT"
|
||||
extraData = "/"+editingWorkflow.id
|
||||
workflowdata = editingWorkflow
|
||||
}
|
||||
|
||||
fetch(globalUrl+"/api/v1/workflows", {
|
||||
method: 'POST',
|
||||
workflowdata["name"] = newWorkflowName
|
||||
workflowdata["description"] = newWorkflowDescription
|
||||
//console.log(workflowdata)
|
||||
//return
|
||||
|
||||
fetch(globalUrl+"/api/v1/workflows"+extraData, {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
@@ -650,9 +679,13 @@ const Workflows = (props) => {
|
||||
}
|
||||
return response.json()
|
||||
})
|
||||
.then((responseJson) => {
|
||||
window.location.pathname = "/workflows/"+responseJson["id"]
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (method === "POST") {
|
||||
window.location.pathname = "/workflows/"+responseJson["id"]
|
||||
} else {
|
||||
alert.info("Successfully changed basic info for workflow")
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
alert.error(error.toString())
|
||||
});
|
||||
@@ -674,7 +707,7 @@ const Workflows = (props) => {
|
||||
<DialogTitle><div style={{color: "white"}}>New workflow</div></DialogTitle>
|
||||
<DialogContent>
|
||||
<TextField
|
||||
onBlur={(event) => setNewWorkflowname(event.target.value)}
|
||||
onBlur={(event) => setNewWorkflowName(event.target.value)}
|
||||
InputProps={{
|
||||
style:{
|
||||
color: "white",
|
||||
@@ -683,6 +716,7 @@ const Workflows = (props) => {
|
||||
color="primary"
|
||||
placeholder="Name"
|
||||
margin="dense"
|
||||
defaultValue={newWorkflowName}
|
||||
fullWidth
|
||||
/>
|
||||
<TextField
|
||||
@@ -693,6 +727,7 @@ const Workflows = (props) => {
|
||||
},
|
||||
}}
|
||||
color="primary"
|
||||
defaultValue={newWorkflowDescription}
|
||||
placeholder="Description"
|
||||
margin="dense"
|
||||
fullWidth
|
||||
@@ -700,15 +735,15 @@ const Workflows = (props) => {
|
||||
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button style={{}} onClick={() => setModalOpen(false)} color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button style={{}} disabled={newWorkflowName.length === 0} onClick={() => {
|
||||
<Button style={{}} onClick={() => setModalOpen(false)} color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button style={{}} disabled={newWorkflowName.length === 0} onClick={() => {
|
||||
setNewWorkflow()
|
||||
setModalOpen(false)
|
||||
}} color="primary">
|
||||
Submit
|
||||
</Button>
|
||||
Submit
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</FormControl>
|
||||
</Dialog>
|
||||
@@ -763,7 +798,9 @@ const Workflows = (props) => {
|
||||
<h2>Executions</h2>
|
||||
</div>
|
||||
<div style={{flex: "1"}}>
|
||||
<Button color="primary" style={{marginTop: "20px"}} variant="outlined" onClick={() => {alert.info("Refreshing executions"); getWorkflowExecution(selectedWorkflow.id)}}>Refresh</Button>
|
||||
<Button color="primary" style={{marginTop: "20px"}} variant="outlined" onClick={() => {alert.info("Refreshing executions"); getWorkflowExecution(selectedWorkflow.id)}}>
|
||||
<CachedIcon />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Divider style={{marginBottom: "10px", height: "1px", width: "100%", backgroundColor: dividerColor}}/>
|
||||
|
||||
@@ -115,6 +115,8 @@ const data = [{
|
||||
selector: '.success-highlight',
|
||||
css: {
|
||||
'background-color': '#399645',
|
||||
'border-color': '#399645',
|
||||
'border-width': '5px',
|
||||
'transition-property': 'background-color',
|
||||
'transition-duration': '0.5s',
|
||||
},
|
||||
@@ -123,6 +125,8 @@ const data = [{
|
||||
selector: '.failure-highlight',
|
||||
css: {
|
||||
'background-color': '#8e3530',
|
||||
'border-color': '#8e3530',
|
||||
'border-width': '5px',
|
||||
'transition-property': 'background-color',
|
||||
'transition-duration': '0.5s',
|
||||
},
|
||||
@@ -141,7 +145,8 @@ const data = [{
|
||||
css: {
|
||||
'background-color': '#ffef47',
|
||||
'border-color': '#ffef47',
|
||||
'transition-property': '#ffef47',
|
||||
'border-width': '5px',
|
||||
'transition-property': 'border-width',
|
||||
'transition-duration': '0.25s',
|
||||
},
|
||||
},
|
||||
@@ -149,6 +154,8 @@ const data = [{
|
||||
selector: '.awaiting-data-highlight',
|
||||
css: {
|
||||
'background-color': '#f4ad42',
|
||||
'border-color': '#f4ad42',
|
||||
'border-width': '5px',
|
||||
'transition-property': 'background-color',
|
||||
'transition-duration': '0.5s',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user