Added details link to running/already finished running nodes

This commit is contained in:
Michael Abashian
2016-12-01 11:45:32 -05:00
parent 765b7d9cc2
commit 5fe066124e
6 changed files with 116 additions and 54 deletions

View File

@@ -20,9 +20,12 @@
fill: @default-err-hov; fill: @default-err-hov;
} }
.node .WorkflowChart-defaultText { .node {
font-size: 12px; font-size: 12px;
font-family: 'Open Sans', sans-serif; font-family: 'Open Sans', sans-serif;
}
.WorkflowChart-defaultText {
fill: @default-interface-txt; fill: @default-interface-txt;
} }
@@ -76,3 +79,7 @@
.workflowChart-nodeStatus--failed { .workflowChart-nodeStatus--failed {
fill: @default-err; fill: @default-err;
} }
.WorkflowChart-detailsLink {
fill: @default-link;
cursor: pointer;
}

View File

@@ -4,8 +4,8 @@
* All Rights Reserved * All Rights Reserved
*************************************************/ *************************************************/
export default [ export default [ '$state',
function() { function($state) {
return { return {
scope: { scope: {
@@ -13,7 +13,8 @@ export default [
canAddWorkflowJobTemplate: '=', canAddWorkflowJobTemplate: '=',
addNode: '&', addNode: '&',
editNode: '&', editNode: '&',
deleteNode: '&' deleteNode: '&',
mode: '@'
}, },
restrict: 'E', restrict: 'E',
link: function(scope, element) { link: function(scope, element) {
@@ -64,8 +65,11 @@ export default [
// TODO: this function is hacky and we need to come up with a better solution // TODO: this function is hacky and we need to come up with a better solution
// see: http://stackoverflow.com/questions/15975440/add-ellipses-to-overflowing-text-in-svg#answer-27723752 // see: http://stackoverflow.com/questions/15975440/add-ellipses-to-overflowing-text-in-svg#answer-27723752
function wrap(text) { function wrap(text) {
if(text && text.length > 15) {
return text.substring(0,15) + '...'; let maxLength = scope.mode === 'details' ? 14 : 15;
if(text && text.length > maxLength) {
return text.substring(0,maxLength) + '...';
} }
else { else {
return text; return text;
@@ -156,11 +160,12 @@ export default [
.attr("class", function(d) { .attr("class", function(d) {
return d.placeholder ? "rect placeholder" : "rect"; return d.placeholder ? "rect placeholder" : "rect";
}); });
thisNode.append("text") thisNode.append("text")
.attr("x", rectW / 2) .attr("x", function(d){ return (scope.mode === 'details' && d.job && d.job.jobStatus) ? 20 : rectW / 2; })
.attr("y", rectH / 2) .attr("y", function(d){ return (scope.mode === 'details' && d.job && d.job.jobStatus) ? 10 : rectH / 2; })
.attr("dy", ".35em") .attr("dy", ".35em")
.attr("text-anchor", "middle") .attr("text-anchor", function(d){ return (scope.mode === 'details' && d.job && d.job.jobStatus) ? "inherit" : "middle"; })
.attr("class", "WorkflowChart-defaultText WorkflowChart-nameText") .attr("class", "WorkflowChart-defaultText WorkflowChart-nameText")
.text(function (d) { .text(function (d) {
return (d.unifiedJobTemplate && d.unifiedJobTemplate.name) ? d.unifiedJobTemplate.name : ""; return (d.unifiedJobTemplate && d.unifiedJobTemplate.name) ? d.unifiedJobTemplate.name : "";
@@ -199,6 +204,16 @@ export default [
.classed("hovering", false); .classed("hovering", false);
} }
}); });
thisNode.append("text")
.attr("x", rectW - 50)
.attr("y", rectH - 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"; })
.text(function () {
return "DETAILS";
})
.call(details);
thisNode.append("circle") thisNode.append("circle")
.attr("id", function(d){return "node-" + d.id + "-add";}) .attr("id", function(d){return "node-" + d.id + "-add";})
.attr("cx", rectW) .attr("cx", rectW)
@@ -288,27 +303,29 @@ export default [
let statusClass = "WorkflowChart-nodeStatus "; let statusClass = "WorkflowChart-nodeStatus ";
switch(d.jobStatus) { if(d.job){
case "pending": switch(d.job.jobStatus) {
statusClass = "workflowChart-nodeStatus--running"; case "pending":
break; statusClass = "workflowChart-nodeStatus--running";
case "waiting": break;
statusClass = "workflowChart-nodeStatus--running"; case "waiting":
break; statusClass = "workflowChart-nodeStatus--running";
case "running": break;
statusClass = "workflowChart-nodeStatus--running"; case "running":
break; statusClass = "workflowChart-nodeStatus--running";
case "successful": break;
statusClass = "workflowChart-nodeStatus--success"; case "successful":
break; statusClass = "workflowChart-nodeStatus--success";
case "failed": break;
statusClass = "workflowChart-nodeStatus--failed"; case "failed":
break; statusClass = "workflowChart-nodeStatus--failed";
break;
}
} }
return statusClass; return statusClass;
}) })
.style("display", function(d) { return d.jobStatus ? null : "none"; }) .style("display", function(d) { return d.job && d.job.jobStatus ? null : "none"; })
.attr("cy", 10) .attr("cy", 10)
.attr("cx", 10) .attr("cx", 10)
.attr("r", 6); .attr("r", 6);
@@ -456,11 +473,6 @@ export default [
return d.placeholder ? "rect placeholder" : "rect"; return d.placeholder ? "rect placeholder" : "rect";
}); });
t.selectAll(".WorkflowChart-nameText")
.text(function (d) {
return (d.unifiedJobTemplate && d.unifiedJobTemplate.name) ? wrap(d.unifiedJobTemplate.name) : "";
});
t.selectAll(".node") t.selectAll(".node")
.attr("transform", function(d) {d.px = d.x; d.py = d.y; return "translate(" + d.y + "," + d.x + ")"; }); .attr("transform", function(d) {d.px = d.x; d.py = d.y; return "translate(" + d.y + "," + d.x + ")"; });
@@ -478,32 +490,34 @@ export default [
let statusClass = "WorkflowChart-nodeStatus "; let statusClass = "WorkflowChart-nodeStatus ";
switch(d.jobStatus) { if(d.job){
case "pending": switch(d.job.jobStatus) {
statusClass += "workflowChart-nodeStatus--running"; case "pending":
break; statusClass += "workflowChart-nodeStatus--running";
case "waiting": break;
statusClass += "workflowChart-nodeStatus--running"; case "waiting":
break; statusClass += "workflowChart-nodeStatus--running";
case "running": break;
statusClass += "workflowChart-nodeStatus--running"; case "running":
break; statusClass += "workflowChart-nodeStatus--running";
case "successful": break;
statusClass += "workflowChart-nodeStatus--success"; case "successful":
break; statusClass += "workflowChart-nodeStatus--success";
case "failed": break;
statusClass += "workflowChart-nodeStatus--failed"; case "failed":
break; statusClass += "workflowChart-nodeStatus--failed";
break;
}
} }
return statusClass; return statusClass;
}) })
.style("display", function(d) { return d.jobStatus ? null : "none"; }) .style("display", function(d) { return d.job && d.job.jobStatus ? null : "none"; })
.transition() .transition()
.duration(0) .duration(0)
.attr("r", 6) .attr("r", 6)
.each(function(d) { .each(function(d) {
if(d.jobStatus && (d.jobStatus === "pending" || d.jobStatus === "waiting" || d.jobStatus === "running")) { if(d.job && d.job.jobStatus && (d.job.jobStatus === "pending" || d.job.jobStatus === "waiting" || d.job.jobStatus === "running")) {
// Pulse the circle // Pulse the circle
var circle = d3.select(this); var circle = d3.select(this);
(function repeat() { (function repeat() {
@@ -519,6 +533,18 @@ export default [
} }
}); });
t.selectAll(".WorkflowChart-nameText")
.attr("x", function(d){ return (scope.mode === 'details' && d.job && d.job.jobStatus) ? 20 : rectW / 2; })
.attr("y", function(d){ return (scope.mode === 'details' && d.job && d.job.jobStatus) ? 10 : rectH / 2; })
.attr("text-anchor", function(d){ return (scope.mode === 'details' && d.job && d.job.jobStatus) ? "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"; });
} }
function add_node() { function add_node() {
@@ -563,6 +589,28 @@ export default [
}); });
} }
function details() {
this.on("mouseover", function() {
d3.select(this).style("text-decoration", "underline");
});
this.on("mouseout", function() {
d3.select(this).style("text-decoration", null);
});
this.on("click", function(d) {
if(d.job.unified_job_id && d.unifiedJobTemplate) {
if(d.unifiedJobTemplate.unified_job_type === 'job') {
$state.go('jobDetail', {id: d.job.unified_job_id});
}
else if(d.unifiedJobTemplate.unified_job_type === 'inventory_update') {
$state.go('inventorySyncStdout', {id: d.job.unified_job_id});
}
else if(d.unifiedJobTemplate.unified_job_type === 'project_update') {
$state.go('scmUpdateStdout', {id: d.job.unified_job_id});
}
}
});
}
scope.$on('refreshWorkflowChart', function(){ scope.$on('refreshWorkflowChart', function(){
update(); update();
}); });

View File

@@ -60,7 +60,7 @@
<span class="badge List-titleBadge" ng-bind="treeData.data.totalNodes"></span> <span class="badge List-titleBadge" ng-bind="treeData.data.totalNodes"></span>
</div> </div>
</div> </div>
<workflow-chart tree-data="treeData.data" add-node="startAddNode(parent, betweenTwoNodes)" edit-node="startEditNode(nodeToEdit)" delete-node="startDeleteNode(nodeToDelete)" can-add-workflow-job-template="canAddWorkflowJobTemplate" class="WorkflowMaker-chart"></workflow-chart> <workflow-chart tree-data="treeData.data" add-node="startAddNode(parent, betweenTwoNodes)" edit-node="startEditNode(nodeToEdit)" delete-node="startDeleteNode(nodeToDelete)" can-add-workflow-job-template="canAddWorkflowJobTemplate" mode="edit" class="WorkflowMaker-chart"></workflow-chart>
</div> </div>
<div class="WorkflowMaker-contentRight"> <div class="WorkflowMaker-contentRight">
<div class="WorkflowMaker-formTitle">{{(workflowMakerFormConfig.nodeMode === 'edit' && nodeBeingEdited && nodeBeingEdited.unifiedJobTemplate && nodeBeingEdited.unifiedJobTemplate.name) ? nodeBeingEdited.unifiedJobTemplate.name : "ADD A TEMPLATE"}}</div> <div class="WorkflowMaker-formTitle">{{(workflowMakerFormConfig.nodeMode === 'edit' && nodeBeingEdited && nodeBeingEdited.unifiedJobTemplate && nodeBeingEdited.unifiedJobTemplate.name) ? nodeBeingEdited.unifiedJobTemplate.name : "ADD A TEMPLATE"}}</div>

View File

@@ -221,7 +221,10 @@ export default [function(){
} }
if(params.nodesObj[params.nodeId].summary_fields.job) { if(params.nodesObj[params.nodeId].summary_fields.job) {
treeNode.jobStatus = params.nodesObj[params.nodeId].summary_fields.job.status; treeNode.job = {
jobStatus: params.nodesObj[params.nodeId].summary_fields.job.status,
unified_job_id: params.nodesObj[params.nodeId].summary_fields.job.id
};
} }
// Loop across the success nodes and add them recursively // Loop across the success nodes and add them recursively
@@ -271,7 +274,10 @@ export default [function(){
}); });
if(matchingNode) { if(matchingNode) {
matchingNode.jobStatus = params.status; matchingNode.job = {
jobStatus: params.status,
unified_job_id: params.unified_job_id
};
} }
} }

View File

@@ -118,7 +118,8 @@ export default ['workflowData',
WorkflowService.updateStatusOfNode({ WorkflowService.updateStatusOfNode({
treeData: $scope.treeData, treeData: $scope.treeData,
nodeId: data.workflow_node_id, nodeId: data.workflow_node_id,
status: data.status status: data.status,
unified_job_id: data.unified_job_id
}); });
$scope.$broadcast("refreshWorkflowChart"); $scope.$broadcast("refreshWorkflowChart");

View File

@@ -216,7 +216,7 @@
</div> </div>
</div> </div>
<workflow-status-bar></workflow-status-bar> <workflow-status-bar></workflow-status-bar>
<workflow-chart tree-data="treeData.data" can-add-workflow-job-template="canAddWorkflowJobTemplate" class="WorkflowMaker-chart"></workflow-chart> <workflow-chart tree-data="treeData.data" can-add-workflow-job-template="canAddWorkflowJobTemplate" mode="details" class="WorkflowMaker-chart"></workflow-chart>
</div> </div>
</div> </div>