mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 10:00:01 -03:30
Addresses a number of workflow related bugs
This commit is contained in:
parent
281345dd67
commit
72263c5c7b
@ -186,16 +186,8 @@
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.WorkflowChart-tooltipArrow--right {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 10px solid transparent;
|
||||
border-bottom: 10px solid transparent;
|
||||
border-left: 10px solid @default-interface-txt;
|
||||
margin: auto;
|
||||
position: relative;
|
||||
right: -55px;
|
||||
top: -34px;
|
||||
.WorkflowChart-tooltipArrow {
|
||||
fill: @default-interface-txt;
|
||||
}
|
||||
|
||||
.WorkflowChart-dashedNode {
|
||||
|
||||
@ -240,6 +240,81 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
||||
|
||||
function update() {
|
||||
if(scope.dimensionsSet) {
|
||||
const buildLinkTooltip = (d) => {
|
||||
let sourceNode = d3.select(`#node-${d.source.id}`);
|
||||
const sourceNodeX = d3.transform(sourceNode.attr("transform")).translate[0];
|
||||
const sourceNodeY = d3.transform(sourceNode.attr("transform")).translate[1];
|
||||
let targetNode = d3.select(`#node-${d.target.id}`);
|
||||
const targetNodeX = d3.transform(targetNode.attr("transform")).translate[0];
|
||||
const targetNodeY = d3.transform(targetNode.attr("transform")).translate[1];
|
||||
let xPos, yPos, arrowPoints;
|
||||
if (nodePositionMap[d.source.id].y === nodePositionMap[d.target.id].y) {
|
||||
xPos = (sourceNodeX + nodeW + targetNodeX)/2 - 50;
|
||||
yPos = (sourceNodeY + nodeH + targetNodeY)/2 - 70;
|
||||
arrowPoints = {
|
||||
pt1: {
|
||||
x: xPos + 40,
|
||||
y: yPos + 47
|
||||
},
|
||||
pt2: {
|
||||
x: xPos + 60,
|
||||
y: yPos + 47
|
||||
},
|
||||
pt3: {
|
||||
x: xPos + 50,
|
||||
y: yPos + 57
|
||||
}
|
||||
};
|
||||
} else {
|
||||
xPos = (sourceNodeX + nodeW + targetNodeX)/2 - 120;
|
||||
yPos = (sourceNodeY + nodeH + targetNodeY)/2 - 30;
|
||||
arrowPoints = {
|
||||
pt1: {
|
||||
x: xPos + 100,
|
||||
y: yPos + 17
|
||||
},
|
||||
pt2: {
|
||||
x: xPos + 100,
|
||||
y: yPos + 33
|
||||
},
|
||||
pt3: {
|
||||
x: xPos + 110,
|
||||
y: yPos + 25
|
||||
}
|
||||
};
|
||||
}
|
||||
let edgeTypeLabel;
|
||||
switch(d.edgeType) {
|
||||
case "always":
|
||||
edgeTypeLabel = TemplatesStrings.get('workflow_maker.ALWAYS');
|
||||
break;
|
||||
case "success":
|
||||
edgeTypeLabel = TemplatesStrings.get('workflow_maker.ON_SUCCESS');
|
||||
break;
|
||||
case "failure":
|
||||
edgeTypeLabel = TemplatesStrings.get('workflow_maker.ON_FAILURE');
|
||||
break;
|
||||
}
|
||||
let linkInstructionText = !scope.readOnly ? TemplatesStrings.get('workflow_maker.EDIT_LINK_TOOLTIP') : TemplatesStrings.get('workflow_maker.VIEW_LINK_TOOLTIP');
|
||||
let linkTooltip = svgGroup.append("g")
|
||||
.attr("class", "WorkflowChart-tooltip");
|
||||
linkTooltip.append("foreignObject")
|
||||
.attr("transform", `translate(${xPos},${yPos})`)
|
||||
.attr("width", 100)
|
||||
.attr("height", 50)
|
||||
.html(function(){
|
||||
return `<div class='WorkflowChart-tooltipContents'>
|
||||
<div>${TemplatesStrings.get('workflow_maker.RUN')}: ${edgeTypeLabel}</div>
|
||||
<div>${linkInstructionText}</div>
|
||||
</div>`;
|
||||
});
|
||||
linkTooltip.append("polygon")
|
||||
.attr("class", "WorkflowChart-tooltipArrow")
|
||||
.attr("points", function() {
|
||||
return `${arrowPoints.pt1.x},${arrowPoints.pt1.y} ${arrowPoints.pt2.x},${arrowPoints.pt2.y} ${arrowPoints.pt3.x},${arrowPoints.pt3.y}`;
|
||||
});
|
||||
};
|
||||
|
||||
var g = new dagre.graphlib.Graph();
|
||||
|
||||
g.setGraph({rankdir: 'LR', nodesep: 30, ranksep: 120});
|
||||
@ -336,7 +411,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
||||
|
||||
baseSvg.selectAll(".WorkflowChart-circleBetweenNodes")
|
||||
.attr("id", function(d){return "link-" + d.source.id + "-" + d.target.id + "-add";})
|
||||
.style("display", function(d) { return (scope.graphState.isLinkMode || d.source.id === scope.graphState.nodeBeingAdded || d.target.id === scope.graphState.nodeBeingAdded || scope.readOnly) ? "none" : null; })
|
||||
.style("display", function(d) { return (d.edgeType === 'placeholder' || scope.graphState.isLinkMode || d.source.id === scope.graphState.nodeBeingAdded || d.target.id === scope.graphState.nodeBeingAdded || scope.readOnly) ? "none" : null; })
|
||||
.attr("cx", function(d) {
|
||||
return (nodePositionMap[d.source.id].x + nodePositionMap[d.source.id].width + nodePositionMap[d.target.id].x)/2;
|
||||
})
|
||||
@ -356,7 +431,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
||||
});
|
||||
|
||||
baseSvg.selectAll(".WorkflowChart-betweenNodesIcon")
|
||||
.style("display", function(d) { return (scope.graphState.isLinkMode || d.source.id === scope.graphState.nodeBeingAdded || d.target.id === scope.graphState.nodeBeingAdded || scope.readOnly) ? "none" : null; })
|
||||
.style("display", function(d) { return (d.edgeType === 'placeholder' || scope.graphState.isLinkMode || d.source.id === scope.graphState.nodeBeingAdded || d.target.id === scope.graphState.nodeBeingAdded || scope.readOnly) ? "none" : null; })
|
||||
.attr("transform", function(d) {
|
||||
let translate;
|
||||
|
||||
@ -411,48 +486,20 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
||||
return [pt1, pt2, pt3, pt4].join(" ");
|
||||
})
|
||||
.on("mouseover", function(d) {
|
||||
if(!scope.graphState.isLinkMode && !d.source.isStartNode && d.source.id !== scope.graphState.nodeBeingAdded && d.target.id !== scope.graphState.nodeBeingAdded && scope.mode !== 'details') {
|
||||
if(
|
||||
d.edgeType !== 'placeholder' &&
|
||||
!scope.graphState.isLinkMode &&
|
||||
!d.source.isStartNode &&
|
||||
d.source.id !== scope.graphState.nodeBeingAdded &&
|
||||
d.target.id !== scope.graphState.nodeBeingAdded &&
|
||||
scope.mode !== 'details'
|
||||
) {
|
||||
$(`#link-${d.source.id}-${d.target.id}`).appendTo(`#aw-workflow-chart-g`);
|
||||
d3.select(`#link-${d.source.id}-${d.target.id}`)
|
||||
.classed("WorkflowChart-linkHovering", true);
|
||||
|
||||
let xPos, yPos, arrowClass;
|
||||
if (nodePositionMap[d.source.id].y === nodePositionMap[d.target.id].y) {
|
||||
xPos = (nodePositionMap[d.source.id].x + nodePositionMap[d.target.id].x)/2 + 45;
|
||||
yPos = (nodePositionMap[d.source.id].y + nodePositionMap[d.target.id].y)/2 - 107;
|
||||
arrowClass = 'WorkflowChart-tooltipArrow--down';
|
||||
} else {
|
||||
xPos = (nodePositionMap[d.source.id].x + nodePositionMap[d.target.id].x)/2 - 30;
|
||||
yPos = (nodePositionMap[d.source.id].y + nodePositionMap[d.target.id].y)/2 - 70;
|
||||
arrowClass = 'WorkflowChart-tooltipArrow--right';
|
||||
}
|
||||
|
||||
let edgeTypeLabel;
|
||||
|
||||
switch(d.edgeType) {
|
||||
case "always":
|
||||
edgeTypeLabel = TemplatesStrings.get('workflow_maker.ALWAYS');
|
||||
break;
|
||||
case "success":
|
||||
edgeTypeLabel = TemplatesStrings.get('workflow_maker.ON_SUCCESS');
|
||||
break;
|
||||
case "failure":
|
||||
edgeTypeLabel = TemplatesStrings.get('workflow_maker.ON_FAILURE');
|
||||
break;
|
||||
}
|
||||
|
||||
let linkInstructionText = !scope.readOnly ? TemplatesStrings.get('workflow_maker.EDIT_LINK_TOOLTIP') : TemplatesStrings.get('workflow_maker.VIEW_LINK_TOOLTIP');
|
||||
|
||||
svgGroup.append("foreignObject")
|
||||
.attr("transform", `translate(${xPos},${yPos})`)
|
||||
.attr("width", 100)
|
||||
.attr("height", 60)
|
||||
.attr("class", "WorkflowChart-tooltip")
|
||||
.html(function(){
|
||||
return `<div class='WorkflowChart-tooltipContents'><div>${TemplatesStrings.get('workflow_maker.RUN')}: ${edgeTypeLabel}</div><div>${linkInstructionText}</div></div><div class='${arrowClass}'></div>`;
|
||||
});
|
||||
buildLinkTooltip(d);
|
||||
}
|
||||
|
||||
})
|
||||
.on("mouseout", function(d){
|
||||
if(!d.source.isStartNode && d.target.id !== scope.graphState.nodeBeingAdded && scope.mode !== 'details') {
|
||||
@ -471,46 +518,19 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
||||
.attr("d", lineData)
|
||||
.call(edit_link)
|
||||
.on("mouseenter", function(d) {
|
||||
if(!scope.graphState.isLinkMode && !d.source.isStartNode && d.source.id !== scope.graphState.nodeBeingAdded && d.target.id !== scope.graphState.nodeBeingAdded && scope.mode !== 'details') {
|
||||
if(
|
||||
d.edgeType !== 'placeholder' &&
|
||||
!scope.graphState.isLinkMode &&
|
||||
!d.source.isStartNode &&
|
||||
d.source.id !== scope.graphState.nodeBeingAdded &&
|
||||
d.target.id !== scope.graphState.nodeBeingAdded &&
|
||||
scope.mode !== 'details'
|
||||
) {
|
||||
$(`#link-${d.source.id}-${d.target.id}`).appendTo(`#aw-workflow-chart-g`);
|
||||
d3.select("#link-" + d.source.id + "-" + d.target.id)
|
||||
d3.select(`#link-${d.source.id}-${d.target.id}`)
|
||||
.classed("WorkflowChart-linkHovering", true);
|
||||
|
||||
let xPos, yPos, arrowClass;
|
||||
if (nodePositionMap[d.source.id].y === nodePositionMap[d.target.id].y) {
|
||||
xPos = (nodePositionMap[d.source.id].x + nodePositionMap[d.target.id].x)/2 + 45;
|
||||
yPos = (nodePositionMap[d.source.id].y + nodePositionMap[d.target.id].y)/2 - 107;
|
||||
arrowClass = 'WorkflowChart-tooltipArrow--down';
|
||||
} else {
|
||||
xPos = (nodePositionMap[d.source.id].x + nodePositionMap[d.target.id].x)/2 - 30;
|
||||
yPos = (nodePositionMap[d.source.id].y + nodePositionMap[d.target.id].y)/2 - 70;
|
||||
arrowClass = 'WorkflowChart-tooltipArrow--right';
|
||||
}
|
||||
|
||||
let edgeTypeLabel;
|
||||
|
||||
switch(d.edgeType) {
|
||||
case "always":
|
||||
edgeTypeLabel = TemplatesStrings.get('workflow_maker.ALWAYS');
|
||||
break;
|
||||
case "success":
|
||||
edgeTypeLabel = TemplatesStrings.get('workflow_maker.ON_SUCCESS');
|
||||
break;
|
||||
case "failure":
|
||||
edgeTypeLabel = TemplatesStrings.get('workflow_maker.ON_FAILURE');
|
||||
break;
|
||||
}
|
||||
|
||||
let linkInstructionText = !scope.readOnly ? TemplatesStrings.get('workflow_maker.EDIT_LINK_TOOLTIP') : TemplatesStrings.get('workflow_maker.VIEW_LINK_TOOLTIP');
|
||||
|
||||
svgGroup.append("foreignObject")
|
||||
.attr("transform", `translate(${xPos},${yPos})`)
|
||||
.attr("width", 100)
|
||||
.attr("height", 60)
|
||||
.attr("class", "WorkflowChart-tooltip")
|
||||
.html(function(){
|
||||
return `<div class='WorkflowChart-tooltipContents'><div>${TemplatesStrings.get('workflow_maker.RUN')}: ${edgeTypeLabel}</div><div>${linkInstructionText}</div></div><div class='${arrowClass}'></div>`;
|
||||
});
|
||||
buildLinkTooltip(d);
|
||||
}
|
||||
})
|
||||
.on("mouseleave", function(d){
|
||||
@ -543,7 +563,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
||||
.attr("id", function(d){return "link-" + d.source.id + "-" + d.target.id + "-add";})
|
||||
.attr("r", 10)
|
||||
.attr("class", "WorkflowChart-addCircle WorkflowChart-circleBetweenNodes")
|
||||
.style("display", function(d) { return (scope.graphState.isLinkMode || d.source.id === scope.graphState.nodeBeingAdded || d.target.id === scope.graphState.nodeBeingAdded || scope.readOnly) ? "none" : null; })
|
||||
.style("display", function(d) { return (d.edgeType === 'placeholder' || scope.graphState.isLinkMode || d.source.id === scope.graphState.nodeBeingAdded || d.target.id === scope.graphState.nodeBeingAdded || scope.readOnly) ? "none" : null; })
|
||||
.attr("cx", function(d) {
|
||||
return (nodePositionMap[d.source.id].x + nodePositionMap[d.source.id].width + nodePositionMap[d.target.id].x)/2;
|
||||
})
|
||||
@ -580,7 +600,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
||||
.size(60)
|
||||
.type("cross")
|
||||
)
|
||||
.style("display", function(d) { return (scope.graphState.isLinkMode || d.source.id === scope.graphState.nodeBeingAdded || d.target.id === scope.graphState.nodeBeingAdded || scope.readOnly) ? "none" : null; })
|
||||
.style("display", function(d) { return (d.edgeType === 'placeholder' || scope.graphState.isLinkMode || d.source.id === scope.graphState.nodeBeingAdded || d.target.id === scope.graphState.nodeBeingAdded || scope.readOnly) ? "none" : null; })
|
||||
.attr("transform", function(d) {
|
||||
let translate;
|
||||
|
||||
@ -1263,7 +1283,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
||||
|
||||
function add_node_with_child() {
|
||||
this.on("click", function(d) {
|
||||
if(!scope.readOnly && !scope.graphState.isLinkMode) {
|
||||
if(!scope.readOnly && !scope.graphState.isLinkMode && d.edgeType !== 'placeholder') {
|
||||
scope.addNodeWithChild({
|
||||
link: d
|
||||
});
|
||||
@ -1340,25 +1360,32 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
||||
}
|
||||
};
|
||||
|
||||
if(d.job.id) {
|
||||
if(d.job.type) {
|
||||
if(d.unifiedJobTemplate) {
|
||||
goToJobResults(d.unifiedJobTemplate.unified_job_type);
|
||||
}
|
||||
else {
|
||||
// We don't have access to the unified resource and have to make
|
||||
// We don't have access to the job type and have to make
|
||||
// a GET request in order to find out what type job this was
|
||||
// so that we can route the user to the correct stdout view
|
||||
|
||||
Rest.setUrl(GetBasePath("unified_jobs") + "?id=" + d.job.id);
|
||||
Rest.setUrl(GetBasePath("workflow_jobs") + `${d.originalNodeObj.workflow_job}/workflow_nodes/?order_by=id`);
|
||||
Rest.get()
|
||||
.then(function (res) {
|
||||
if(res.data.results && res.data.results.length > 0) {
|
||||
goToJobResults(res.data.results[0].type);
|
||||
}
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Unable to get job: ' + status });
|
||||
});
|
||||
.then(function (res) {
|
||||
if (res.data.results && res.data.results.length > 0) {
|
||||
const { results } = res.data;
|
||||
const job = results.filter(result => result.summary_fields.job.id === d.job.id);
|
||||
goToJobResults(job[0].summary_fields.job.type);
|
||||
}
|
||||
})
|
||||
.catch(({
|
||||
data,
|
||||
status
|
||||
}) => {
|
||||
ProcessErrors(scope, data, status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Unable to get job: ' + status
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -97,7 +97,6 @@ export default [function(){
|
||||
return {
|
||||
arrayOfNodesForChart,
|
||||
arrayOfLinksForChart,
|
||||
chartNodeIdToIndexMapping,
|
||||
nodeIdToChartNodeIdMapping,
|
||||
nodeRef,
|
||||
workflowMakerNodeIdCounter: nodeIdCounter
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
<div class="WorkflowMaker-formTitle">{{readOnly ? strings.get('workflow_maker.VIEW_LINK') : (linkConfig.mode === 'add' ? strings.get('workflow_maker.ADD_LINK') : strings.get('workflow_maker.EDIT_LINK')) }} | {{linkConfig.parent.name}} {{linkConfig.child ? 'to ' + linkConfig.child.name : ''}}</div>
|
||||
<div class="WorkflowMaker-formTitle">{{readOnly ? strings.get('workflow_maker.VIEW_LINK') : (linkConfig.mode === 'add' ? strings.get('workflow_maker.ADD_LINK') : strings.get('workflow_maker.EDIT_LINK')) }} | {{linkConfig.source.name}} {{linkConfig.target ? 'to ' + linkConfig.target.name : ''}}</div>
|
||||
<div class="WorkflowMaker-form">
|
||||
<div class="form-group Form-formGroup Form-formGroup--singleColumn">
|
||||
<div ng-show="linkConfig.mode === 'add' && !linkConfig.child">{{:: strings.get('workflow_maker.NEW_LINK')}}</div>
|
||||
<span ng-show="linkConfig.child">
|
||||
<div ng-show="linkConfig.mode === 'add' && !linkConfig.target">{{:: strings.get('workflow_maker.NEW_LINK')}}</div>
|
||||
<span ng-show="linkConfig.target">
|
||||
<label for="edgeType" class="Form-inputLabelContainer">
|
||||
<span class="Form-requiredAsterisk">*</span>
|
||||
<span class="Form-inputLabel">{{:: strings.get('workflow_maker.RUN') }}</span>
|
||||
@ -25,6 +25,6 @@
|
||||
<button type="button" class="btn btn-sm Form-primaryButton Form-primaryButton--noMargin" id="workflow_maker_unlink_btn" ng-show="!readOnly && linkConfig.canUnlink" ng-click="unlink()"> {{:: strings.get('workflow_maker.UNLINK') }}</button>
|
||||
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_cancel_link_btn" ng-show="!readOnly" ng-click="cancel()"> {{:: strings.get('CANCEL') }}</button>
|
||||
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_cancel_link_btn" ng-show="readOnly" ng-click="cancel()"> {{:: strings.get('CLOSE') }}</button>
|
||||
<button type="button" class="btn btn-sm Form-saveButton" id="workflow_maker_select_link_btn" ng-show="!readOnly && linkConfig.child" ng-click="select({edgeType: edgeType.value})" ng-disabled="!edgeType"> {{:: strings.get('SAVE') }}</button>
|
||||
<button type="button" class="btn btn-sm Form-saveButton" id="workflow_maker_select_link_btn" ng-show="!readOnly && linkConfig.target" ng-click="select({edgeType: edgeType.value})" ng-disabled="!edgeType"> {{:: strings.get('SAVE') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<div ng-show="nodeFormDataLoaded">
|
||||
<div class="WorkflowMaker-formTitle">{{nodeConfig.mode === 'edit' ? nodeConfig.node.unifiedJobTemplate.name : strings.get('workflow_maker.ADD_A_TEMPLATE')}}</div>
|
||||
<div class="Form-tabHolder" ng-if="!readOnly">
|
||||
<div class="WorkflowMaker-formTitle">{{nodeConfig.mode === 'edit' ? nodeConfig.node.fullUnifiedJobTemplateObject.name || nodeConfig.node.unifiedJobTemplate.name : strings.get('workflow_maker.ADD_A_TEMPLATE')}}</div>
|
||||
<div class="Form-tabHolder" ng-show="!readOnly">
|
||||
<div class="Form-tab WorkflowMaker-formTab" ng-class="{'is-selected': activeTab === 'jobs'}" ng-click="activeTab = 'jobs'">{{strings.get('workflow_maker.JOBS')}}</div>
|
||||
<div class="Form-tab WorkflowMaker-formTab" ng-class="{'is-selected': activeTab === 'project_syncs'}" ng-click="activeTab = 'project_syncs'">{{strings.get('workflow_maker.PROJECT_SYNC')}}</div>
|
||||
<div class="Form-tab WorkflowMaker-formTab" ng-class="{'is-selected': activeTab === 'inventory_syncs'}" ng-click="activeTab = 'inventory_syncs'">{{strings.get('workflow_maker.INVENTORY_SYNC')}}</div>
|
||||
</div>
|
||||
<div class="WorkflowMaker-formLists" ng-if="!readOnly">
|
||||
<div class="WorkflowMaker-formLists" ng-show="!readOnly">
|
||||
<div id="workflow-jobs-list" ng-show="activeTab === 'jobs'">
|
||||
<div ng-hide="wf_maker_templates.length === 0 && (searchTags | isEmpty)">
|
||||
<smart-search django-model="unified_job_templates" base-path="unified_job_templates" iterator="wf_maker_template" dataset="wf_maker_template_dataset" list="templateList" collection="wf_maker_templates" default-params="wf_maker_template_default_params" query-set="wf_maker_template_queryset" search-bar-full-width="true" search-tags="searchTags">
|
||||
@ -141,7 +141,7 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="readOnly">
|
||||
<div ng-show="readOnly">
|
||||
<div
|
||||
class="WorkflowMaker-readOnlyPromptText"
|
||||
ng-show="nodeConfig.node.originalNodeObject.job_type !== null ||
|
||||
|
||||
@ -20,7 +20,6 @@ export default ['$scope', 'TemplatesService',
|
||||
let deletedNodeIds = [];
|
||||
let workflowMakerNodeIdCounter = 1;
|
||||
let nodeIdToChartNodeIdMapping = {};
|
||||
let chartNodeIdToIndexMapping = {};
|
||||
let nodeRef = {};
|
||||
|
||||
$scope.showKey = false;
|
||||
@ -365,25 +364,22 @@ export default ['$scope', 'TemplatesService',
|
||||
}
|
||||
|
||||
$scope.graphState.arrayOfNodesForChart.push({
|
||||
index: $scope.graphState.arrayOfNodesForChart.length,
|
||||
id: workflowMakerNodeIdCounter,
|
||||
unifiedJobTemplate: null
|
||||
});
|
||||
|
||||
$scope.graphState.nodeBeingAdded = workflowMakerNodeIdCounter;
|
||||
|
||||
chartNodeIdToIndexMapping[workflowMakerNodeIdCounter] = $scope.graphState.arrayOfNodesForChart.length - 1;
|
||||
|
||||
$scope.graphState.arrayOfLinksForChart.push({
|
||||
source: $scope.graphState.arrayOfNodesForChart[parent.index],
|
||||
target: $scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[workflowMakerNodeIdCounter]],
|
||||
source: {id: parent.id},
|
||||
target: {id: workflowMakerNodeIdCounter},
|
||||
edgeType: "placeholder"
|
||||
});
|
||||
|
||||
$scope.nodeConfig = {
|
||||
mode: "add",
|
||||
nodeId: workflowMakerNodeIdCounter,
|
||||
newNodeIsRoot: parent.index === 0
|
||||
newNodeIsRoot: parent.id === 1
|
||||
};
|
||||
|
||||
workflowMakerNodeIdCounter++;
|
||||
@ -403,18 +399,15 @@ export default ['$scope', 'TemplatesService',
|
||||
}
|
||||
|
||||
$scope.graphState.arrayOfNodesForChart.push({
|
||||
index: $scope.graphState.arrayOfNodesForChart.length,
|
||||
id: workflowMakerNodeIdCounter,
|
||||
unifiedJobTemplate: null
|
||||
});
|
||||
|
||||
$scope.graphState.nodeBeingAdded = workflowMakerNodeIdCounter;
|
||||
|
||||
chartNodeIdToIndexMapping[workflowMakerNodeIdCounter] = $scope.graphState.arrayOfNodesForChart.length - 1;
|
||||
|
||||
$scope.graphState.arrayOfLinksForChart.push({
|
||||
source: $scope.graphState.arrayOfNodesForChart[link.source.index],
|
||||
target: $scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[workflowMakerNodeIdCounter]],
|
||||
source: {id: link.source.id},
|
||||
target: {id: workflowMakerNodeIdCounter},
|
||||
edgeType: "placeholder"
|
||||
});
|
||||
|
||||
@ -426,9 +419,9 @@ export default ['$scope', 'TemplatesService',
|
||||
|
||||
// Search for the link that used to exist between source and target and shift it to
|
||||
// go from our new node to the target
|
||||
$scope.graphState.arrayOfLinksForChart.forEach((foo) => {
|
||||
if (foo.source.id === link.source.id && foo.target.id === link.target.id) {
|
||||
foo.source = $scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[workflowMakerNodeIdCounter]];
|
||||
$scope.graphState.arrayOfLinksForChart.forEach((linkToCompare) => {
|
||||
if (linkToCompare.source.id === link.source.id && linkToCompare.target.id === link.target.id) {
|
||||
linkToCompare.source = {id: workflowMakerNodeIdCounter};
|
||||
}
|
||||
});
|
||||
|
||||
@ -440,7 +433,7 @@ export default ['$scope', 'TemplatesService',
|
||||
};
|
||||
|
||||
$scope.confirmNodeForm = function(selectedTemplate, promptData, edgeType) {
|
||||
const nodeIndex = chartNodeIdToIndexMapping[$scope.nodeConfig.nodeId];
|
||||
const nodeId = $scope.nodeConfig.nodeId;
|
||||
if ($scope.nodeConfig.mode === "add") {
|
||||
if (selectedTemplate && edgeType && edgeType.value) {
|
||||
nodeRef[$scope.nodeConfig.nodeId] = {
|
||||
@ -449,11 +442,10 @@ export default ['$scope', 'TemplatesService',
|
||||
isNew: true
|
||||
};
|
||||
|
||||
$scope.graphState.arrayOfNodesForChart[nodeIndex].unifiedJobTemplate = selectedTemplate;
|
||||
$scope.graphState.nodeBeingAdded = null;
|
||||
|
||||
$scope.graphState.arrayOfLinksForChart.map( (link) => {
|
||||
if (link.target.index === nodeIndex) {
|
||||
if (link.target.id === nodeId) {
|
||||
link.edgeType = edgeType.value;
|
||||
}
|
||||
});
|
||||
@ -463,11 +455,16 @@ export default ['$scope', 'TemplatesService',
|
||||
nodeRef[$scope.nodeConfig.nodeId].fullUnifiedJobTemplateObject = selectedTemplate;
|
||||
nodeRef[$scope.nodeConfig.nodeId].promptData = _.cloneDeep(promptData);
|
||||
nodeRef[$scope.nodeConfig.nodeId].isEdited = true;
|
||||
$scope.graphState.arrayOfNodesForChart[nodeIndex].unifiedJobTemplate = selectedTemplate;
|
||||
$scope.graphState.nodeBeingEdited = null;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.graphState.arrayOfNodesForChart.map( (node) => {
|
||||
if (node.id === nodeId) {
|
||||
node.unifiedJobTemplate = selectedTemplate;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.formState.showNodeForm = false;
|
||||
$scope.nodeConfig = null;
|
||||
|
||||
@ -475,10 +472,15 @@ export default ['$scope', 'TemplatesService',
|
||||
};
|
||||
|
||||
$scope.cancelNodeForm = function() {
|
||||
const nodeIndex = chartNodeIdToIndexMapping[$scope.nodeConfig.nodeId];
|
||||
const nodeId = $scope.nodeConfig.nodeId;
|
||||
if ($scope.nodeConfig.mode === "add") {
|
||||
// Remove the placeholder node from the array
|
||||
$scope.graphState.arrayOfNodesForChart.splice(nodeIndex, 1);
|
||||
for( let i = $scope.graphState.arrayOfNodesForChart.length; i--; ){
|
||||
if ($scope.graphState.arrayOfNodesForChart[i].id === nodeId) {
|
||||
$scope.graphState.arrayOfNodesForChart.splice(i, 1);
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the links
|
||||
let parents = [];
|
||||
@ -488,47 +490,30 @@ export default ['$scope', 'TemplatesService',
|
||||
for( let i = $scope.graphState.arrayOfLinksForChart.length; i--; ){
|
||||
const link = $scope.graphState.arrayOfLinksForChart[i];
|
||||
|
||||
if (link.source.index === nodeIndex || link.target.index === nodeIndex) {
|
||||
if (link.source.index === nodeIndex) {
|
||||
const targetIndex = link.target.index < nodeIndex ? link.target.index : link.target.index - 1;
|
||||
children.push({index: targetIndex, edgeType: link.edgeType});
|
||||
} else if (link.target.index === nodeIndex) {
|
||||
const sourceIndex = link.source.index < nodeIndex ? link.source.index : link.source.index - 1;
|
||||
parents.push(sourceIndex);
|
||||
if (link.source.id === nodeId || link.target.id === nodeId) {
|
||||
if (link.source.id === nodeId) {
|
||||
children.push({id: link.target.id, edgeType: link.edgeType});
|
||||
} else if (link.target.id === nodeId) {
|
||||
parents.push(link.source.id);
|
||||
}
|
||||
$scope.graphState.arrayOfLinksForChart.splice(i, 1);
|
||||
} else {
|
||||
if (link.source.index > nodeIndex) {
|
||||
link.source.index--;
|
||||
}
|
||||
if (link.target.index > nodeIndex) {
|
||||
link.target.index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the new links
|
||||
parents.forEach((parentIndex) => {
|
||||
parents.forEach((parentId) => {
|
||||
children.forEach((child) => {
|
||||
if (parentIndex === 0) {
|
||||
if (parentId === 1) {
|
||||
child.edgeType = "always";
|
||||
}
|
||||
$scope.graphState.arrayOfLinksForChart.push({
|
||||
source: $scope.graphState.arrayOfNodesForChart[parentIndex],
|
||||
target: $scope.graphState.arrayOfNodesForChart[child.index],
|
||||
source: {id: parentId},
|
||||
target: {id: child.id},
|
||||
edgeType: child.edgeType
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
delete chartNodeIdToIndexMapping[$scope.nodeConfig.nodeId];
|
||||
|
||||
for (const key in chartNodeIdToIndexMapping) {
|
||||
if (chartNodeIdToIndexMapping[key] > nodeIndex) {
|
||||
chartNodeIdToIndexMapping[key]--;
|
||||
}
|
||||
}
|
||||
|
||||
} else if ($scope.nodeConfig.mode === "edit") {
|
||||
$scope.graphState.nodeBeingEdited = null;
|
||||
}
|
||||
@ -544,7 +529,7 @@ export default ['$scope', 'TemplatesService',
|
||||
$scope.cancelLinkForm();
|
||||
}
|
||||
|
||||
if (!$scope.nodeConfig || ($scope.nodeConfig && $scope.nodeConfig.nodeId !== nodeToEdit.index)) {
|
||||
if (!$scope.nodeConfig || ($scope.nodeConfig && $scope.nodeConfig.nodeId !== nodeToEdit.id)) {
|
||||
if ($scope.nodeConfig) {
|
||||
$scope.cancelNodeForm();
|
||||
}
|
||||
@ -583,11 +568,11 @@ export default ['$scope', 'TemplatesService',
|
||||
|
||||
$scope.linkConfig = {
|
||||
mode: "edit",
|
||||
parent: {
|
||||
source: {
|
||||
id: linkToEdit.source.id,
|
||||
name: _.get(linkToEdit, 'source.unifiedJobTemplate.name') || ""
|
||||
},
|
||||
child: {
|
||||
target: {
|
||||
id: linkToEdit.target.id,
|
||||
name: _.get(linkToEdit, 'target.unifiedJobTemplate.name') || ""
|
||||
},
|
||||
@ -604,7 +589,7 @@ export default ['$scope', 'TemplatesService',
|
||||
}
|
||||
|
||||
if ($scope.linkConfig) {
|
||||
if ($scope.linkConfig.parent.id !== linkToEdit.source.id || $scope.linkConfig.child.id !== linkToEdit.target.id) {
|
||||
if ($scope.linkConfig.source.id !== linkToEdit.source.id || $scope.linkConfig.target.id !== linkToEdit.target.id) {
|
||||
// User is going from editing one link to editing another
|
||||
if ($scope.linkConfig.mode === "add") {
|
||||
$scope.graphState.arrayOfLinksForChart.splice($scope.graphState.arrayOfLinksForChart.length-1, 1);
|
||||
@ -621,27 +606,31 @@ export default ['$scope', 'TemplatesService',
|
||||
if ($scope.nodeConfig) {
|
||||
$scope.cancelNodeForm();
|
||||
}
|
||||
// User was add/editing a link and then hit the link icon
|
||||
if ($scope.linkConfig && $scope.linkConfig.target) {
|
||||
$scope.cancelLinkForm();
|
||||
}
|
||||
if ($scope.linkConfig) {
|
||||
// This is the second node selected
|
||||
$scope.linkConfig.child = {
|
||||
$scope.linkConfig.target = {
|
||||
id: node.id,
|
||||
name: node.unifiedJobTemplate.name
|
||||
};
|
||||
$scope.linkConfig.edgeType = "success";
|
||||
|
||||
$scope.graphState.arrayOfNodesForChart.forEach((node) => {
|
||||
node.isInvalidLinkTarget = false;
|
||||
$scope.graphState.arrayOfNodesForChart.forEach((nodeToUpdate) => {
|
||||
nodeToUpdate.isInvalidLinkTarget = false;
|
||||
});
|
||||
|
||||
$scope.graphState.arrayOfLinksForChart.push({
|
||||
target: $scope.graphState.arrayOfNodesForChart[node.index],
|
||||
source: $scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[$scope.linkConfig.parent.id]],
|
||||
source: {id: $scope.linkConfig.source.id},
|
||||
target: {id: node.id},
|
||||
edgeType: "placeholder"
|
||||
});
|
||||
|
||||
$scope.graphState.linkBeingEdited = {
|
||||
source: $scope.graphState.arrayOfNodesForChart[node.index].id,
|
||||
target: $scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[$scope.linkConfig.parent.id]].id
|
||||
source: {id: $scope.linkConfig.source.id},
|
||||
target: {id: node.id}
|
||||
};
|
||||
|
||||
$scope.graphState.arrayOfLinksForChart.forEach((link, index) => {
|
||||
@ -656,7 +645,7 @@ export default ['$scope', 'TemplatesService',
|
||||
$scope.graphState.addLinkSource = node.id;
|
||||
$scope.linkConfig = {
|
||||
mode: "add",
|
||||
parent: {
|
||||
source: {
|
||||
id: node.id,
|
||||
name: node.unifiedJobTemplate.name
|
||||
}
|
||||
@ -693,7 +682,11 @@ export default ['$scope', 'TemplatesService',
|
||||
|
||||
// Filter out the duplicates
|
||||
invalidLinkTargetIds.filter((element, index, array) => index === array.indexOf(element)).forEach((ancestorId) => {
|
||||
$scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[ancestorId]].isInvalidLinkTarget = true;
|
||||
$scope.graphState.arrayOfNodesForChart.forEach((node) => {
|
||||
if (node.id === ancestorId) {
|
||||
node.isInvalidLinkTarget = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$scope.graphState.isLinkMode = true;
|
||||
@ -706,7 +699,7 @@ export default ['$scope', 'TemplatesService',
|
||||
|
||||
$scope.confirmLinkForm = (newEdgeType) => {
|
||||
$scope.graphState.arrayOfLinksForChart.forEach((link) => {
|
||||
if (link.source.id === $scope.linkConfig.parent.id && link.target.id === $scope.linkConfig.child.id) {
|
||||
if (link.source.id === $scope.linkConfig.source.id && link.target.id === $scope.linkConfig.target.id) {
|
||||
link.edgeType = newEdgeType;
|
||||
}
|
||||
});
|
||||
@ -729,7 +722,7 @@ export default ['$scope', 'TemplatesService',
|
||||
for( let i = $scope.graphState.arrayOfLinksForChart.length; i--; ){
|
||||
const link = $scope.graphState.arrayOfLinksForChart[i];
|
||||
|
||||
if (link.source.id === $scope.linkConfig.parent.id && link.target.id === $scope.linkConfig.child.id) {
|
||||
if (link.source.id === $scope.linkConfig.source.id && link.target.id === $scope.linkConfig.target.id) {
|
||||
$scope.graphState.arrayOfLinksForChart.splice(i, 1);
|
||||
}
|
||||
}
|
||||
@ -740,19 +733,19 @@ export default ['$scope', 'TemplatesService',
|
||||
};
|
||||
|
||||
$scope.cancelLinkForm = () => {
|
||||
if ($scope.linkConfig.mode === "add" && $scope.linkConfig.child) {
|
||||
if ($scope.linkConfig.mode === "add" && $scope.linkConfig.target) {
|
||||
$scope.graphState.arrayOfLinksForChart.splice($scope.graphState.arrayOfLinksForChart.length-1, 1);
|
||||
let targetIsOrphaned = true;
|
||||
$scope.graphState.arrayOfLinksForChart.forEach((link) => {
|
||||
if (link.target.id === $scope.linkConfig.child.id) {
|
||||
if (link.target.id === $scope.linkConfig.target.id) {
|
||||
targetIsOrphaned = false;
|
||||
}
|
||||
});
|
||||
if (targetIsOrphaned) {
|
||||
// Link it to the start node
|
||||
$scope.graphState.arrayOfLinksForChart.push({
|
||||
source: $scope.graphState.arrayOfNodesForChart[0],
|
||||
target: $scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[$scope.linkConfig.child.id]],
|
||||
source: {id: 1},
|
||||
target: {id: $scope.linkConfig.target.id},
|
||||
edgeType: "always"
|
||||
});
|
||||
}
|
||||
@ -782,53 +775,69 @@ export default ['$scope', 'TemplatesService',
|
||||
|
||||
$scope.confirmDeleteNode = function () {
|
||||
if ($scope.nodeToBeDeleted) {
|
||||
const nodeIndex = $scope.nodeToBeDeleted.index;
|
||||
const nodeId = $scope.nodeToBeDeleted.id;
|
||||
|
||||
if ($scope.linkBeingWorkedOn) {
|
||||
if ($scope.linkConfig) {
|
||||
$scope.cancelLinkForm();
|
||||
}
|
||||
|
||||
// Remove the node from the array
|
||||
$scope.graphState.arrayOfNodesForChart.splice(nodeIndex, 1);
|
||||
for( let i = $scope.graphState.arrayOfNodesForChart.length; i--; ){
|
||||
if ($scope.graphState.arrayOfNodesForChart[i].id === nodeId) {
|
||||
$scope.graphState.arrayOfNodesForChart.splice(i, 1);
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the links
|
||||
let parents = [];
|
||||
let children = [];
|
||||
let linkParentMapping = {};
|
||||
|
||||
// Remove any links that reference this node
|
||||
for( let i = $scope.graphState.arrayOfLinksForChart.length; i--; ){
|
||||
const link = $scope.graphState.arrayOfLinksForChart[i];
|
||||
|
||||
if (link.source.index === nodeIndex || link.target.index === nodeIndex) {
|
||||
if (link.source.index === nodeIndex) {
|
||||
const targetIndex = link.target.index < nodeIndex ? link.target.index : link.target.index - 1;
|
||||
children.push({index: targetIndex, edgeType: link.edgeType});
|
||||
} else if (link.target.index === nodeIndex) {
|
||||
const sourceIndex = link.source.index < nodeIndex ? link.source.index : link.source.index - 1;
|
||||
parents.push(sourceIndex);
|
||||
if (!linkParentMapping[link.target.id]) {
|
||||
linkParentMapping[link.target.id] = [];
|
||||
}
|
||||
|
||||
linkParentMapping[link.target.id].push(link.source.id);
|
||||
|
||||
if (link.source.id === nodeId || link.target.id === nodeId) {
|
||||
if (link.source.id === nodeId) {
|
||||
children.push({id: link.target.id, edgeType: link.edgeType});
|
||||
} else if (link.target.id === nodeId) {
|
||||
parents.push(link.source.id);
|
||||
}
|
||||
$scope.graphState.arrayOfLinksForChart.splice(i, 1);
|
||||
} else {
|
||||
// if (link.source.index > nodeIndex) {
|
||||
// link.source.index = link.source.index - 1;
|
||||
// }
|
||||
// if (link.target.index > nodeIndex) {
|
||||
// link.target.index = link.target.index - 1;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
// Add the new links
|
||||
parents.forEach((parentIndex) => {
|
||||
parents.forEach((parentId) => {
|
||||
children.forEach((child) => {
|
||||
if (parentIndex === 0) {
|
||||
child.edgeType = "always";
|
||||
if (parentId === 1) {
|
||||
// We only want to create a link from the start node to this node if it
|
||||
// doesn't have any other parents
|
||||
if(linkParentMapping[child.id].length === 1) {
|
||||
$scope.graphState.arrayOfLinksForChart.push({
|
||||
source: {id: parentId},
|
||||
target: {id: child.id},
|
||||
edgeType: "always"
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// We don't want to add a link that already exists
|
||||
if (!linkParentMapping[child.id].includes(parentId)) {
|
||||
$scope.graphState.arrayOfLinksForChart.push({
|
||||
source: {id: parentId},
|
||||
target: {id: child.id},
|
||||
edgeType: child.edgeType
|
||||
});
|
||||
}
|
||||
}
|
||||
$scope.graphState.arrayOfLinksForChart.push({
|
||||
source: $scope.graphState.arrayOfNodesForChart[parentIndex],
|
||||
target: $scope.graphState.arrayOfNodesForChart[child.index],
|
||||
edgeType: child.edgeType
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@ -838,12 +847,6 @@ export default ['$scope', 'TemplatesService',
|
||||
|
||||
delete nodeRef[$scope.nodeToBeDeleted.id];
|
||||
|
||||
for (const key in chartNodeIdToIndexMapping) {
|
||||
if (chartNodeIdToIndexMapping[key] > $scope.nodeToBeDeleted.index) {
|
||||
chartNodeIdToIndexMapping[key]--;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.deleteOverlayVisible = false;
|
||||
|
||||
$scope.nodeToBeDeleted = null;
|
||||
@ -902,7 +905,7 @@ export default ['$scope', 'TemplatesService',
|
||||
let arrayOfLinksForChart = [];
|
||||
let arrayOfNodesForChart = [];
|
||||
|
||||
({arrayOfNodesForChart, arrayOfLinksForChart, chartNodeIdToIndexMapping, nodeIdToChartNodeIdMapping, nodeRef, workflowMakerNodeIdCounter} = WorkflowChartService.generateArraysOfNodesAndLinks(allNodes));
|
||||
({arrayOfNodesForChart, arrayOfLinksForChart, nodeIdToChartNodeIdMapping, nodeRef, workflowMakerNodeIdCounter} = WorkflowChartService.generateArraysOfNodesAndLinks(allNodes));
|
||||
|
||||
$scope.graphState = { arrayOfNodesForChart, arrayOfLinksForChart };
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user