Added execution view drawer

This commit is contained in:
frikky
2020-05-25 10:43:00 +02:00
parent 7a4e9560a2
commit 191a8589a2
3 changed files with 169 additions and 50 deletions
+1 -5
View File
@@ -638,10 +638,6 @@ func handleGetStreamResults(resp http.ResponseWriter, request *http.Request) {
return
}
//for _, action := range workflowExecution.Workflow.Actions {
// log.Printf("Name: %s, Env: %s", action.Name, action.Environment)
//}
newjson, err := json.Marshal(workflowExecution)
if err != nil {
resp.WriteHeader(401)
@@ -3711,7 +3707,7 @@ func getWorkflowExecutions(resp http.ResponseWriter, request *http.Request) {
}
// Query for the specifci workflowId
q := datastore.NewQuery("workflowexecution").Filter("workflow_id =", fileId).Limit(50)
q := datastore.NewQuery("workflowexecution").Filter("workflow_id =", fileId).Order("-started_at").Limit(50)
var workflowExecutions []WorkflowExecution
_, err = dbclient.GetAll(ctx, q, &workflowExecutions)
if err != nil {
+166 -43
View File
@@ -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>&nbsp;
<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>&nbsp;
{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)
+2 -2
View File
@@ -38,10 +38,10 @@ 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"
// Production - backend proxy forwarding in nginx
//const globalUrl = window.location.origin
const globalUrl = window.location.origin
const surfaceColor = "#27292D"
const inputColor = "#383B40"