mirror of
https://github.com/ansible/awx.git
synced 2026-03-11 14:39:30 -02:30
Refresh nodes after workflow has finished running so that we can display all job info for relevant nodes.
This commit is contained in:
@@ -33,10 +33,11 @@ const StyledExclamationTriangleIcon = styled(ExclamationTriangleIcon)`
|
||||
|
||||
function WorkflowNodeHelp({ node, i18n }) {
|
||||
let nodeType;
|
||||
if (node.unifiedJobTemplate || node.job) {
|
||||
const job = node?.originalNodeObject?.summary_fields?.job;
|
||||
if (node.unifiedJobTemplate || job) {
|
||||
const type = node.unifiedJobTemplate
|
||||
? node.unifiedJobTemplate.unified_job_type || node.unifiedJobTemplate.type
|
||||
: node.job.type;
|
||||
: job.type;
|
||||
switch (type) {
|
||||
case 'job_template':
|
||||
case 'job':
|
||||
@@ -64,8 +65,8 @@ function WorkflowNodeHelp({ node, i18n }) {
|
||||
}
|
||||
|
||||
let jobStatus;
|
||||
if (node.job) {
|
||||
switch (node.job.status) {
|
||||
if (job) {
|
||||
switch (job.status) {
|
||||
case 'new':
|
||||
jobStatus = i18n._(t`New`);
|
||||
break;
|
||||
@@ -112,23 +113,22 @@ function WorkflowNodeHelp({ node, i18n }) {
|
||||
|
||||
return (
|
||||
<>
|
||||
{!node.unifiedJobTemplate &&
|
||||
(!node.job || node.job.type !== 'workflow_approval') && (
|
||||
<>
|
||||
<ResourceDeleted job={node.job}>
|
||||
<StyledExclamationTriangleIcon />
|
||||
<Trans>
|
||||
The resource associated with this node has been deleted.
|
||||
</Trans>
|
||||
</ResourceDeleted>
|
||||
</>
|
||||
)}
|
||||
{node.job && (
|
||||
{!node.unifiedJobTemplate && (!job || job.type !== 'workflow_approval') && (
|
||||
<>
|
||||
<ResourceDeleted job={job}>
|
||||
<StyledExclamationTriangleIcon />
|
||||
<Trans>
|
||||
The resource associated with this node has been deleted.
|
||||
</Trans>
|
||||
</ResourceDeleted>
|
||||
</>
|
||||
)}
|
||||
{job && (
|
||||
<GridDL>
|
||||
<dt>
|
||||
<b>{i18n._(t`Name`)}</b>
|
||||
</dt>
|
||||
<dd id="workflow-node-help-name">{node.job.name}</dd>
|
||||
<dd id="workflow-node-help-name">{job.name}</dd>
|
||||
<dt>
|
||||
<b>{i18n._(t`Type`)}</b>
|
||||
</dt>
|
||||
@@ -137,19 +137,19 @@ function WorkflowNodeHelp({ node, i18n }) {
|
||||
<b>{i18n._(t`Job Status`)}</b>
|
||||
</dt>
|
||||
<dd id="workflow-node-help-status">{jobStatus}</dd>
|
||||
{typeof node.job.elapsed === 'number' && (
|
||||
{typeof job.elapsed === 'number' && (
|
||||
<>
|
||||
<dt>
|
||||
<b>{i18n._(t`Elapsed`)}</b>
|
||||
</dt>
|
||||
<dd id="workflow-node-help-elapsed">
|
||||
{secondsToHHMMSS(node.job.elapsed)}
|
||||
{secondsToHHMMSS(job.elapsed)}
|
||||
</dd>
|
||||
</>
|
||||
)}
|
||||
</GridDL>
|
||||
)}
|
||||
{node.unifiedJobTemplate && !node.job && (
|
||||
{node.unifiedJobTemplate && !job && (
|
||||
<GridDL>
|
||||
<dt>
|
||||
<b>{i18n._(t`Name`)}</b>
|
||||
@@ -161,7 +161,7 @@ function WorkflowNodeHelp({ node, i18n }) {
|
||||
<dd id="workflow-node-help-type">{nodeType}</dd>
|
||||
</GridDL>
|
||||
)}
|
||||
{node.job && node.job.type !== 'workflow_approval' && (
|
||||
{job && job.type !== 'workflow_approval' && (
|
||||
<p css="margin-top: 10px">{i18n._(t`Click to view job details`)}</p>
|
||||
)}
|
||||
</>
|
||||
|
||||
@@ -365,9 +365,6 @@ function generateNodes(workflowNodes, i18n) {
|
||||
originalNodeObject: node,
|
||||
};
|
||||
|
||||
if (node.summary_fields.job) {
|
||||
nodeObj.job = node.summary_fields.job;
|
||||
}
|
||||
if (node.summary_fields.unified_job_template) {
|
||||
nodeObj.unifiedJobTemplate = node.summary_fields.unified_job_template;
|
||||
}
|
||||
|
||||
@@ -64,24 +64,25 @@ Elapsed.displayName = 'Elapsed';
|
||||
function WorkflowOutputNode({ i18n, mouseEnter, mouseLeave, node }) {
|
||||
const history = useHistory();
|
||||
const { nodePositions } = useContext(WorkflowStateContext);
|
||||
const job = node?.originalNodeObject?.summary_fields?.job;
|
||||
let borderColor = '#93969A';
|
||||
|
||||
if (node.job) {
|
||||
if (job) {
|
||||
if (
|
||||
node.job.status === 'failed' ||
|
||||
node.job.status === 'error' ||
|
||||
node.job.status === 'canceled'
|
||||
job.status === 'failed' ||
|
||||
job.status === 'error' ||
|
||||
job.status === 'canceled'
|
||||
) {
|
||||
borderColor = '#d9534f';
|
||||
}
|
||||
if (node.job.status === 'successful' || node.job.status === 'ok') {
|
||||
if (job.status === 'successful' || job.status === 'ok') {
|
||||
borderColor = '#5cb85c';
|
||||
}
|
||||
}
|
||||
|
||||
const handleNodeClick = () => {
|
||||
if (node.job && node.job.type !== 'workflow_aproval') {
|
||||
history.push(`/jobs/${node.job.id}/details`);
|
||||
if (job && job.type !== 'workflow_aproval') {
|
||||
history.push(`/jobs/${job.id}/details`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -90,7 +91,7 @@ function WorkflowOutputNode({ i18n, mouseEnter, mouseLeave, node }) {
|
||||
id={`node-${node.id}`}
|
||||
transform={`translate(${nodePositions[node.id].x},${nodePositions[node.id]
|
||||
.y - nodePositions[1].y})`}
|
||||
job={node.job}
|
||||
job={job}
|
||||
onClick={handleNodeClick}
|
||||
onMouseEnter={mouseEnter}
|
||||
onMouseLeave={mouseLeave}
|
||||
@@ -106,14 +107,14 @@ function WorkflowOutputNode({ i18n, mouseEnter, mouseLeave, node }) {
|
||||
/>
|
||||
<foreignObject height="58" width="178" x="1" y="1">
|
||||
<NodeContents>
|
||||
{node.job ? (
|
||||
{job ? (
|
||||
<>
|
||||
<JobTopLine>
|
||||
{node.job.status && <StatusIcon status={node.job.status} />}
|
||||
<p>{node.job.name || node.unifiedJobTemplate.name}</p>
|
||||
{job.status && <StatusIcon status={job.status} />}
|
||||
<p>{job.name || node.unifiedJobTemplate.name}</p>
|
||||
</JobTopLine>
|
||||
{!!node?.job?.elapsed && (
|
||||
<Elapsed>{secondsToHHMMSS(node.job.elapsed)}</Elapsed>
|
||||
{!!job?.elapsed && (
|
||||
<Elapsed>{secondsToHHMMSS(job.elapsed)}</Elapsed>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
@@ -125,7 +126,7 @@ function WorkflowOutputNode({ i18n, mouseEnter, mouseLeave, node }) {
|
||||
)}
|
||||
</NodeContents>
|
||||
</foreignObject>
|
||||
{(node.unifiedJobTemplate || node.job) && (
|
||||
{(node.unifiedJobTemplate || job) && (
|
||||
<WorkflowNodeTypeLetter node={node} />
|
||||
)}
|
||||
</NodeG>
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import useWebsocket from '../../../util/useWebsocket';
|
||||
import { WorkflowJobsAPI } from '../../../api';
|
||||
|
||||
const fetchWorkflowNodes = async (jobId, pageNo = 1, nodes = []) => {
|
||||
const { data } = await WorkflowJobsAPI.readNodes(jobId, {
|
||||
page_size: 200,
|
||||
page: pageNo,
|
||||
});
|
||||
|
||||
if (data.next) {
|
||||
return fetchWorkflowNodes(jobId, pageNo + 1, nodes.concat(data.results));
|
||||
}
|
||||
return nodes.concat(data.results);
|
||||
};
|
||||
|
||||
export default function useWsWorkflowOutput(workflowJobId, initialNodes) {
|
||||
const [nodes, setNodes] = useState(initialNodes);
|
||||
@@ -14,20 +27,53 @@ export default function useWsWorkflowOutput(workflowJobId, initialNodes) {
|
||||
|
||||
useEffect(
|
||||
function parseWsMessage() {
|
||||
if (
|
||||
!nodes ||
|
||||
nodes.length === 0 ||
|
||||
lastMessage?.workflow_job_id !== workflowJobId
|
||||
) {
|
||||
return;
|
||||
async function refreshNodeObjects() {
|
||||
const refreshedNodes = [];
|
||||
const updatedNodeObjects = await fetchWorkflowNodes(workflowJobId);
|
||||
const updatedNodeObjectsMap = updatedNodeObjects.reduce((map, node) => {
|
||||
map[node.id] = node;
|
||||
return map;
|
||||
}, {});
|
||||
nodes.forEach(node => {
|
||||
if (node.id === 1) {
|
||||
// This is our artificial start node
|
||||
refreshedNodes.push({
|
||||
...node,
|
||||
});
|
||||
} else {
|
||||
refreshedNodes.push({
|
||||
...node,
|
||||
originalNodeObject:
|
||||
updatedNodeObjectsMap[node.originalNodeObject.id],
|
||||
});
|
||||
}
|
||||
});
|
||||
setNodes(refreshedNodes);
|
||||
}
|
||||
|
||||
const index = nodes.findIndex(
|
||||
node => node?.originalNodeObject?.id === lastMessage.workflow_node_id
|
||||
);
|
||||
if (
|
||||
lastMessage?.unified_job_id === workflowJobId &&
|
||||
['successful', 'failed', 'error', 'cancelled'].includes(
|
||||
lastMessage.status
|
||||
)
|
||||
) {
|
||||
refreshNodeObjects();
|
||||
} else {
|
||||
if (
|
||||
!nodes ||
|
||||
nodes.length === 0 ||
|
||||
lastMessage?.workflow_job_id !== workflowJobId
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index > -1) {
|
||||
setNodes(updateNode(nodes, index, lastMessage));
|
||||
const index = nodes.findIndex(
|
||||
node => node?.originalNodeObject?.id === lastMessage.workflow_node_id
|
||||
);
|
||||
|
||||
if (index > -1) {
|
||||
setNodes(updateNode(nodes, index, lastMessage));
|
||||
}
|
||||
}
|
||||
},
|
||||
[lastMessage] // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
Reference in New Issue
Block a user