Added execution view drawer
This commit is contained in:
+166
-43
@@ -29,6 +29,7 @@ import Breadcrumbs from '@material-ui/core/Breadcrumbs';
|
||||
import CircularProgress from '@material-ui/core/CircularProgress';
|
||||
import ReactJson from 'react-json-view'
|
||||
|
||||
import DirectionsRunIcon from '@material-ui/icons/DirectionsRun';
|
||||
import PolymerIcon from '@material-ui/icons/Polymer';
|
||||
import CreateIcon from '@material-ui/icons/Create';
|
||||
import PlayArrowIcon from '@material-ui/icons/PlayArrow';
|
||||
@@ -155,7 +156,8 @@ const AngularWorkflow = (props) => {
|
||||
|
||||
const [, setExecutingNodes] = React.useState([])
|
||||
const [executionRunning, setExecutionRunning] = React.useState(false)
|
||||
const [executionModalOpen, setExecutionModalOpen] = React.useState(true)
|
||||
const [executionModalOpen, setExecutionModalOpen] = React.useState(false)
|
||||
const [executionModalView, setExecutionModalView] = React.useState(0)
|
||||
const [executionData, setExecutionData] = React.useState({})
|
||||
|
||||
const [lastSaved, setLastSaved] = React.useState(true)
|
||||
@@ -280,8 +282,11 @@ const AngularWorkflow = (props) => {
|
||||
// Update on every interval? idk
|
||||
|
||||
if (JSON.stringify(responseJson) !== JSON.stringify(executionData)) {
|
||||
console.log("Executiondata: ", responseJson)
|
||||
setExecutionData(responseJson)
|
||||
// FIXME: If another is selected, don't edit..
|
||||
// Doesn't work because this is some async garbage
|
||||
if (executionData.execution_id === undefined || responseJson.execution_id === executionData.execution_id) {
|
||||
setExecutionData(responseJson)
|
||||
}
|
||||
}
|
||||
if (responseJson.execution_id !== executionRequest.execution_id) {
|
||||
cy.elements().removeClass('success-highlight failure-highlight executing-highlight')
|
||||
@@ -340,7 +345,8 @@ const AngularWorkflow = (props) => {
|
||||
|
||||
if (!visited.includes(item.action.label)) {
|
||||
if (executionRunning) {
|
||||
alert.show("Success for "+item.action.label+" with result "+item.result)
|
||||
alert.show("Success in node "+item.action.label)
|
||||
//+" with result "+item.result)
|
||||
visited.push(item.action.label)
|
||||
setVisited(visited)
|
||||
}
|
||||
@@ -656,6 +662,7 @@ const AngularWorkflow = (props) => {
|
||||
setExecutingNodes([workflow.start])
|
||||
setExecutionData({})
|
||||
setExecutionModalOpen(true)
|
||||
setExecutionModalView(1)
|
||||
start()
|
||||
})
|
||||
.catch(error => {
|
||||
@@ -1457,8 +1464,20 @@ const AngularWorkflow = (props) => {
|
||||
}
|
||||
|
||||
const handleVariablesHoverOut = () => {
|
||||
setVariablesHoverColor(hoverOutColor)
|
||||
}
|
||||
setVariablesHoverColor(hoverOutColor)
|
||||
}
|
||||
|
||||
const paperVariableStyle = {
|
||||
minHeight: "50px",
|
||||
maxHeight: "50px",
|
||||
minWidth: "100%",
|
||||
maxWidth: "100%",
|
||||
marginTop: "5px",
|
||||
color: "white",
|
||||
backgroundColor: surfaceColor,
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
}
|
||||
|
||||
const VariablesView = () => {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
@@ -1478,19 +1497,7 @@ const AngularWorkflow = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const paperVariableStyle = {
|
||||
minHeight: "50px",
|
||||
maxHeight: "50px",
|
||||
minWidth: "100%",
|
||||
maxWidth: "100%",
|
||||
marginTop: "5px",
|
||||
color: "white",
|
||||
backgroundColor: surfaceColor,
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
}
|
||||
}
|
||||
|
||||
const menuClick = (event) => {
|
||||
setOpen(!open)
|
||||
@@ -4184,7 +4191,7 @@ const AngularWorkflow = (props) => {
|
||||
return null
|
||||
}
|
||||
|
||||
const cytoscapeViewWidths = 600
|
||||
const cytoscapeViewWidths = 650
|
||||
const bottomBarStyle = {
|
||||
position: "fixed",
|
||||
right: 20,
|
||||
@@ -4271,8 +4278,11 @@ const AngularWorkflow = (props) => {
|
||||
style={{backgroundColor: inputColor, }}
|
||||
InputProps={{
|
||||
style:{
|
||||
color: "white",
|
||||
height: 50,
|
||||
color: "white",
|
||||
marginLeft: 5,
|
||||
maxWidth: "95%",
|
||||
fontSize: "1em",
|
||||
},
|
||||
}}
|
||||
color="secondary"
|
||||
@@ -4300,6 +4310,13 @@ const AngularWorkflow = (props) => {
|
||||
<DeleteIcon />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip color="secondary" title="Show executions" placement="top-start">
|
||||
<Button color="primary" style={{height: 50, marginLeft: 10, }} variant="outlined" onClick={() => {
|
||||
setExecutionModalOpen(true)
|
||||
}}>
|
||||
<DirectionsRunIcon />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -4389,21 +4406,118 @@ const AngularWorkflow = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
const ExecutionModal = () => {
|
||||
return (
|
||||
<Drawer anchor={"right"} open={executionModalOpen} onClose={() => setExecutionModalOpen(false)}>
|
||||
<div style={{padding: 20, maxWidth: 250, minWidth: 250,}}>
|
||||
const executionPaperStyle = {
|
||||
minWidth: "95%",
|
||||
maxWidth: "95%",
|
||||
marginTop: "5px",
|
||||
color: "white",
|
||||
marginBottom: 10,
|
||||
padding: 5,
|
||||
backgroundColor: surfaceColor,
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
minHeight: 40,
|
||||
maxHeight: 40,
|
||||
}
|
||||
|
||||
const executionModal =
|
||||
<Drawer anchor={"right"} open={executionModalOpen} onClose={() => setExecutionModalOpen(false)} PaperProps={{style: {minWidth: 375, maxWidth: 375, backgroundColor: "#1F2023", color: "white", fontSize: 18}}}>
|
||||
{executionModalView === 0 ?
|
||||
<div style={{padding: 25, }}>
|
||||
<Breadcrumbs aria-label="breadcrumb" separator="›" style={{color: "white", fontSize: 16}}>
|
||||
<h2 style={{color: "rgba(255,255,255,0.5)"}}>
|
||||
<DirectionsRunIcon style={{marginRight: 10}} />
|
||||
All Executions
|
||||
</h2>
|
||||
</Breadcrumbs>
|
||||
<Button
|
||||
style={{borderRadius: "0px"}}
|
||||
onClick={() => {
|
||||
getWorkflowExecution(props.match.params.key)
|
||||
}} color="primary">
|
||||
Refresh executions
|
||||
</Button>
|
||||
<Divider style={{backgroundColor: "white", marginTop: 10, marginBottom: 10,}}/>
|
||||
{workflowExecutions.length > 0 ?
|
||||
<div>
|
||||
{workflowExecutions.map(data => {
|
||||
const statusColor = data.status === "FINISHED" ? "green" : data.status === "ABORTED" ? "red" : "orange"
|
||||
const timeElapsed = data.completed_at-data.started_at
|
||||
const resultsLength = data.results !== undefined && data.results !== null ? data.results.length : 0
|
||||
|
||||
const timestamp = new Date(data.started_at*1000).toISOString().split('.')[0].split("T").join(" ")
|
||||
|
||||
return (
|
||||
<Paper elevation={5} square style={executionPaperStyle} onMouseOver={() => {}} onMouseOut={() => {}} onClick={() => {
|
||||
setExecutionModalView(1)
|
||||
setExecutionData(data)
|
||||
}}>
|
||||
<div style={{display: "flex", flex: 1}}>
|
||||
<div style={{marginLeft: 5, width: 2, backgroundColor: statusColor, marginRight: 15}} />
|
||||
<div style={{ marginTop: "auto", marginBottom: "auto", marginRight: 15, }}>
|
||||
{timestamp}
|
||||
</div>
|
||||
<Tooltip color="primary" title={resultsLength+" actions ran"} placement="top">
|
||||
<div style={{marginRight: 10, marginTop: "auto", marginBottom: "auto",}}>
|
||||
{resultsLength}/{data.workflow.actions.length}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<Tooltip title={"Inspect execution"} placement="top">
|
||||
<KeyboardArrowRightIcon style={{marginTop: "auto", marginBottom: "auto"}}/>
|
||||
</Tooltip>
|
||||
</Paper>
|
||||
)
|
||||
return
|
||||
})}
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
There are no executions yet
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
:
|
||||
<div style={{padding: 25, }}>
|
||||
<Breadcrumbs aria-label="breadcrumb" separator="›" style={{color: "white", fontSize: 16}}>
|
||||
<h2 style={{color: "rgba(255,255,255,0.5)", cursor: "pointer"}} onClick={() => {setExecutionModalView(0)}}>
|
||||
<DirectionsRunIcon style={{marginRight: 10}} />
|
||||
Other Executions
|
||||
</h2>
|
||||
</Breadcrumbs>
|
||||
<Divider style={{backgroundColor: "white", marginTop: 10, marginBottom: 10,}}/>
|
||||
<h2>Executing Workflow</h2>
|
||||
<Divider />
|
||||
<h3>Execution Argument: </h3>{executionText}
|
||||
{executionData.execution_argument !== undefined && executionData.execution_argument.length > 0 ?
|
||||
<div>
|
||||
<h3>Execution Argument: </h3>{executionText}
|
||||
</div>
|
||||
: null }
|
||||
{executionData.status !== undefined && executionData.status.length > 0 ?
|
||||
<div>
|
||||
<h3>Status: </h3>{executionData.status}
|
||||
<b>Status: </b>{executionData.status}
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
<h3>Results: </h3>
|
||||
{executionData.results === undefined || executionData.results === null || executionData.results.length === 0 ?
|
||||
{executionData.started_at !== undefined ?
|
||||
<div>
|
||||
<b>Started: </b>{new Date(executionData.started_at*1000).toISOString()}
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
{executionData.execution_id !== undefined && executionData.execution_id.length > 0 ?
|
||||
<div>
|
||||
<b>ID: </b>{executionData.execution_id}
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
<Divider style={{backgroundColor: "white", marginTop: 30, marginBottom: 30,}}/>
|
||||
<div style={{display: "flex", marginTop: 10, marginBottom: 30,}}>
|
||||
<b>Actions</b>
|
||||
<div>
|
||||
{executionData.status !== undefined && executionData.status !== "ABORTED" && executionData.status !== "FINISHED" ? <CircularProgress style={{marginLeft: 20}}/> : null}
|
||||
</div>
|
||||
</div>
|
||||
{executionData.results === undefined || executionData.results === null || executionData.results.length === 0 && executionData.status === "EXECUTING" ?
|
||||
<CircularProgress />
|
||||
:
|
||||
executionData.results.map(data => {
|
||||
@@ -4417,12 +4531,19 @@ const AngularWorkflow = (props) => {
|
||||
jsonvalid = false
|
||||
}
|
||||
|
||||
const curapp = apps.find(a => a.name === data.action.app_name && a.app_version === data.action.app_version)
|
||||
const imgsize = 50
|
||||
const actionimg = curapp === null ?
|
||||
null :
|
||||
<img alt={data.action.app_name} src={curapp.large_image} style={{marginRight: 20, width: imgsize, height: imgsize}} />
|
||||
|
||||
return (
|
||||
<div style={{margin: 10, border: "1px solid rgba(0,0,0,0.5)"}}>
|
||||
<div style={{width: 17, height: 17, borderRadius: 17 / 2, backgroundColor: "#f85a3e", marginRight: 10}}/>
|
||||
<b>Name:</b> {data.action.label}<div/>
|
||||
<b>Status:</b> {data.status}<div/>
|
||||
<b>Result:</b>
|
||||
<div style={{marginBottom: 40,}}>
|
||||
<div style={{display: "flex", marginBottom: 15,}}>
|
||||
{actionimg}
|
||||
<span style={{fontSize: 24, marginTop: "auto", marginBottom: "auto"}}><b>{data.action.label}</b></span>
|
||||
</div>
|
||||
<div style={{marginBottom: 5}}><b>Status </b> {data.status}</div>
|
||||
{jsonvalid ? <ReactJson
|
||||
src={JSON.parse(showResult)}
|
||||
theme="solarized"
|
||||
@@ -4431,16 +4552,18 @@ const AngularWorkflow = (props) => {
|
||||
name={"Results for "+data.action.label}
|
||||
/>
|
||||
:
|
||||
data.result
|
||||
<div>
|
||||
<b>Result</b>
|
||||
{data.result}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</Drawer>
|
||||
)
|
||||
}
|
||||
|
||||
const newView = isLoggedIn ?
|
||||
<div style={{color: "white"}}>
|
||||
@@ -4459,12 +4582,12 @@ const AngularWorkflow = (props) => {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<ExecutionModal />
|
||||
e
|
||||
{executionModal}
|
||||
<RightSideBar />
|
||||
<BottomCytoscapeBar />
|
||||
<TopCytoscapeBar />
|
||||
<NoActionsBar />
|
||||
{debugView}
|
||||
</div>
|
||||
:
|
||||
<div style={{color: "white"}}>
|
||||
@@ -4533,7 +4656,7 @@ const AngularWorkflow = (props) => {
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
<Button
|
||||
style={{borderRadius: "0px"}}
|
||||
onClick={() => {
|
||||
setNewVariableName("")
|
||||
@@ -4543,7 +4666,7 @@ const AngularWorkflow = (props) => {
|
||||
}} color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button style={{borderRadius: "0px"}} disabled={newVariableName.length === 0 || newVariableValue.length === 0} onClick={() => {
|
||||
<Button style={{borderRadius: "0px"}} disabled={newVariableName.length === 0 || newVariableValue.length === 0} onClick={() => {
|
||||
if (workflow.workflow_variables === undefined || workflow.workflow_variables === null) {
|
||||
workflow.workflow_variables = []
|
||||
}
|
||||
@@ -4692,7 +4815,7 @@ const AngularWorkflow = (props) => {
|
||||
<AuthenticationData />
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
<Button
|
||||
style={{borderRadius: "0px"}}
|
||||
onClick={() => {
|
||||
setAuthenticationModalOpen(false)
|
||||
|
||||
Reference in New Issue
Block a user