mirror of
https://github.com/ansible/awx.git
synced 2026-02-23 22:16:00 -03:30
Merge pull request #2726 from mabashian/workflow-cleanup-7
Code cleanup. Fixed bugs with workflow results page including details links
This commit is contained in:
@@ -62,7 +62,7 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
|||||||
return d.y;
|
return d.y;
|
||||||
});
|
});
|
||||||
|
|
||||||
zoomObj = d3.behavior.zoom().scaleExtent([0.5, 2]);
|
zoomObj = d3.behavior.zoom().scaleExtent([0.1, 2]);
|
||||||
|
|
||||||
baseSvg = d3.select(element[0]).append("svg")
|
baseSvg = d3.select(element[0]).append("svg")
|
||||||
.attr("class", "WorkflowChart-svg")
|
.attr("class", "WorkflowChart-svg")
|
||||||
@@ -1130,9 +1130,11 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
|||||||
thisNode.append("foreignObject")
|
thisNode.append("foreignObject")
|
||||||
.attr("x", nodeW - 6)
|
.attr("x", nodeW - 6)
|
||||||
.attr("y", nodeH/2 - 9)
|
.attr("y", nodeH/2 - 9)
|
||||||
|
.attr("height", "17px")
|
||||||
|
.attr("width", "13px")
|
||||||
.style("font-size","14px")
|
.style("font-size","14px")
|
||||||
.html(function () {
|
.html(function () {
|
||||||
return `<span class="fa fa-link" />`;
|
return `<span class="fa fa-link"></span>`;
|
||||||
})
|
})
|
||||||
.attr("class", "WorkflowChart-nodeLinkIcon")
|
.attr("class", "WorkflowChart-nodeLinkIcon")
|
||||||
.style("display", function(d) { return d.id === scope.graphState.nodeBeingAdded || scope.readOnly ? "none" : null; })
|
.style("display", function(d) { return d.id === scope.graphState.nodeBeingAdded || scope.readOnly ? "none" : null; })
|
||||||
@@ -1347,46 +1349,18 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
|
|||||||
d3.select(this).style("text-decoration", null);
|
d3.select(this).style("text-decoration", null);
|
||||||
});
|
});
|
||||||
this.on("click", function(d) {
|
this.on("click", function(d) {
|
||||||
|
if(d.job.type === 'job') {
|
||||||
let goToJobResults = function(job_type) {
|
$state.go('output', {id: d.job.id, type: 'playbook'});
|
||||||
if(job_type === 'job') {
|
}
|
||||||
$state.go('output', {id: d.job.id, type: 'playbook'});
|
else if(d.job.type === 'inventory_update') {
|
||||||
}
|
$state.go('output', {id: d.job.id, type: 'inventory'});
|
||||||
else if(job_type === 'inventory_update') {
|
}
|
||||||
$state.go('output', {id: d.job.id, type: 'inventory'});
|
else if(d.job.type === 'project_update') {
|
||||||
}
|
$state.go('output', {id: d.job.id, type: 'project'});
|
||||||
else if(job_type === 'project_update') {
|
} else if (d.job.type === 'workflow_job') {
|
||||||
$state.go('output', {id: d.job.id, type: 'project'});
|
$state.go('workflowResults', {
|
||||||
}
|
id: d.job.id,
|
||||||
};
|
});
|
||||||
|
|
||||||
if(d.job.type) {
|
|
||||||
if(d.unifiedJobTemplate) {
|
|
||||||
goToJobResults(d.unifiedJobTemplate.unified_job_type);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// 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("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) {
|
|
||||||
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
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
export default [function(){
|
export default [function(){
|
||||||
return {
|
return {
|
||||||
generateArraysOfNodesAndLinks: function(allNodes) {
|
generateArraysOfNodesAndLinks: (allNodes) => {
|
||||||
let nonRootNodeIds = [];
|
let nonRootNodeIds = [];
|
||||||
let allNodeIds = [];
|
let allNodeIds = [];
|
||||||
let arrayOfLinksForChart = [];
|
let arrayOfLinksForChart = [];
|
||||||
@@ -15,10 +15,7 @@ export default [function(){
|
|||||||
isStartNode: true,
|
isStartNode: true,
|
||||||
unifiedJobTemplate: {
|
unifiedJobTemplate: {
|
||||||
name: "START"
|
name: "START"
|
||||||
},
|
}
|
||||||
fixed: true,
|
|
||||||
x: 0,
|
|
||||||
y: 0
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
nodeIdCounter++;
|
nodeIdCounter++;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default ['templateUrl',
|
|||||||
scope.zoom = 100;
|
scope.zoom = 100;
|
||||||
$( "#slider" ).slider({
|
$( "#slider" ).slider({
|
||||||
value:100,
|
value:100,
|
||||||
min: 50,
|
min: 10,
|
||||||
max: 200,
|
max: 200,
|
||||||
step: 10,
|
step: 10,
|
||||||
slide: function( event, ui ) {
|
slide: function( event, ui ) {
|
||||||
@@ -54,7 +54,7 @@ export default ['templateUrl',
|
|||||||
};
|
};
|
||||||
|
|
||||||
scope.zoomOut = function() {
|
scope.zoomOut = function() {
|
||||||
scope.zoom = Math.floor((scope.zoom - 10) / 10) * 10 > 50 ? Math.floor((scope.zoom - 10) / 10) * 10 : 50;
|
scope.zoom = Math.floor((scope.zoom - 10) / 10) * 10 > 10 ? Math.floor((scope.zoom - 10) / 10) * 10 : 10;
|
||||||
$("#slider").slider('value',scope.zoom);
|
$("#slider").slider('value',scope.zoom);
|
||||||
scope.zoomChart({
|
scope.zoomChart({
|
||||||
zoom: scope.zoom
|
zoom: scope.zoom
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
'missingSurveyValue'
|
'missingSurveyValue'
|
||||||
];
|
];
|
||||||
|
|
||||||
promptWatcher = $scope.$watchGroup(promptDataToWatch, function() {
|
promptWatcher = $scope.$watchGroup(promptDataToWatch, () => {
|
||||||
let missingPromptValue = false;
|
let missingPromptValue = false;
|
||||||
if ($scope.missingSurveyValue) {
|
if ($scope.missingSurveyValue) {
|
||||||
missingPromptValue = true;
|
missingPromptValue = true;
|
||||||
@@ -524,7 +524,7 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
|
|
||||||
listPromises.push(
|
listPromises.push(
|
||||||
qs.search(GetBasePath('unified_job_templates'), $scope.wf_maker_template_queryset)
|
qs.search(GetBasePath('unified_job_templates'), $scope.wf_maker_template_queryset)
|
||||||
.then(function(res) {
|
.then((res) => {
|
||||||
$scope.wf_maker_template_dataset = res.data;
|
$scope.wf_maker_template_dataset = res.data;
|
||||||
$scope.wf_maker_templates = $scope.wf_maker_template_dataset.results;
|
$scope.wf_maker_templates = $scope.wf_maker_template_dataset.results;
|
||||||
})
|
})
|
||||||
@@ -540,7 +540,7 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
|
|
||||||
listPromises.push(
|
listPromises.push(
|
||||||
qs.search(GetBasePath('projects'), $scope.wf_maker_project_queryset)
|
qs.search(GetBasePath('projects'), $scope.wf_maker_project_queryset)
|
||||||
.then(function(res) {
|
.then((res) => {
|
||||||
$scope.wf_maker_project_dataset = res.data;
|
$scope.wf_maker_project_dataset = res.data;
|
||||||
$scope.wf_maker_projects = $scope.wf_maker_project_dataset.results;
|
$scope.wf_maker_projects = $scope.wf_maker_project_dataset.results;
|
||||||
})
|
})
|
||||||
@@ -557,7 +557,7 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
|
|
||||||
listPromises.push(
|
listPromises.push(
|
||||||
qs.search(GetBasePath('inventory_sources'), $scope.wf_maker_inventory_source_dataset)
|
qs.search(GetBasePath('inventory_sources'), $scope.wf_maker_inventory_source_dataset)
|
||||||
.then(function(res) {
|
.then((res) => {
|
||||||
$scope.wf_maker_inventory_source_dataset = res.data;
|
$scope.wf_maker_inventory_source_dataset = res.data;
|
||||||
$scope.wf_maker_inventory_sources = $scope.wf_maker_inventory_source_dataset.results;
|
$scope.wf_maker_inventory_sources = $scope.wf_maker_inventory_source_dataset.results;
|
||||||
})
|
})
|
||||||
@@ -567,14 +567,14 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
if ($scope.nodeConfig.mode === "edit") {
|
if ($scope.nodeConfig.mode === "edit") {
|
||||||
// Make sure that we have the full unified job template object
|
// Make sure that we have the full unified job template object
|
||||||
if (!$scope.nodeConfig.node.fullUnifiedJobTemplate && _.get($scope, 'nodeConfig.node.originalNodeObject.summary_fields.unified_job_template.unified_job_type') === 'job') {
|
if (!$scope.nodeConfig.node.fullUnifiedJobTemplateObject && _.get($scope, 'nodeConfig.node.originalNodeObject.summary_fields.unified_job_template.unified_job_type') === 'job') {
|
||||||
// This is a node that we got back from the api with an incomplete
|
// This is a node that we got back from the api with an incomplete
|
||||||
// unified job template so we're going to pull down the whole object
|
// unified job template so we're going to pull down the whole object
|
||||||
TemplatesService.getUnifiedJobTemplate($scope.nodeConfig.node.originalNodeObject.summary_fields.unified_job_template.id)
|
TemplatesService.getUnifiedJobTemplate($scope.nodeConfig.node.originalNodeObject.summary_fields.unified_job_template.id)
|
||||||
.then(function({data}) {
|
.then(({data}) => {
|
||||||
$scope.nodeConfig.node.fullUnifiedJobTemplateObject = data.results[0];
|
$scope.nodeConfig.node.fullUnifiedJobTemplateObject = data.results[0];
|
||||||
finishConfiguringEdit();
|
finishConfiguringEdit();
|
||||||
}, function(error) {
|
}, (error) => {
|
||||||
ProcessErrors($scope, error.data, error.status, null, {
|
ProcessErrors($scope, error.data, error.status, null, {
|
||||||
hdr: 'Error!',
|
hdr: 'Error!',
|
||||||
msg: 'Failed to get unified job template. GET returned ' +
|
msg: 'Failed to get unified job template. GET returned ' +
|
||||||
@@ -590,16 +590,15 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.openPromptModal = function() {
|
$scope.openPromptModal = () => {
|
||||||
$scope.promptData.triggerModalOpen = true;
|
$scope.promptData.triggerModalOpen = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.toggle_row = function(selectedRow) {
|
$scope.toggle_row = (selectedRow) => {
|
||||||
if (!$scope.readOnly) {
|
if (!$scope.readOnly) {
|
||||||
// TODO: make this more concise
|
|
||||||
switch($scope.activeTab) {
|
switch($scope.activeTab) {
|
||||||
case 'jobs':
|
case 'jobs':
|
||||||
$scope.wf_maker_templates.forEach(function(row, i) {
|
$scope.wf_maker_templates.forEach((row, i) => {
|
||||||
if (row.id === selectedRow.id) {
|
if (row.id === selectedRow.id) {
|
||||||
$scope.wf_maker_templates[i].checked = 1;
|
$scope.wf_maker_templates[i].checked = 1;
|
||||||
|
|
||||||
@@ -609,7 +608,7 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'project_syncs':
|
case 'project_syncs':
|
||||||
$scope.wf_maker_projects.forEach(function(row, i) {
|
$scope.wf_maker_projects.forEach((row, i) => {
|
||||||
if (row.id === selectedRow.id) {
|
if (row.id === selectedRow.id) {
|
||||||
$scope.wf_maker_projects[i].checked = 1;
|
$scope.wf_maker_projects[i].checked = 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -618,7 +617,7 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'inventory_syncs':
|
case 'inventory_syncs':
|
||||||
$scope.wf_maker_inventory_sources.forEach(function(row, i) {
|
$scope.wf_maker_inventory_sources.forEach((row, i) => {
|
||||||
if (row.id === selectedRow.id) {
|
if (row.id === selectedRow.id) {
|
||||||
$scope.wf_maker_inventory_sources[i].checked = 1;
|
$scope.wf_maker_inventory_sources[i].checked = 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -638,11 +637,11 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
});
|
});
|
||||||
|
|
||||||
$scope.$watchGroup(['wf_maker_templates', 'wf_maker_projects', 'wf_maker_inventory_sources', 'activeTab'], () => {
|
$scope.$watchGroup(['wf_maker_templates', 'wf_maker_projects', 'wf_maker_inventory_sources', 'activeTab'], () => {
|
||||||
// TODO: make this more concise
|
const unifiedJobTemplateId = _.get($scope, 'nodeConfig.node.fullUnifiedJobTemplateObject.id') || _.get($scope, 'nodeConfig.node.unifiedJobTemplate.id') || null;
|
||||||
switch($scope.activeTab) {
|
switch($scope.activeTab) {
|
||||||
case 'jobs':
|
case 'jobs':
|
||||||
$scope.wf_maker_templates.forEach(function(row, i) {
|
$scope.wf_maker_templates.forEach((row, i) => {
|
||||||
if(_.hasIn($scope, 'nodeConfig.node.fullUnifiedJobTemplateObject.id') && row.id === $scope.nodeConfig.node.fullUnifiedJobTemplateObject.id) {
|
if(row.id === unifiedJobTemplateId) {
|
||||||
$scope.wf_maker_templates[i].checked = 1;
|
$scope.wf_maker_templates[i].checked = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -651,8 +650,8 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'project_syncs':
|
case 'project_syncs':
|
||||||
$scope.wf_maker_projects.forEach(function(row, i) {
|
$scope.wf_maker_projects.forEach((row, i) => {
|
||||||
if(_.hasIn($scope, 'nodeConfig.node.fullUnifiedJobTemplateObject.id') && row.id === $scope.nodeConfig.node.fullUnifiedJobTemplateObject.id) {
|
if(row.id === unifiedJobTemplateId) {
|
||||||
$scope.wf_maker_projects[i].checked = 1;
|
$scope.wf_maker_projects[i].checked = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -661,8 +660,8 @@ export default ['$scope', 'TemplatesService', 'JobTemplateModel', 'PromptService
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'inventory_syncs':
|
case 'inventory_syncs':
|
||||||
$scope.wf_maker_inventory_sources.forEach(function(row, i) {
|
$scope.wf_maker_inventory_sources.forEach((row, i) => {
|
||||||
if(_.hasIn($scope, 'nodeConfig.node.fullUnifiedJobTemplateObject.id') && row.id === $scope.nodeConfig.node.fullUnifiedJobTemplateObject.id) {
|
if(row.id === unifiedJobTemplateId) {
|
||||||
$scope.wf_maker_inventory_sources[i].checked = 1;
|
$scope.wf_maker_inventory_sources[i].checked = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -14,86 +14,121 @@ export default ['$scope', 'TemplatesService',
|
|||||||
Wait
|
Wait
|
||||||
) {
|
) {
|
||||||
|
|
||||||
$scope.strings = TemplatesStrings;
|
|
||||||
$scope.preventCredsWithPasswords = true;
|
|
||||||
|
|
||||||
let deletedNodeIds = [];
|
let deletedNodeIds = [];
|
||||||
let workflowMakerNodeIdCounter = 1;
|
let workflowMakerNodeIdCounter;
|
||||||
let nodeIdToChartNodeIdMapping = {};
|
let nodeIdToChartNodeIdMapping = {};
|
||||||
let nodeRef = {};
|
let nodeRef = {};
|
||||||
|
let allNodes = [];
|
||||||
|
let page = 1;
|
||||||
|
|
||||||
|
$scope.strings = TemplatesStrings;
|
||||||
|
$scope.preventCredsWithPasswords = true;
|
||||||
$scope.showKey = false;
|
$scope.showKey = false;
|
||||||
$scope.toggleKey = () => $scope.showKey = !$scope.showKey;
|
$scope.toggleKey = () => $scope.showKey = !$scope.showKey;
|
||||||
$scope.keyClassList = `{ 'Key-menuIcon--active': showKey }`;
|
$scope.keyClassList = `{ 'Key-menuIcon--active': showKey }`;
|
||||||
|
|
||||||
$scope.readOnly = !_.get($scope, 'workflowJobTemplateObj.summary_fields.user_capabilities.edit');
|
$scope.readOnly = !_.get($scope, 'workflowJobTemplateObj.summary_fields.user_capabilities.edit');
|
||||||
|
|
||||||
$scope.formState = {
|
$scope.formState = {
|
||||||
'showNodeForm': false,
|
'showNodeForm': false,
|
||||||
'showLinkForm': false
|
'showLinkForm': false
|
||||||
};
|
};
|
||||||
|
|
||||||
let buildSendableNodeData = function (node) {
|
let getNodes = () => {
|
||||||
// Create the node
|
Wait('start');
|
||||||
let sendableNodeData = {
|
TemplatesService.getWorkflowJobTemplateNodes($scope.workflowJobTemplateObj.id, page)
|
||||||
extra_data: {},
|
.then(({data}) => {
|
||||||
inventory: null,
|
for (var i = 0; i < data.results.length; i++) {
|
||||||
job_type: null,
|
allNodes.push(data.results[i]);
|
||||||
job_tags: null,
|
}
|
||||||
skip_tags: null,
|
if (data.next) {
|
||||||
limit: null,
|
// Get the next page
|
||||||
diff_mode: null,
|
page++;
|
||||||
verbosity: null,
|
getNodes();
|
||||||
credential: null
|
} else {
|
||||||
};
|
let arrayOfLinksForChart = [];
|
||||||
|
let arrayOfNodesForChart = [];
|
||||||
|
|
||||||
if (_.has(node, 'fullUnifiedJobTemplateObject')) {
|
({arrayOfNodesForChart, arrayOfLinksForChart, nodeIdToChartNodeIdMapping, nodeRef, workflowMakerNodeIdCounter} = WorkflowChartService.generateArraysOfNodesAndLinks(allNodes));
|
||||||
sendableNodeData.unified_job_template = node.fullUnifiedJobTemplateObject.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_.has(node, 'promptData.extraVars')) {
|
$scope.graphState = { arrayOfNodesForChart, arrayOfLinksForChart };
|
||||||
if (_.get(node, 'promptData.launchConf.defaults.extra_vars')) {
|
|
||||||
const defaultVars = jsyaml.safeLoad(node.promptData.launchConf.defaults.extra_vars);
|
|
||||||
|
|
||||||
// Only include extra vars that differ from the template default vars
|
Wait('stop');
|
||||||
_.forOwn(node.promptData.extraVars, (value, key) => {
|
}
|
||||||
if (!defaultVars[key] || defaultVars[key] !== value) {
|
}, ({ data, status, config }) => {
|
||||||
sendableNodeData.extra_data[key] = value;
|
Wait('stop');
|
||||||
}
|
ProcessErrors($scope, data, status, null, {
|
||||||
|
hdr: $scope.strings.get('error.HEADER'),
|
||||||
|
msg: $scope.strings.get('error.CALL', {
|
||||||
|
path: `${config.url}`,
|
||||||
|
action: `${config.method}`,
|
||||||
|
status
|
||||||
|
})
|
||||||
});
|
});
|
||||||
if (_.isEmpty(sendableNodeData.extra_data)) {
|
|
||||||
delete sendableNodeData.extra_data;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (_.has(node, 'promptData.extraVars') && !_.isEmpty(node.promptData.extraVars)) {
|
|
||||||
sendableNodeData.extra_data = node.promptData.extraVars;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check to see if the user has provided any prompt values that are different
|
|
||||||
// from the defaults in the job template
|
|
||||||
|
|
||||||
if (_.has(node, 'fullUnifiedJobTemplateObject') && node.fullUnifiedJobTemplateObject.type === "job_template" && node.promptData) {
|
|
||||||
sendableNodeData = PromptService.bundlePromptDataForSaving({
|
|
||||||
promptData: node.promptData,
|
|
||||||
dataToSave: sendableNodeData
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return sendableNodeData;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.closeWorkflowMaker = function() {
|
getNodes();
|
||||||
|
|
||||||
|
$scope.closeWorkflowMaker = () => {
|
||||||
// Revert the data to the master which was created when the dialog was opened
|
// Revert the data to the master which was created when the dialog was opened
|
||||||
$scope.graphState.nodeTree = angular.copy($scope.graphStateMaster);
|
$scope.graphState.nodeTree = angular.copy($scope.graphStateMaster);
|
||||||
$scope.closeDialog();
|
$scope.closeDialog();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.saveWorkflowMaker = function () {
|
$scope.saveWorkflowMaker = () => {
|
||||||
|
|
||||||
Wait('start');
|
Wait('start');
|
||||||
|
|
||||||
|
let buildSendableNodeData = (node) => {
|
||||||
|
// Create the node
|
||||||
|
let sendableNodeData = {
|
||||||
|
extra_data: {},
|
||||||
|
inventory: null,
|
||||||
|
job_type: null,
|
||||||
|
job_tags: null,
|
||||||
|
skip_tags: null,
|
||||||
|
limit: null,
|
||||||
|
diff_mode: null,
|
||||||
|
verbosity: null,
|
||||||
|
credential: null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_.has(node, 'fullUnifiedJobTemplateObject')) {
|
||||||
|
sendableNodeData.unified_job_template = node.fullUnifiedJobTemplateObject.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.has(node, 'promptData.extraVars')) {
|
||||||
|
if (_.get(node, 'promptData.launchConf.defaults.extra_vars')) {
|
||||||
|
const defaultVars = jsyaml.safeLoad(node.promptData.launchConf.defaults.extra_vars);
|
||||||
|
|
||||||
|
// Only include extra vars that differ from the template default vars
|
||||||
|
_.forOwn(node.promptData.extraVars, (value, key) => {
|
||||||
|
if (!defaultVars[key] || defaultVars[key] !== value) {
|
||||||
|
sendableNodeData.extra_data[key] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (_.isEmpty(sendableNodeData.extra_data)) {
|
||||||
|
delete sendableNodeData.extra_data;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (_.has(node, 'promptData.extraVars') && !_.isEmpty(node.promptData.extraVars)) {
|
||||||
|
sendableNodeData.extra_data = node.promptData.extraVars;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if the user has provided any prompt values that are different
|
||||||
|
// from the defaults in the job template
|
||||||
|
|
||||||
|
if (_.has(node, 'fullUnifiedJobTemplateObject') && node.fullUnifiedJobTemplateObject.type === "job_template" && node.promptData) {
|
||||||
|
sendableNodeData = PromptService.bundlePromptDataForSaving({
|
||||||
|
promptData: node.promptData,
|
||||||
|
dataToSave: sendableNodeData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return sendableNodeData;
|
||||||
|
};
|
||||||
|
|
||||||
if ($scope.graphState.arrayOfNodesForChart.length > 1) {
|
if ($scope.graphState.arrayOfNodesForChart.length > 1) {
|
||||||
let addPromises = [];
|
let addPromises = [];
|
||||||
let editPromises = [];
|
let editPromises = [];
|
||||||
@@ -110,9 +145,9 @@ export default ['$scope', 'TemplatesService',
|
|||||||
if (_.get(nodeRef[workflowMakerNodeId], 'promptData.launchConf.ask_credential_on_launch')) {
|
if (_.get(nodeRef[workflowMakerNodeId], 'promptData.launchConf.ask_credential_on_launch')) {
|
||||||
// This finds the credentials that were selected in the prompt but don't occur
|
// This finds the credentials that were selected in the prompt but don't occur
|
||||||
// in the template defaults
|
// in the template defaults
|
||||||
let credentialIdsToPost = nodeRef[workflowMakerNodeId].promptData.prompts.credentials.value.filter(function (credFromPrompt) {
|
let credentialIdsToPost = nodeRef[workflowMakerNodeId].promptData.prompts.credentials.value.filter((credFromPrompt) => {
|
||||||
let defaultCreds = _.get(nodeRef[workflowMakerNodeId], 'promptData.launchConf.defaults.credentials', []);
|
let defaultCreds = _.get(nodeRef[workflowMakerNodeId], 'promptData.launchConf.defaults.credentials', []);
|
||||||
return !defaultCreds.some(function (defaultCred) {
|
return !defaultCreds.some((defaultCred) => {
|
||||||
return credFromPrompt.id === defaultCred.id;
|
return credFromPrompt.id === defaultCred.id;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -134,16 +169,16 @@ export default ['$scope', 'TemplatesService',
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
if (_.get(nodeRef[workflowMakerNodeId], 'promptData.launchConf.ask_credential_on_launch')) {
|
if (_.get(nodeRef[workflowMakerNodeId], 'promptData.launchConf.ask_credential_on_launch')) {
|
||||||
let credentialsNotInPriorCredentials = nodeRef[workflowMakerNodeId].promptData.prompts.credentials.value.filter(function (credFromPrompt) {
|
let credentialsNotInPriorCredentials = nodeRef[workflowMakerNodeId].promptData.prompts.credentials.value.filter((credFromPrompt) => {
|
||||||
let defaultCreds = _.get(nodeRef[workflowMakerNodeId], 'promptData.launchConf.defaults.credentials', []);
|
let defaultCreds = _.get(nodeRef[workflowMakerNodeId], 'promptData.launchConf.defaults.credentials', []);
|
||||||
return !defaultCreds.some(function (defaultCred) {
|
return !defaultCreds.some((defaultCred) => {
|
||||||
return credFromPrompt.id === defaultCred.id;
|
return credFromPrompt.id === defaultCred.id;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let credentialsToAdd = credentialsNotInPriorCredentials.filter(function (credNotInPrior) {
|
let credentialsToAdd = credentialsNotInPriorCredentials.filter((credNotInPrior) => {
|
||||||
let previousOverrides = _.get(nodeRef[workflowMakerNodeId], 'promptData.prompts.credentials.previousOverrides', []);
|
let previousOverrides = _.get(nodeRef[workflowMakerNodeId], 'promptData.prompts.credentials.previousOverrides', []);
|
||||||
return !previousOverrides.some(function (priorCred) {
|
return !previousOverrides.some((priorCred) => {
|
||||||
return credNotInPrior.id === priorCred.id;
|
return credNotInPrior.id === priorCred.id;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -151,8 +186,8 @@ export default ['$scope', 'TemplatesService',
|
|||||||
let credentialsToRemove = [];
|
let credentialsToRemove = [];
|
||||||
|
|
||||||
if (_.has(nodeRef[workflowMakerNodeId], 'promptData.prompts.credentials.previousOverrides')) {
|
if (_.has(nodeRef[workflowMakerNodeId], 'promptData.prompts.credentials.previousOverrides')) {
|
||||||
credentialsToRemove = nodeRef[workflowMakerNodeId].promptData.prompts.credentials.previousOverrides.filter(function (priorCred) {
|
credentialsToRemove = nodeRef[workflowMakerNodeId].promptData.prompts.credentials.previousOverrides.filter((priorCred) => {
|
||||||
return !credentialsNotInPriorCredentials.some(function (credNotInPrior) {
|
return !credentialsNotInPriorCredentials.some((credNotInPrior) => {
|
||||||
return priorCred.id === credNotInPrior.id;
|
return priorCred.id === credNotInPrior.id;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -181,7 +216,7 @@ export default ['$scope', 'TemplatesService',
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let deletePromises = deletedNodeIds.map(function (nodeId) {
|
let deletePromises = deletedNodeIds.map((nodeId) => {
|
||||||
return TemplatesService.deleteWorkflowJobTemplateNode(nodeId);
|
return TemplatesService.deleteWorkflowJobTemplateNode(nodeId);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -315,8 +350,8 @@ export default ['$scope', 'TemplatesService',
|
|||||||
});
|
});
|
||||||
|
|
||||||
$q.all(disassociatePromises)
|
$q.all(disassociatePromises)
|
||||||
.then(function () {
|
.then(() => {
|
||||||
let credentialPromises = credentialRequests.map(function (request) {
|
let credentialPromises = credentialRequests.map((request) => {
|
||||||
return TemplatesService.postWorkflowNodeCredential({
|
return TemplatesService.postWorkflowNodeCredential({
|
||||||
id: request.id,
|
id: request.id,
|
||||||
data: request.data
|
data: request.data
|
||||||
@@ -324,7 +359,7 @@ export default ['$scope', 'TemplatesService',
|
|||||||
});
|
});
|
||||||
|
|
||||||
return $q.all(associatePromises.concat(credentialPromises))
|
return $q.all(associatePromises.concat(credentialPromises))
|
||||||
.then(function () {
|
.then(() => {
|
||||||
Wait('stop');
|
Wait('stop');
|
||||||
$scope.closeDialog();
|
$scope.closeDialog();
|
||||||
});
|
});
|
||||||
@@ -339,12 +374,12 @@ export default ['$scope', 'TemplatesService',
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
let deletePromises = deletedNodeIds.map(function (nodeId) {
|
let deletePromises = deletedNodeIds.map((nodeId) => {
|
||||||
return TemplatesService.deleteWorkflowJobTemplateNode(nodeId);
|
return TemplatesService.deleteWorkflowJobTemplateNode(nodeId);
|
||||||
});
|
});
|
||||||
|
|
||||||
$q.all(deletePromises)
|
$q.all(deletePromises)
|
||||||
.then(function () {
|
.then(() => {
|
||||||
Wait('stop');
|
Wait('stop');
|
||||||
$scope.closeDialog();
|
$scope.closeDialog();
|
||||||
});
|
});
|
||||||
@@ -353,7 +388,7 @@ export default ['$scope', 'TemplatesService',
|
|||||||
|
|
||||||
/* ADD NODE FUNCTIONS */
|
/* ADD NODE FUNCTIONS */
|
||||||
|
|
||||||
$scope.startAddNodeWithoutChild = function (parent) {
|
$scope.startAddNodeWithoutChild = (parent) => {
|
||||||
if ($scope.nodeConfig) {
|
if ($scope.nodeConfig) {
|
||||||
$scope.cancelNodeForm();
|
$scope.cancelNodeForm();
|
||||||
}
|
}
|
||||||
@@ -388,7 +423,7 @@ export default ['$scope', 'TemplatesService',
|
|||||||
$scope.formState.showNodeForm = true;
|
$scope.formState.showNodeForm = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.startAddNodeWithChild = function (link) {
|
$scope.startAddNodeWithChild = (link) => {
|
||||||
if ($scope.nodeConfig) {
|
if ($scope.nodeConfig) {
|
||||||
$scope.cancelNodeForm();
|
$scope.cancelNodeForm();
|
||||||
}
|
}
|
||||||
@@ -431,7 +466,7 @@ export default ['$scope', 'TemplatesService',
|
|||||||
$scope.formState.showNodeForm = true;
|
$scope.formState.showNodeForm = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.confirmNodeForm = function(selectedTemplate, promptData, edgeType) {
|
$scope.confirmNodeForm = (selectedTemplate, promptData, edgeType) => {
|
||||||
const nodeId = $scope.nodeConfig.nodeId;
|
const nodeId = $scope.nodeConfig.nodeId;
|
||||||
if ($scope.nodeConfig.mode === "add") {
|
if ($scope.nodeConfig.mode === "add") {
|
||||||
if (selectedTemplate && edgeType && edgeType.value) {
|
if (selectedTemplate && edgeType && edgeType.value) {
|
||||||
@@ -470,7 +505,7 @@ export default ['$scope', 'TemplatesService',
|
|||||||
$scope.$broadcast("refreshWorkflowChart");
|
$scope.$broadcast("refreshWorkflowChart");
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.cancelNodeForm = function() {
|
$scope.cancelNodeForm = () => {
|
||||||
const nodeId = $scope.nodeConfig.nodeId;
|
const nodeId = $scope.nodeConfig.nodeId;
|
||||||
if ($scope.nodeConfig.mode === "add") {
|
if ($scope.nodeConfig.mode === "add") {
|
||||||
// Remove the placeholder node from the array
|
// Remove the placeholder node from the array
|
||||||
@@ -523,7 +558,7 @@ export default ['$scope', 'TemplatesService',
|
|||||||
|
|
||||||
/* EDIT NODE FUNCTIONS */
|
/* EDIT NODE FUNCTIONS */
|
||||||
|
|
||||||
$scope.startEditNode = function(nodeToEdit) {
|
$scope.startEditNode = (nodeToEdit) => {
|
||||||
if ($scope.linkConfig) {
|
if ($scope.linkConfig) {
|
||||||
$scope.cancelLinkForm();
|
$scope.cancelLinkForm();
|
||||||
}
|
}
|
||||||
@@ -762,17 +797,17 @@ export default ['$scope', 'TemplatesService',
|
|||||||
|
|
||||||
/* DELETE NODE FUNCTIONS */
|
/* DELETE NODE FUNCTIONS */
|
||||||
|
|
||||||
$scope.startDeleteNode = function (nodeToDelete) {
|
$scope.startDeleteNode = (nodeToDelete) => {
|
||||||
$scope.nodeToBeDeleted = nodeToDelete;
|
$scope.nodeToBeDeleted = nodeToDelete;
|
||||||
$scope.deleteOverlayVisible = true;
|
$scope.deleteOverlayVisible = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.cancelDeleteNode = function () {
|
$scope.cancelDeleteNode = () => {
|
||||||
$scope.nodeToBeDeleted = null;
|
$scope.nodeToBeDeleted = null;
|
||||||
$scope.deleteOverlayVisible = false;
|
$scope.deleteOverlayVisible = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.confirmDeleteNode = function () {
|
$scope.confirmDeleteNode = () => {
|
||||||
if ($scope.nodeToBeDeleted) {
|
if ($scope.nodeToBeDeleted) {
|
||||||
const nodeId = $scope.nodeToBeDeleted.id;
|
const nodeId = $scope.nodeToBeDeleted.id;
|
||||||
|
|
||||||
@@ -856,73 +891,34 @@ export default ['$scope', 'TemplatesService',
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.toggleManualControls = function() {
|
$scope.toggleManualControls = () => {
|
||||||
$scope.showManualControls = !$scope.showManualControls;
|
$scope.showManualControls = !$scope.showManualControls;
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.panChart = function (direction) {
|
$scope.panChart = (direction) => {
|
||||||
$scope.$broadcast('panWorkflowChart', {
|
$scope.$broadcast('panWorkflowChart', {
|
||||||
direction: direction
|
direction: direction
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.zoomChart = function (zoom) {
|
$scope.zoomChart = (zoom) => {
|
||||||
$scope.$broadcast('zoomWorkflowChart', {
|
$scope.$broadcast('zoomWorkflowChart', {
|
||||||
zoom: zoom
|
zoom: zoom
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.resetChart = function () {
|
$scope.resetChart = () => {
|
||||||
$scope.$broadcast('resetWorkflowChart');
|
$scope.$broadcast('resetWorkflowChart');
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.workflowZoomed = function (zoom) {
|
$scope.workflowZoomed = (zoom) => {
|
||||||
$scope.$broadcast('workflowZoomed', {
|
$scope.$broadcast('workflowZoomed', {
|
||||||
zoom: zoom
|
zoom: zoom
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.zoomToFitChart = function () {
|
$scope.zoomToFitChart = () => {
|
||||||
$scope.$broadcast('zoomToFitChart');
|
$scope.$broadcast('zoomToFitChart');
|
||||||
};
|
};
|
||||||
|
|
||||||
let allNodes = [];
|
|
||||||
let page = 1;
|
|
||||||
|
|
||||||
let getNodes = function () {
|
|
||||||
Wait('start');
|
|
||||||
TemplatesService.getWorkflowJobTemplateNodes($scope.workflowJobTemplateObj.id, page)
|
|
||||||
.then(function (data) {
|
|
||||||
for (var i = 0; i < data.data.results.length; i++) {
|
|
||||||
allNodes.push(data.data.results[i]);
|
|
||||||
}
|
|
||||||
if (data.data.next) {
|
|
||||||
// Get the next page
|
|
||||||
page++;
|
|
||||||
getNodes();
|
|
||||||
} else {
|
|
||||||
let arrayOfLinksForChart = [];
|
|
||||||
let arrayOfNodesForChart = [];
|
|
||||||
|
|
||||||
({arrayOfNodesForChart, arrayOfLinksForChart, nodeIdToChartNodeIdMapping, nodeRef, workflowMakerNodeIdCounter} = WorkflowChartService.generateArraysOfNodesAndLinks(allNodes));
|
|
||||||
|
|
||||||
$scope.graphState = { arrayOfNodesForChart, arrayOfLinksForChart };
|
|
||||||
|
|
||||||
Wait('stop');
|
|
||||||
}
|
|
||||||
}, function ({ data, status, config }) {
|
|
||||||
Wait('stop');
|
|
||||||
ProcessErrors($scope, data, status, null, {
|
|
||||||
hdr: $scope.strings.get('error.HEADER'),
|
|
||||||
msg: $scope.strings.get('error.CALL', {
|
|
||||||
path: `${config.url}`,
|
|
||||||
action: `${config.method}`,
|
|
||||||
status
|
|
||||||
})
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
getNodes();
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -74,7 +74,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="WorkflowLegend-maker--right">
|
<div class="WorkflowLegend-maker--right">
|
||||||
<span class="WorkflowMaker-totalJobs">{{strings.get('workflow_maker.TOTAL_TEMPLATES')}}</span>
|
<span class="WorkflowMaker-totalJobs">{{strings.get('workflow_maker.TOTAL_TEMPLATES')}}</span>
|
||||||
<span class="badge List-titleBadge" ng-bind="graphState.arrayOfNodesForChart.length-1"></span>
|
<span class="badge List-titleBadge" ng-bind="graphState.arrayOfNodesForChart.length === 0 ? graphState.arrayOfNodesForChart.length : graphState.arrayOfNodesForChart.length-1"></span>
|
||||||
<i ng-class="{'WorkflowMaker-manualControlsIcon--active': showManualControls}" class="fa fa-cog WorkflowMaker-manualControlsIcon" aria-hidden="true" alt="Controls" ng-click="toggleManualControls()"></i>
|
<i ng-class="{'WorkflowMaker-manualControlsIcon--active': showManualControls}" class="fa fa-cog WorkflowMaker-manualControlsIcon" aria-hidden="true" alt="Controls" ng-click="toggleManualControls()"></i>
|
||||||
<div ng-show="showManualControls" class="WorkflowMaker-manualControls noselect">
|
<div ng-show="showManualControls" class="WorkflowMaker-manualControls noselect">
|
||||||
<workflow-controls class="WorkflowControls" pan-chart="panChart(direction)" zoom-chart="zoomChart(zoom)" reset-chart="resetChart()" zoom-to-fit-chart="zoomToFitChart()"></workflow-controls>
|
<workflow-controls class="WorkflowControls" pan-chart="panChart(direction)" zoom-chart="zoomChart(zoom)" reset-chart="resetChart()" zoom-to-fit-chart="zoomToFitChart()"></workflow-controls>
|
||||||
|
|||||||
@@ -5,9 +5,8 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
|||||||
workflowDataOptions, jobLabels, workflowNodes, $scope, ParseTypeChange,
|
workflowDataOptions, jobLabels, workflowNodes, $scope, ParseTypeChange,
|
||||||
ParseVariableString, count, $state, i18n, WorkflowChartService, $filter,
|
ParseVariableString, count, $state, i18n, WorkflowChartService, $filter,
|
||||||
moment) {
|
moment) {
|
||||||
|
let nodeRef;
|
||||||
var runTimeElapsedTimer = null;
|
var runTimeElapsedTimer = null;
|
||||||
let nodeIdToChartNodeIdMapping = {};
|
|
||||||
let chartNodeIdToIndexMapping = {};
|
|
||||||
|
|
||||||
var getLinks = function() {
|
var getLinks = function() {
|
||||||
var getLink = function(key) {
|
var getLink = function(key) {
|
||||||
@@ -104,7 +103,6 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
|||||||
function init() {
|
function init() {
|
||||||
// put initially resolved request data on scope
|
// put initially resolved request data on scope
|
||||||
$scope.workflow = workflowData;
|
$scope.workflow = workflowData;
|
||||||
$scope.workflow_nodes = workflowNodes;
|
|
||||||
$scope.workflowOptions = workflowDataOptions.actions.GET;
|
$scope.workflowOptions = workflowDataOptions.actions.GET;
|
||||||
$scope.labels = jobLabels;
|
$scope.labels = jobLabels;
|
||||||
$scope.showManualControls = false;
|
$scope.showManualControls = false;
|
||||||
@@ -164,7 +162,7 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
|||||||
let arrayOfLinksForChart = [];
|
let arrayOfLinksForChart = [];
|
||||||
let arrayOfNodesForChart = [];
|
let arrayOfNodesForChart = [];
|
||||||
|
|
||||||
({arrayOfNodesForChart, arrayOfLinksForChart, chartNodeIdToIndexMapping, nodeIdToChartNodeIdMapping} = WorkflowChartService.generateArraysOfNodesAndLinks(workflowNodes));
|
({arrayOfNodesForChart, arrayOfLinksForChart, nodeRef} = WorkflowChartService.generateArraysOfNodesAndLinks(workflowNodes));
|
||||||
|
|
||||||
$scope.graphState = { arrayOfNodesForChart, arrayOfLinksForChart };
|
$scope.graphState = { arrayOfNodesForChart, arrayOfLinksForChart };
|
||||||
}
|
}
|
||||||
@@ -266,15 +264,12 @@ export default ['workflowData', 'workflowResultsService', 'workflowDataOptions',
|
|||||||
runTimeElapsedTimer = workflowResultsService.createOneSecondTimer(moment(), updateWorkflowJobElapsedTimer);
|
runTimeElapsedTimer = workflowResultsService.createOneSecondTimer(moment(), updateWorkflowJobElapsedTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.graphState.arrayOfNodesForChart[chartNodeIdToIndexMapping[nodeIdToChartNodeIdMapping[data.workflow_node_id]]].job = {
|
$scope.graphState.arrayOfNodesForChart.forEach((node) => {
|
||||||
id: data.unified_job_id,
|
if (nodeRef[node.id] && nodeRef[node.id].originalNodeObject.id === data.workflow_node_id) {
|
||||||
status: data.status
|
node.job = {
|
||||||
};
|
id: data.unified_job_id,
|
||||||
|
status: data.status,
|
||||||
$scope.workflow_nodes.forEach(node => {
|
type: nodeRef[node.id].unifiedJobTemplate.unified_job_type
|
||||||
if(parseInt(node.id) === parseInt(data.workflow_node_id)){
|
|
||||||
node.summary_fields.job = {
|
|
||||||
status: data.status
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user