diff --git a/awx/ui/client/src/templates/workflows/workflow-chart/workflow-chart.block.less b/awx/ui/client/src/templates/workflows/workflow-chart/workflow-chart.block.less
index 7263edbf02..4399e6504a 100644
--- a/awx/ui/client/src/templates/workflows/workflow-chart/workflow-chart.block.less
+++ b/awx/ui/client/src/templates/workflows/workflow-chart/workflow-chart.block.less
@@ -105,3 +105,11 @@
.WorkflowChart-activeNode {
fill: @default-link;
}
+.WorkflowChart-elapsedHolder {
+ background-color: @b7grey;
+ color: @default-bg;
+ height: 13px;
+ width: 39px;
+ padding: 1px 3px;
+ border-radius: 4px;
+}
diff --git a/awx/ui/client/src/templates/workflows/workflow-chart/workflow-chart.directive.js b/awx/ui/client/src/templates/workflows/workflow-chart/workflow-chart.directive.js
index 759286178a..331543e7b2 100644
--- a/awx/ui/client/src/templates/workflows/workflow-chart/workflow-chart.directive.js
+++ b/awx/ui/client/src/templates/workflows/workflow-chart/workflow-chart.directive.js
@@ -190,6 +190,7 @@ export default [ '$state',
.attr("dy", ".35em")
.attr("class", "WorkflowChart-startText")
.text(function () { return "START"; })
+ .attr("display", function() { return scope.mode === 'details' ? 'none' : null;})
.call(add_node);
}
else {
@@ -225,10 +226,10 @@ export default [ '$state',
.style("display", function(d) { return d.isActiveEdit ? null : "none"; });
thisNode.append("text")
- .attr("x", function(d){ return (scope.mode === 'details' && d.job && d.job.jobStatus) ? 20 : nodeW / 2; })
- .attr("y", function(d){ return (scope.mode === 'details' && d.job && d.job.jobStatus) ? 10 : nodeH / 2; })
+ .attr("x", function(d){ return (scope.mode === 'details' && d.job && d.job.status) ? 20 : nodeW / 2; })
+ .attr("y", function(d){ return (scope.mode === 'details' && d.job && d.job.status) ? 10 : nodeH / 2; })
.attr("dy", ".35em")
- .attr("text-anchor", function(d){ return (scope.mode === 'details' && d.job && d.job.jobStatus) ? "inherit" : "middle"; })
+ .attr("text-anchor", function(d){ return (scope.mode === 'details' && d.job && d.job.status) ? "inherit" : "middle"; })
.attr("class", "WorkflowChart-defaultText WorkflowChart-nameText")
.text(function (d) {
return (d.unifiedJobTemplate && d.unifiedJobTemplate.name) ? d.unifiedJobTemplate.name : "";
@@ -293,7 +294,7 @@ export default [ '$state',
.attr("y", nodeH - 10)
.attr("dy", ".35em")
.attr("class", "WorkflowChart-detailsLink")
- .style("display", function(d){ return d.job && d.job.jobStatus && d.job.unified_job_id ? null : "none"; })
+ .style("display", function(d){ return d.job && d.job.status && d.job.id ? null : "none"; })
.text(function () {
return "DETAILS";
})
@@ -388,7 +389,7 @@ export default [ '$state',
let statusClass = "WorkflowChart-nodeStatus ";
if(d.job){
- switch(d.job.jobStatus) {
+ switch(d.job.status) {
case "pending":
statusClass = "workflowChart-nodeStatus--running";
break;
@@ -404,15 +405,37 @@ export default [ '$state',
case "failed":
statusClass = "workflowChart-nodeStatus--failed";
break;
+ case "error":
+ statusClass = "workflowChart-nodeStatus--failed";
+ break;
}
}
return statusClass;
})
- .style("display", function(d) { return d.job && d.job.jobStatus ? null : "none"; })
+ .style("display", function(d) { return d.job && d.job.status ? null : "none"; })
.attr("cy", 10)
.attr("cx", 10)
.attr("r", 6);
+
+ thisNode.append("foreignObject")
+ .attr("x", 5)
+ .attr("y", 43)
+ .style("font-size","0.7em")
+ .attr("class", "WorkflowChart-elapsed")
+ .html(function (d) {
+ if(d.job && d.job.elapsed) {
+ let elapsedMs = d.job.elapsed * 1000;
+ let elapsedMoment = moment.duration(elapsedMs);
+ let paddedElapsedMoment = Math.floor(elapsedMoment.asHours()) < 10 ? "0" + Math.floor(elapsedMoment.asHours()) : Math.floor(elapsedMoment.asHours());
+ let elapsedString = paddedElapsedMoment + moment.utc(elapsedMs).format(":mm:ss");
+ return "
" + elapsedString + "
";
+ }
+ else {
+ return "";
+ }
+ })
+ .style("display", function(d) { return (d.job && d.job.elapsed) ? null : "none"; });
}
});
@@ -608,7 +631,7 @@ export default [ '$state',
let statusClass = "WorkflowChart-nodeStatus ";
if(d.job){
- switch(d.job.jobStatus) {
+ switch(d.job.status) {
case "pending":
statusClass += "workflowChart-nodeStatus--running";
break;
@@ -624,17 +647,20 @@ export default [ '$state',
case "failed":
statusClass += "workflowChart-nodeStatus--failed";
break;
+ case "error":
+ statusClass = "workflowChart-nodeStatus--failed";
+ break;
}
}
return statusClass;
})
- .style("display", function(d) { return d.job && d.job.jobStatus ? null : "none"; })
+ .style("display", function(d) { return d.job && d.job.status ? null : "none"; })
.transition()
.duration(0)
.attr("r", 6)
.each(function(d) {
- if(d.job && d.job.jobStatus && (d.job.jobStatus === "pending" || d.job.jobStatus === "waiting" || d.job.jobStatus === "running")) {
+ if(d.job && d.job.status && (d.job.status === "pending" || d.job.status === "waiting" || d.job.status === "running")) {
// Pulse the circle
var circle = d3.select(this);
(function repeat() {
@@ -651,15 +677,15 @@ export default [ '$state',
});
t.selectAll(".WorkflowChart-nameText")
- .attr("x", function(d){ return (scope.mode === 'details' && d.job && d.job.jobStatus) ? 20 : nodeW / 2; })
- .attr("y", function(d){ return (scope.mode === 'details' && d.job && d.job.jobStatus) ? 10 : nodeH / 2; })
- .attr("text-anchor", function(d){ return (scope.mode === 'details' && d.job && d.job.jobStatus) ? "inherit" : "middle"; })
+ .attr("x", function(d){ return (scope.mode === 'details' && d.job && d.job.status) ? 20 : nodeW / 2; })
+ .attr("y", function(d){ return (scope.mode === 'details' && d.job && d.job.status) ? 10 : nodeH / 2; })
+ .attr("text-anchor", function(d){ return (scope.mode === 'details' && d.job && d.job.status) ? "inherit" : "middle"; })
.text(function (d) {
return (d.unifiedJobTemplate && d.unifiedJobTemplate.name) ? wrap(d.unifiedJobTemplate.name) : "";
});
t.selectAll(".WorkflowChart-detailsLink")
- .style("display", function(d){ return d.job && d.job.jobStatus && d.job.unified_job_id ? null : "none"; });
+ .style("display", function(d){ return d.job && d.job.status && d.job.id ? null : "none"; });
t.selectAll(".WorkflowChart-incompleteText")
.style("display", function(d){ return d.unifiedJobTemplate || d.placeholder ? "none" : null; });
@@ -670,6 +696,9 @@ export default [ '$state',
t.selectAll(".WorkflowChart-activeNode")
.style("display", function(d) { return d.isActiveEdit ? null : "none"; });
+ t.selectAll(".WorkflowChart-elapsed")
+ .style("display", function(d) { return (d.job && d.job.elapsed) ? null : "none"; });
+
}
function add_node() {
@@ -722,15 +751,15 @@ export default [ '$state',
d3.select(this).style("text-decoration", null);
});
this.on("click", function(d) {
- if(d.job.unified_job_id && d.unifiedJobTemplate) {
+ if(d.job.id && d.unifiedJobTemplate) {
if(d.unifiedJobTemplate.unified_job_type === 'job') {
- $state.go('jobDetail', {id: d.job.unified_job_id});
+ $state.go('jobDetail', {id: d.job.id});
}
else if(d.unifiedJobTemplate.unified_job_type === 'inventory_update') {
- $state.go('inventorySyncStdout', {id: d.job.unified_job_id});
+ $state.go('inventorySyncStdout', {id: d.job.id});
}
else if(d.unifiedJobTemplate.unified_job_type === 'project_update') {
- $state.go('scmUpdateStdout', {id: d.job.unified_job_id});
+ $state.go('scmUpdateStdout', {id: d.job.id});
}
}
});
diff --git a/awx/ui/client/src/templates/workflows/workflow.service.js b/awx/ui/client/src/templates/workflows/workflow.service.js
index 4e551c7582..64b939ddcb 100644
--- a/awx/ui/client/src/templates/workflows/workflow.service.js
+++ b/awx/ui/client/src/templates/workflows/workflow.service.js
@@ -224,10 +224,7 @@ export default [function(){
}
if(params.nodesObj[params.nodeId].summary_fields.job) {
- treeNode.job = {
- jobStatus: params.nodesObj[params.nodeId].summary_fields.job.status,
- unified_job_id: params.nodesObj[params.nodeId].summary_fields.job.id
- };
+ treeNode.job = _.clone(params.nodesObj[params.nodeId].summary_fields.job);
}
if(params.nodesObj[params.nodeId].summary_fields.unified_job_template) {
@@ -282,8 +279,8 @@ export default [function(){
if(matchingNode) {
matchingNode.job = {
- jobStatus: params.status,
- unified_job_id: params.unified_job_id
+ status: params.status,
+ id: params.unified_job_id
};
}
diff --git a/awx/ui/client/src/workflow-results/workflow-results.partial.html b/awx/ui/client/src/workflow-results/workflow-results.partial.html
index 86f0ad13a4..998a37c956 100644
--- a/awx/ui/client/src/workflow-results/workflow-results.partial.html
+++ b/awx/ui/client/src/workflow-results/workflow-results.partial.html
@@ -98,32 +98,6 @@
-
-
-
-
-
-
-
- Workflow Job
-
-
-
@@ -281,7 +255,7 @@
-
+