diff --git a/awx/ui/client/src/templates/main.js b/awx/ui/client/src/templates/main.js
index 144d597e2e..456c37fc78 100644
--- a/awx/ui/client/src/templates/main.js
+++ b/awx/ui/client/src/templates/main.js
@@ -37,7 +37,7 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p
.config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider',
function($stateProvider, stateDefinitionsProvider, $stateExtenderProvider) {
let stateTree, addJobTemplate, editJobTemplate, addWorkflow, editWorkflow,
- workflowMaker, inventoryLookup, credentialLookup,
+ workflowMaker,
stateDefinitions = stateDefinitionsProvider.$get(),
stateExtender = $stateExtenderProvider.$get();
@@ -401,8 +401,7 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p
job_template_search: {
value: {
page_size: '5',
- order_by: 'name',
- inventory__isnull: false
+ order_by: 'name'
},
squash: false,
dynamic: true
@@ -474,30 +473,29 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p
name: row.name
};
- $scope.templateSelected(row);
+ $scope.templateManuallySelected(row);
}
});
};
- $scope.$on('templateSelected', function(e, options) {
- if(options.activeTab !== 'jobs') {
+ $scope.$watch('selectedTemplate', () => {
+ $scope.job_templates.forEach(function(row, i) {
+ if(_.has($scope, 'selectedTemplate.id') && row.id === $scope.selectedTemplate.id) {
+ $scope.job_templates[i].checked = 1;
+ }
+ else {
+ $scope.job_templates[i].checked = 0;
+ }
+ });
+ });
+
+ $scope.$watch('activeTab', () => {
+ if(!$scope.activeTab || $scope.activeTab !== "jobs") {
$scope.job_templates.forEach(function(row, i) {
$scope.job_templates[i].checked = 0;
});
}
- else {
- if($scope.selectedTemplate){
- $scope.job_templates.forEach(function(row, i) {
- if(row.id === $scope.selectedTemplate.id) {
- $scope.job_templates[i].checked = 1;
- }
- else {
- $scope.job_templates[i].checked = 0;
- }
- });
- }
- }
});
$scope.$on('clearWorkflowLists', function() {
@@ -552,30 +550,29 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p
name: row.name
};
- $scope.templateSelected(row);
+ $scope.templateManuallySelected(row);
}
});
};
- $scope.$on('templateSelected', function(e, options) {
- if(options.activeTab !== 'inventory_sync') {
+ $scope.$watch('selectedTemplate', () => {
+ $scope.workflow_inventory_sources.forEach(function(row, i) {
+ if(_.has($scope, 'selectedTemplate.id') && row.id === $scope.selectedTemplate.id) {
+ $scope.workflow_inventory_sources[i].checked = 1;
+ }
+ else {
+ $scope.workflow_inventory_sources[i].checked = 0;
+ }
+ });
+ });
+
+ $scope.$watch('activeTab', () => {
+ if(!$scope.activeTab || $scope.activeTab !== "inventory_sync") {
$scope.workflow_inventory_sources.forEach(function(row, i) {
$scope.workflow_inventory_sources[i].checked = 0;
});
}
- else {
- if($scope.selectedTemplate){
- $scope.workflow_inventory_sources.forEach(function(row, i) {
- if(row.id === $scope.selectedTemplate.id) {
- $scope.workflow_inventory_sources[i].checked = 1;
- }
- else {
- $scope.workflow_inventory_sources[i].checked = 0;
- }
- });
- }
- }
});
$scope.$on('clearWorkflowLists', function() {
@@ -630,30 +627,29 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p
name: row.name
};
- $scope.templateSelected(row);
+ $scope.templateManuallySelected(row);
}
});
};
- $scope.$on('templateSelected', function(e, options) {
- if(options.activeTab !== 'project_sync') {
+ $scope.$watch('selectedTemplate', () => {
+ $scope.projects.forEach(function(row, i) {
+ if(_.has($scope, 'selectedTemplate.id') && row.id === $scope.selectedTemplate.id) {
+ $scope.projects[i].checked = 1;
+ }
+ else {
+ $scope.projects[i].checked = 0;
+ }
+ });
+ });
+
+ $scope.$watch('activeTab', () => {
+ if(!$scope.activeTab || $scope.activeTab !== "project_sync") {
$scope.projects.forEach(function(row, i) {
$scope.projects[i].checked = 0;
});
}
- else {
- if($scope.selectedTemplate){
- $scope.projects.forEach(function(row, i) {
- if(row.id === $scope.selectedTemplate.id) {
- $scope.projects[i].checked = 1;
- }
- else {
- $scope.projects[i].checked = 0;
- }
- });
- }
- }
});
$scope.$on('clearWorkflowLists', function() {
@@ -663,69 +659,6 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p
});
}
]
- },
- 'workflowForm@templates.editWorkflowJobTemplate.workflowMaker': {
- templateProvider: function(WorkflowMakerForm, GenerateForm) {
- let form = WorkflowMakerForm();
- let html = GenerateForm.buildHTML(form, {
- mode: 'add',
- related: false,
- noPanel: true
- });
- return html;
- },
- controller: ['$scope', '$timeout', 'CreateSelect2',
- function($scope, $timeout, CreateSelect2) {
- function resetPromptFields() {
- $scope.credential = null;
- $scope.credential_name = null;
- $scope.inventory = null;
- $scope.inventory_name = null;
- $scope.job_type = null;
- $scope.limit = null;
- $scope.job_tags = null;
- $scope.skip_tags = null;
- }
-
- $scope.saveNodeForm = function(){
- // Gather up all of our form data - then let the main scope know what
- // the new data is
-
- $scope.confirmNodeForm({
- skip_tags: $scope.skip_tags,
- job_tags: $scope.job_tags,
- limit: $scope.limit,
- credential: $scope.credential,
- credential_name: $scope.credential_name,
- inventory: $scope.inventory,
- inventory_name: $scope.inventory_name,
- edgeType: $scope.edgeType,
- job_type: $scope.job_type
- });
- };
-
- $scope.$on('templateSelected', function(e, options) {
-
- resetPromptFields();
- // Loop across the preset values and attach them to scope
- _.forOwn(options.presetValues, function(value, key) {
- $scope[key] = value;
- });
-
- // The default needs to be in place before we can select2-ify the dropdown
- $timeout(function() {
- CreateSelect2({
- element: '#workflow_maker_job_type',
- multiple: false
- });
- });
- });
-
- $scope.$on('setEdgeType', function(e, edgeType) {
- $scope.edgeType = edgeType;
- });
- }
- ]
}
},
resolve: {
@@ -798,114 +731,114 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p
}
};
- inventoryLookup = {
- searchPrefix: 'inventory',
- name: 'templates.editWorkflowJobTemplate.workflowMaker.inventory',
- url: '/inventory',
- data: {
- formChildState: true
- },
- params: {
- inventory_search: {
- value: {
- page_size: '5'
- },
- squash: true,
- dynamic: true
- }
- },
- ncyBreadcrumb: {
- skip: true
- },
- views: {
- 'related': {
- templateProvider: function(ListDefinition, generateList) {
- let list_html = generateList.build({
- mode: 'lookup',
- list: ListDefinition,
- input_type: 'radio'
- });
- return `${list_html}`;
-
- }
- }
- },
- resolve: {
- ListDefinition: ['InventoryList', function(InventoryList) {
- // mutate the provided list definition here
- let list = _.cloneDeep(InventoryList);
- list.lookupConfirmText = 'SELECT';
- return list;
- }],
- Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath',
- (list, qs, $stateParams, GetBasePath) => {
- let path = GetBasePath(list.name) || GetBasePath(list.basePath);
- return qs.search(path, $stateParams[`${list.iterator}_search`]);
- }
- ]
- },
- onExit: function($state) {
- if ($state.transition) {
- $('#form-modal').modal('hide');
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- }
- },
- };
-
- credentialLookup = {
- searchPrefix: 'credential',
- name: 'templates.editWorkflowJobTemplate.workflowMaker.credential',
- url: '/credential',
- data: {
- formChildState: true
- },
- params: {
- credential_search: {
- value: {
- page_size: '5'
- },
- squash: true,
- dynamic: true
- }
- },
- ncyBreadcrumb: {
- skip: true
- },
- views: {
- 'related': {
- templateProvider: function(ListDefinition, generateList) {
- let list_html = generateList.build({
- mode: 'lookup',
- list: ListDefinition,
- input_type: 'radio'
- });
- return `${list_html}`;
-
- }
- }
- },
- resolve: {
- ListDefinition: ['CredentialList', function(CredentialList) {
- let list = _.cloneDeep(CredentialList);
- list.lookupConfirmText = 'SELECT';
- return list;
- }],
- Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath',
- (list, qs, $stateParams, GetBasePath) => {
- let path = GetBasePath(list.name) || GetBasePath(list.basePath);
- return qs.search(path, $stateParams[`${list.iterator}_search`]);
- }
- ]
- },
- onExit: function($state) {
- if ($state.transition) {
- $('#form-modal').modal('hide');
- $('.modal-backdrop').remove();
- $('body').removeClass('modal-open');
- }
- },
- };
+ // inventoryLookup = {
+ // searchPrefix: 'inventory',
+ // name: 'templates.editWorkflowJobTemplate.workflowMaker.inventory',
+ // url: '/inventory',
+ // data: {
+ // formChildState: true
+ // },
+ // params: {
+ // inventory_search: {
+ // value: {
+ // page_size: '5'
+ // },
+ // squash: true,
+ // dynamic: true
+ // }
+ // },
+ // ncyBreadcrumb: {
+ // skip: true
+ // },
+ // views: {
+ // 'related': {
+ // templateProvider: function(ListDefinition, generateList) {
+ // let list_html = generateList.build({
+ // mode: 'lookup',
+ // list: ListDefinition,
+ // input_type: 'radio'
+ // });
+ // return `${list_html}`;
+ //
+ // }
+ // }
+ // },
+ // resolve: {
+ // ListDefinition: ['InventoryList', function(InventoryList) {
+ // // mutate the provided list definition here
+ // let list = _.cloneDeep(InventoryList);
+ // list.lookupConfirmText = 'SELECT';
+ // return list;
+ // }],
+ // Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath',
+ // (list, qs, $stateParams, GetBasePath) => {
+ // let path = GetBasePath(list.name) || GetBasePath(list.basePath);
+ // return qs.search(path, $stateParams[`${list.iterator}_search`]);
+ // }
+ // ]
+ // },
+ // onExit: function($state) {
+ // if ($state.transition) {
+ // $('#form-modal').modal('hide');
+ // $('.modal-backdrop').remove();
+ // $('body').removeClass('modal-open');
+ // }
+ // },
+ // };
+ //
+ // credentialLookup = {
+ // searchPrefix: 'credential',
+ // name: 'templates.editWorkflowJobTemplate.workflowMaker.credential',
+ // url: '/credential',
+ // data: {
+ // formChildState: true
+ // },
+ // params: {
+ // credential_search: {
+ // value: {
+ // page_size: '5'
+ // },
+ // squash: true,
+ // dynamic: true
+ // }
+ // },
+ // ncyBreadcrumb: {
+ // skip: true
+ // },
+ // views: {
+ // 'related': {
+ // templateProvider: function(ListDefinition, generateList) {
+ // let list_html = generateList.build({
+ // mode: 'lookup',
+ // list: ListDefinition,
+ // input_type: 'radio'
+ // });
+ // return `${list_html}`;
+ //
+ // }
+ // }
+ // },
+ // resolve: {
+ // ListDefinition: ['CredentialList', function(CredentialList) {
+ // let list = _.cloneDeep(CredentialList);
+ // list.lookupConfirmText = 'SELECT';
+ // return list;
+ // }],
+ // Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath',
+ // (list, qs, $stateParams, GetBasePath) => {
+ // let path = GetBasePath(list.name) || GetBasePath(list.basePath);
+ // return qs.search(path, $stateParams[`${list.iterator}_search`]);
+ // }
+ // ]
+ // },
+ // onExit: function($state) {
+ // if ($state.transition) {
+ // $('#form-modal').modal('hide');
+ // $('.modal-backdrop').remove();
+ // $('body').removeClass('modal-open');
+ // }
+ // },
+ // };
return Promise.all([
@@ -920,8 +853,8 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p
}, [
stateExtender.buildDefinition(listRoute),
stateExtender.buildDefinition(workflowMaker),
- stateExtender.buildDefinition(inventoryLookup),
- stateExtender.buildDefinition(credentialLookup)
+ // stateExtender.buildDefinition(inventoryLookup),
+ // stateExtender.buildDefinition(credentialLookup)
])
};
});
diff --git a/awx/ui/client/src/templates/prompt/prompt.partial.html b/awx/ui/client/src/templates/prompt/prompt.partial.html
index 8a99a5f7b0..87e3f83a08 100644
--- a/awx/ui/client/src/templates/prompt/prompt.partial.html
+++ b/awx/ui/client/src/templates/prompt/prompt.partial.html
@@ -1,5 +1,5 @@
-
+
{{:: vm.strings.get('prompt.INVENTORY') }}
{{:: vm.strings.get('prompt.CREDENTIAL') }}
diff --git a/awx/ui/client/src/templates/prompt/prompt.service.js b/awx/ui/client/src/templates/prompt/prompt.service.js
index 9090bfda05..5ab5002c27 100644
--- a/awx/ui/client/src/templates/prompt/prompt.service.js
+++ b/awx/ui/client/src/templates/prompt/prompt.service.js
@@ -19,7 +19,7 @@ function PromptService (Empty, $filter) {
let skipTags = _.has(params, 'currentValues.skip_tags') && params.currentValues.skip_tags ? params.currentValues.skip_tags : (_.has(params, 'launchConf.defaults.skip_tags') ? params.launchConf.defaults.skip_tags : "");
let jobTags = _.has(params, 'currentValues.job_tags') && params.currentValues.job_tags ? params.currentValues.job_tags : (_.has(params, 'launchConf.defaults.job_tags') ? params.launchConf.defaults.job_tags : "");
- prompts.variables.value = _.has(params, 'launchConf.defaults.extra_vars') ? params.launchConf.defaults.extra_vars : "---";
+ prompts.variables.value = _.has(params, 'launchConf.defaults.extra_vars') && params.launchConf.defaults.extra_vars !== "" ? params.launchConf.defaults.extra_vars : "---";
prompts.verbosity.choices = _.get(params, 'launchOptions.actions.POST.verbosity.choices', []).map(c => ({label: c[1], value: c[0]}));
prompts.verbosity.value = _.has(params, 'currentValues.verbosity') && params.currentValues.verbosity ? _.find(prompts.verbosity.choices, item => item.value === params.currentValues.verbosity) : _.find(prompts.verbosity.choices, item => item.value === params.launchConf.defaults.verbosity);
prompts.jobType.choices = _.get(params, 'launchOptions.actions.POST.job_type.choices', []).map(c => ({label: c[1], value: c[0]}));
diff --git a/awx/ui/client/src/templates/prompt/steps/inventory/prompt-inventory.directive.js b/awx/ui/client/src/templates/prompt/steps/inventory/prompt-inventory.directive.js
index 826981c189..e3b1d24823 100644
--- a/awx/ui/client/src/templates/prompt/steps/inventory/prompt-inventory.directive.js
+++ b/awx/ui/client/src/templates/prompt/steps/inventory/prompt-inventory.directive.js
@@ -54,17 +54,17 @@ export default [ 'templateUrl', 'QuerySet', 'GetBasePath', 'generateList', '$com
$('#prompt-inventory').append($compile(html)(scope));
scope.$watch('promptData.prompts.inventory.value', () => {
- if(scope.promptData.prompts.inventory.value && scope.promptData.prompts.inventory.value.id) {
- // Loop across the inventories and see if one of them should be "checked"
- scope.inventories.forEach((row, i) => {
- if (row.id === scope.promptData.prompts.inventory.value.id) {
- scope.inventories[i].checked = 1;
- }
- else {
- scope.inventories[i].checked = 0;
- }
- });
- }
+ scope.inventories.forEach((row, i) => {
+ if (
+ _.has(scope, 'promptData.prompts.inventory.value.id') &&
+ row.id === scope.promptData.prompts.inventory.value.id
+ ) {
+ scope.inventories[i].checked = 1;
+ }
+ else {
+ scope.inventories[i].checked = 0;
+ }
+ });
});
});
}
diff --git a/awx/ui/client/src/templates/prompt/steps/other-prompts/prompt-other-prompts.controller.js b/awx/ui/client/src/templates/prompt/steps/other-prompts/prompt-other-prompts.controller.js
index 127c412d88..96a087218d 100644
--- a/awx/ui/client/src/templates/prompt/steps/other-prompts/prompt-other-prompts.controller.js
+++ b/awx/ui/client/src/templates/prompt/steps/other-prompts/prompt-other-prompts.controller.js
@@ -5,7 +5,7 @@
*************************************************/
export default
- ['ParseTypeChange', 'CreateSelect2', 'TemplatesStrings', function(ParseTypeChange, CreateSelect2, strings) {
+ ['ParseTypeChange', 'CreateSelect2', 'TemplatesStrings', '$timeout', function(ParseTypeChange, CreateSelect2, strings, $timeout) {
const vm = this;
vm.strings = strings;
@@ -30,10 +30,12 @@ export default
let codemirrorExtraVars = () => {
if(scope.promptData.launchConf.ask_variables_on_launch && !scope.promptData.prompts.variables.ignore) {
- ParseTypeChange({
- scope: scope,
- variable: 'extraVariables',
- field_id: 'job_launch_variables'
+ $timeout(() => {
+ ParseTypeChange({
+ scope: scope,
+ variable: 'extraVariables',
+ field_id: 'job_launch_variables'
+ });
});
}
};
diff --git a/awx/ui/client/src/templates/templates.service.js b/awx/ui/client/src/templates/templates.service.js
index cc322a0fb1..1a63cb6553 100644
--- a/awx/ui/client/src/templates/templates.service.js
+++ b/awx/ui/client/src/templates/templates.service.js
@@ -281,6 +281,15 @@ export default ['Rest', 'GetBasePath', '$q', 'NextPage', function(Rest, GetBaseP
});
return deferred.promise;
+ },
+ postWorkflowNodeCredential: function(params) {
+ // params.id
+ // params.data
+
+ var url = GetBasePath('workflow_job_template_nodes') + params.id + '/credentials';
+
+ Rest.setUrl(url);
+ return Rest.post(params.data);
}
};
}];
diff --git a/awx/ui/client/src/templates/workflows/workflow-maker/workflow-maker.controller.js b/awx/ui/client/src/templates/workflows/workflow-maker/workflow-maker.controller.js
index 9bbe6e8996..eac600ec93 100644
--- a/awx/ui/client/src/templates/workflows/workflow-maker/workflow-maker.controller.js
+++ b/awx/ui/client/src/templates/workflows/workflow-maker/workflow-maker.controller.js
@@ -5,11 +5,14 @@
*************************************************/
export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
- '$state', 'ProcessErrors', 'CreateSelect2', 'WorkflowMakerForm', '$q',
+ '$state', 'ProcessErrors', 'CreateSelect2', 'WorkflowMakerForm', '$q', 'JobTemplateModel',
+ 'Empty', 'PromptService', 'Rest',
function($scope, WorkflowService, GetBasePath, TemplatesService, $state,
- ProcessErrors, CreateSelect2, WorkflowMakerForm, $q) {
+ ProcessErrors, CreateSelect2, WorkflowMakerForm, $q, JobTemplate,
+ Empty, PromptService, Rest) {
let form = WorkflowMakerForm();
+ let promptWatcher;
$scope.workflowMakerFormConfig = {
nodeMode: "idle",
@@ -26,80 +29,39 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
}];
$scope.edgeFlags = {
- conflict: false,
- typeRestriction: null,
- showTypeOptions: false
+ conflict: false
};
- $scope.editRequests = [];
- $scope.associateRequests = [];
- $scope.disassociateRequests = [];
+ $scope.edgeTypeOptions = [
+ {
+ label: 'Always',
+ value: 'always'
+ },
+ {
+ label: 'On Success',
+ value: 'success'
+ },
+ {
+ label: 'On Failure',
+ value: 'failure'
+ }
+ ];
+
+ let editRequests = [];
+ let associateRequests = [];
+ let disassociateRequests = [];
+ let credentialRequests = [];
$scope.showKey = false;
$scope.toggleKey = () => $scope.showKey = !$scope.showKey;
$scope.keyClassList = `{ 'Key-menuIcon--active': showKey }`;
- function init() {
-
- let allNodes = [];
- let page = 1;
-
- let buildTreeFromNodes = function(){
- WorkflowService.buildTree({
- workflowNodes: allNodes
- }).then(function(data){
- $scope.treeData = data;
-
- // TODO: I think that the workflow chart directive (and eventually d3) is meddling with
- // this treeData object and removing the children object for some reason (?)
- // This happens on occasion and I think is a race condition (?)
- if(!$scope.treeData.data.children) {
- $scope.treeData.data.children = [];
- }
-
- $scope.treeData.workflow_job_template_obj = $scope.workflowJobTemplateObj;
-
- $scope.treeDataMaster = angular.copy($scope.treeData.data);
- $scope.showManualControls = false;
- });
- };
-
- let getNodes = function(){
- // Get the workflow nodes
- TemplatesService.getWorkflowJobTemplateNodes($scope.workflowJobTemplateObj.id, page)
- .then(function(data){
- for(var i=0; i a.value).sort())) ? null : params.node.promptData.prompts.tags.value.map(a => a.value).join();
}
- if(params.node.unifiedJobTemplate.ask_job_type_on_launch) {
- sendableNodeData.job_type = !params.node.promptValues.job_type || params.node.unifiedJobTemplate.job_type !== params.node.promptValues.job_type ? params.node.promptValues.job_type : null;
+ if(_.has(params, 'node.promptData.prompts.skipTags.value') && _.get(params, 'node.promptData.launchConf.ask_skip_tags_on_launch')){
+ let templateDefaultSkipTags = params.node.promptData.prompts.skipTags.templateDefault.split(',');
+ sendableNodeData.skip_tags = (_.isEqual(templateDefaultSkipTags.sort(), params.node.promptData.prompts.skipTags.value.map(a => a.value).sort())) ? null : params.node.promptData.prompts.skipTags.value.map(a => a.value).join();
}
- if(params.node.unifiedJobTemplate.ask_tags_on_launch) {
- sendableNodeData.job_tags = !params.node.promptValues.job_tags || params.node.unifiedJobTemplate.job_tags !== params.node.promptValues.job_tags ? params.node.promptValues.job_tags : null;
+ if(_.has(params, 'node.promptData.prompts.limit.value') && _.get(params, 'node.promptData.launchConf.ask_limit_on_launch')){
+ sendableNodeData.limit = params.node.promptData.prompts.limit.templateDefault === params.node.promptData.prompts.limit.value ? null : params.node.promptData.prompts.limit.value;
}
- if(params.node.unifiedJobTemplate.ask_skip_tags_on_launch) {
- sendableNodeData.skip_tags = !params.node.promptValues.skip_tags || params.node.unifiedJobTemplate.skip_tags !== params.node.promptValues.skip_tags ? params.node.promptValues.skip_tags : null;
+ if(_.has(params, 'node.promptData.prompts.verbosity.value.value') && _.get(params, 'node.promptData.launchConf.ask_verbosity_on_launch')){
+ sendableNodeData.verbosity = params.node.promptData.prompts.verbosity.templateDefault === params.node.promptData.prompts.verbosity.value.value ? null : params.node.promptData.prompts.verbosity.value.value;
+ }
+ if(_.has(params, 'node.promptData.prompts.inventory.value') && _.get(params, 'node.promptData.launchConf.ask_inventory_on_launch')){
+ sendableNodeData.inventory = _.has(params, 'node.promptData.prompts.inventory.templateDefault.id') && params.node.promptData.prompts.inventory.templateDefault.id === params.node.promptData.prompts.inventory.value.id ? null : params.node.promptData.prompts.inventory.value.id;
+ }
+ if(_.has(params, 'node.promptData.prompts.diffMode.value') && _.get(params, 'node.promptData.launchConf.ask_diff_mode_on_launch')){
+ sendableNodeData.diff_mode = params.node.promptData.prompts.diffMode.templateDefault === params.node.promptData.prompts.diffMode.value ? null : params.node.promptData.prompts.diffMode.value;
}
}
@@ -184,13 +179,33 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
.then(function(data) {
if(!params.node.isRoot) {
- $scope.associateRequests.push({
+ associateRequests.push({
parentId: params.parentId,
nodeId: data.data.id,
edge: params.node.edgeType
});
}
+ if(_.get(params, 'node.promptData.launchConf.ask_credential_on_launch')){
+ // This finds the credentials that were selected in the prompt but don't occur
+ // in the template defaults
+ let credentialsToPost = params.node.promptData.prompts.credentials.value.filter(function(credFromPrompt) {
+ let defaultCreds = params.node.promptData.launchConf.defaults.credentials ? params.node.promptData.launchConf.defaults.credentials : [];
+ return !defaultCreds.some(function(defaultCred) {
+ return credFromPrompt.id === defaultCred.id;
+ });
+ });
+
+ credentialsToPost.forEach((credentialToPost) => {
+ credentialRequests.push({
+ id: data.data.id,
+ data: {
+ id: credentialToPost.id
+ }
+ });
+ });
+ }
+
params.node.isNew = false;
continueRecursing(data.data.id);
}, function(error) {
@@ -207,11 +222,51 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
if(params.node.edited) {
- $scope.editRequests.push({
+ editRequests.push({
id: params.node.nodeId,
data: buildSendableNodeData()
});
+ if(_.get(params, 'node.promptData.launchConf.ask_credential_on_launch')){
+ let credentialsNotInPriorCredentials = params.node.promptData.prompts.credentials.value.filter(function(credFromPrompt) {
+ let defaultCreds = params.node.promptData.launchConf.defaults.credentials ? params.node.promptData.launchConf.defaults.credentials : [];
+ return !defaultCreds.some(function(defaultCred) {
+ return credFromPrompt.id === defaultCred.id;
+ });
+ });
+
+ let credentialsToAdd = credentialsNotInPriorCredentials.filter(function(credNotInPrior) {
+ return !params.node.promptData.prompts.credentials.previousOverrides.some(function(priorCred) {
+ return credNotInPrior.id === priorCred.id;
+ });
+ });
+
+ let credentialsToRemove = params.node.promptData.prompts.credentials.previousOverrides.filter(function(priorCred) {
+ return !credentialsNotInPriorCredentials.some(function(credNotInPrior) {
+ return priorCred.id === credNotInPrior.id;
+ });
+ });
+
+ credentialsToAdd.forEach((credentialToAdd) => {
+ credentialRequests.push({
+ id: params.node.nodeId,
+ data: {
+ id: credentialToAdd.id
+ }
+ });
+ });
+
+ credentialsToRemove.forEach((credentialToRemove) => {
+ credentialRequests.push({
+ id: params.node.nodeId,
+ data: {
+ id: credentialToRemove.id,
+ disassociate: true
+ }
+ });
+ });
+ }
+
}
if((params.node.originalParentId && params.parentId !== params.node.originalParentId) || params.node.originalEdge !== params.node.edgeType) {//beep
@@ -225,7 +280,7 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
});
if(!parentIsDeleted) {
- $scope.disassociateRequests.push({
+ disassociateRequests.push({
parentId: params.node.originalParentId,
nodeId: params.node.nodeId,
edge: params.node.originalEdge
@@ -236,7 +291,7 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
// If we don't have a parent then this is a root node
// and the act of disassociating will make it a root node
if(params.parentId) {
- $scope.associateRequests.push({
+ associateRequests.push({
parentId: params.parentId,
nodeId: params.node.nodeId,
edge: params.node.edgeType
@@ -246,7 +301,7 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
}
else if(!params.node.originalParentId && params.parentId) {
// This used to be a root node but is now not a root node
- $scope.associateRequests.push({
+ associateRequests.push({
parentId: params.parentId,
nodeId: params.node.nodeId,
edge: params.node.edgeType
@@ -259,12 +314,68 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
}
}
- $scope.lookUpInventory = function(){
- $state.go('.inventory');
+ let updateEdgeDropdownOptions = (optionsToInclude) => {
+ // Not passing optionsToInclude will include all by default
+ if(!optionsToInclude) {
+ $scope.edgeTypeOptions = [
+ {
+ label: 'Always',
+ value: 'always'
+ },
+ {
+ label: 'On Success',
+ value: 'success'
+ },
+ {
+ label: 'On Failure',
+ value: 'failure'
+ }
+ ];
+ } else {
+ $scope.edgeTypeOptions = [];
+
+ optionsToInclude.forEach((optionToInclude) => {
+ if(optionToInclude === "always") {
+ $scope.edgeTypeOptions.push({
+ label: 'Always',
+ value: 'always'
+ });
+ } else if(optionToInclude === "success") {
+ $scope.edgeTypeOptions.push({
+ label: 'On Success',
+ value: 'success'
+ });
+ } else if(optionToInclude === "failure") {
+ $scope.edgeTypeOptions.push({
+ label: 'On Failure',
+ value: 'failure'
+ });
+ }
+ });
+ }
+
+ CreateSelect2({
+ element: '#workflow_node_edge',
+ multiple: false
+ });
};
- $scope.lookUpCredential = function(){
- $state.go('.credential');
+ let watchForPromptChanges = () => {
+ let promptDataToWatch = [
+ 'promptData.prompts.inventory.value',
+ 'promptData.prompts.verbosity.value',
+ 'missingSurveyValue'
+ ];
+
+ promptWatcher = $scope.$watchGroup(promptDataToWatch, function() {
+ let missingPromptValue = false;
+ if($scope.missingSurveyValue) {
+ missingPromptValue = true;
+ } else if(!$scope.promptData.prompts.inventory.value || !$scope.promptData.prompts.inventory.value.id) {
+ missingPromptValue = true;
+ }
+ $scope.promptModalMissingReqFields = missingPromptValue;
+ });
};
$scope.closeWorkflowMaker = function() {
@@ -280,7 +391,7 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
if($scope.treeData && $scope.treeData.data && $scope.treeData.data.children && $scope.treeData.data.children.length > 0) {
let completionCallback = function() {
- let disassociatePromises = $scope.disassociateRequests.map(function(request) {
+ let disassociatePromises = disassociateRequests.map(function(request) {
return TemplatesService.disassociateWorkflowNode({
parentId: request.parentId,
nodeId: request.nodeId,
@@ -288,7 +399,14 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
});
});
- let editNodePromises = $scope.editRequests.map(function(request) {
+ let credentialPromises = credentialRequests.map(function(request) {
+ return TemplatesService.postWorkflowNodeCredential({
+ id: request.id,
+ data: request.data
+ });
+ });
+
+ let editNodePromises = editRequests.map(function(request) {
return TemplatesService.editWorkflowNode({
id: request.id,
data: request.data
@@ -299,10 +417,10 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
return TemplatesService.deleteWorkflowJobTemplateNode(nodeId);
});
- $q.all(disassociatePromises.concat(editNodePromises, deletePromises))
+ $q.all(disassociatePromises.concat(editNodePromises, deletePromises, credentialPromises))
.then(function() {
- let associatePromises = $scope.associateRequests.map(function(request) {
+ let associatePromises = associateRequests.map(function(request) {
return TemplatesService.associateWorkflowNode({
parentId: request.parentId,
nodeId: request.nodeId,
@@ -364,59 +482,41 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
});
// Set the default to success
- let edgeType = "success";
+ let edgeType = {label: "On Success", value: "success"};
if (parent && ((betweenTwoNodes && parent.source.isStartNode) || (!betweenTwoNodes && parent.isStartNode))) {
// We don't want to give the user the option to select
// a type as this node will always be executed
- edgeType = "always";
- $scope.edgeFlags.showTypeOptions = false;
+ updateEdgeDropdownOptions(["always"]);
+ edgeType = {label: "Always", value: "always"};
} else {
- if ($scope.placeholderNode.edgeConflict) {
- // This is a conflicted scenario but we'll just let the user keep building - they will have to remediate before saving
- $scope.edgeFlags.typeRestriction = null;
- } else if (_.includes(siblingConnectionTypes, "success") || _.includes(siblingConnectionTypes, "failure")) {
- $scope.edgeFlags.typeRestriction = "successFailure";
- edgeType = "success";
+ if (_.includes(siblingConnectionTypes, "success") || _.includes(siblingConnectionTypes, "failure")) {
+ updateEdgeDropdownOptions(["success", "failure"]);
+ edgeType = {label: "On Success", value: "success"};
} else if (_.includes(siblingConnectionTypes, "always")) {
- $scope.edgeFlags.typeRestriction = "always";
- edgeType = "always";
+ updateEdgeDropdownOptions(["always"]);
+ edgeType = {label: "Always", value: "always"};
} else {
- $scope.edgeFlags.typeRestriction = null;
+ updateEdgeDropdownOptions();
}
-
- $scope.edgeFlags.showTypeOptions = true;
}
// Reset the edgeConflict flag
resetEdgeConflict();
- $scope.$broadcast("setEdgeType", edgeType);
+ $scope.edgeType = edgeType;
$scope.$broadcast("refreshWorkflowChart");
};
- $scope.confirmNodeForm = function(formValues) {
+ $scope.confirmNodeForm = function() {
if ($scope.workflowMakerFormConfig.nodeMode === "add") {
- if ($scope.selectedTemplate && formValues.edgeType) {
+ if ($scope.selectedTemplate && $scope.edgeType && $scope.edgeType.value) {
$scope.placeholderNode.unifiedJobTemplate = $scope.selectedTemplate;
- $scope.placeholderNode.edgeType = formValues.edgeType;
+ $scope.placeholderNode.edgeType = $scope.edgeType.value;
if ($scope.placeholderNode.unifiedJobTemplate.type === 'job_template') {
- $scope.placeholderNode.promptValues = {
- credential: {
- id: formValues.credential,
- name: formValues.credential_name
- },
- inventory: {
- id: formValues.inventory,
- name: formValues.inventory_name
- },
- limit: formValues.limit,
- job_type: formValues.job_type && formValues.job_type.value ? formValues.job_type.value : null,
- job_tags: formValues.job_tags,
- skip_tags: formValues.skip_tags
- };
+ $scope.placeholderNode.promptData = _.cloneDeep($scope.promptData);
}
$scope.placeholderNode.canEdit = true;
@@ -429,25 +529,12 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
}
} else if ($scope.workflowMakerFormConfig.nodeMode === "edit") {
- if ($scope.selectedTemplate && formValues.edgeType) {
+ if ($scope.selectedTemplate && $scope.edgeType && $scope.edgeType.value) {
$scope.nodeBeingEdited.unifiedJobTemplate = $scope.selectedTemplate;
- $scope.nodeBeingEdited.edgeType = formValues.edgeType;
+ $scope.nodeBeingEdited.edgeType = $scope.edgeType.value;
if ($scope.nodeBeingEdited.unifiedJobTemplate.type === 'job_template') {
- $scope.nodeBeingEdited.promptValues = {
- credential: {
- id: formValues.credential,
- name: formValues.credential_name
- },
- inventory: {
- id: formValues.inventory,
- name: formValues.inventory_name
- },
- limit: formValues.limit,
- job_type: formValues.job_type && formValues.job_type.value ? formValues.job_type.value : null,
- job_tags: formValues.job_tags,
- skip_tags: formValues.skip_tags
- };
+ $scope.nodeBeingEdited.promptData = _.cloneDeep($scope.promptData);
}
$scope.nodeBeingEdited.isActiveEdit = false;
@@ -458,6 +545,12 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
}
}
+ if(promptWatcher) {
+ promptWatcher();
+ }
+
+ $scope.promptData = null;
+
// Reset the edgeConflict flag
resetEdgeConflict();
@@ -475,6 +568,12 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
$scope.nodeBeingEdited.isActiveEdit = false;
}
+ if(promptWatcher) {
+ promptWatcher();
+ }
+
+ $scope.promptData = null;
+
// Reset the edgeConflict flag
resetEdgeConflict();
@@ -515,90 +614,123 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
let finishConfiguringEdit = function() {
- let formValues = {};
+ let jobTemplate = new JobTemplate();
- if($scope.nodeBeingEdited.unifiedJobTemplate){
- // build any prompt values
- if ($scope.nodeBeingEdited.unifiedJobTemplate.ask_credential_on_launch) {
- if ($scope.nodeBeingEdited.promptValues && $scope.nodeBeingEdited.promptValues.credential) {
- formValues.credential_name = $scope.nodeBeingEdited.promptValues.credential.name;
- formValues.credential = $scope.nodeBeingEdited.promptValues.credential.id;
- } else if ($scope.nodeBeingEdited.unifiedJobTemplate.summary_fields.credential) {
- formValues.credential_name = $scope.nodeBeingEdited.unifiedJobTemplate.summary_fields.credential.name ? $scope.nodeBeingEdited.unifiedJobTemplate.summary_fields.credential.name : null;
- formValues.credential = $scope.nodeBeingEdited.unifiedJobTemplate.summary_fields.credential.id ? $scope.nodeBeingEdited.unifiedJobTemplate.summary_fields.credential.id : null;
- } else {
- formValues.credential_name = null;
- formValues.credential = null;
- }
- }
+ Rest.setUrl($scope.nodeBeingEdited.originalNodeObj.related.credentials);
- if ($scope.nodeBeingEdited.unifiedJobTemplate.ask_inventory_on_launch) {
- if ($scope.nodeBeingEdited.promptValues && $scope.nodeBeingEdited.promptValues.inventory) {
- formValues.inventory_name = $scope.nodeBeingEdited.promptValues.inventory.name;
- formValues.inventory = $scope.nodeBeingEdited.promptValues.inventory.id;
- } else if ($scope.nodeBeingEdited.unifiedJobTemplate.summary_fields.inventory) {
- formValues.inventory_name = $scope.nodeBeingEdited.unifiedJobTemplate.summary_fields.inventory.name ? $scope.nodeBeingEdited.unifiedJobTemplate.summary_fields.inventory.name : null;
- formValues.inventory = $scope.nodeBeingEdited.unifiedJobTemplate.summary_fields.inventory.id ? $scope.nodeBeingEdited.unifiedJobTemplate.summary_fields.inventory.id : null;
- } else {
- formValues.inventory_name = null;
- formValues.inventory = null;
- }
- }
+ if($scope.nodeBeingEdited.promptData) {
+ $scope.promptData = _.cloneDeep($scope.nodeBeingEdited.promptData);
+ }else if($scope.nodeBeingEdited.unifiedJobTemplate){
+ $q.all([jobTemplate.optionsLaunch($scope.nodeBeingEdited.unifiedJobTemplate.id), jobTemplate.getLaunch($scope.nodeBeingEdited.unifiedJobTemplate.id), Rest.get()])
+ .then((responses) => {
+ let launchOptions = responses[0].data,
+ launchConf = responses[1].data,
+ workflowNodeCredentials = responses[2].data.results;
- if ($scope.nodeBeingEdited.unifiedJobTemplate.ask_job_type_on_launch) {
- if ($scope.nodeBeingEdited.promptValues && $scope.nodeBeingEdited.promptValues.job_type) {
- formValues.job_type = {
- value: $scope.nodeBeingEdited.promptValues.job_type
+ let prompts = PromptService.processPromptValues({
+ launchConf: responses[1].data,
+ launchOptions: responses[0].data,
+ currentValues: $scope.nodeBeingEdited.originalNodeObj
+ });
+
+ let defaultCredsWithoutOverrides = [];
+
+ prompts.credentials.previousOverrides = _.cloneDeep(workflowNodeCredentials);
+
+ const credentialHasScheduleOverride = (templateDefaultCred) => {
+ let credentialHasOverride = false;
+ workflowNodeCredentials.forEach((scheduleCred) => {
+ if(templateDefaultCred.credential_type === scheduleCred.credential_type) {
+ if(
+ (!templateDefaultCred.vault_id && !scheduleCred.inputs.vault_id) ||
+ (templateDefaultCred.vault_id && scheduleCred.inputs.vault_id && templateDefaultCred.vault_id === scheduleCred.inputs.vault_id)
+ ) {
+ credentialHasOverride = true;
+ }
+ }
+ });
+
+ return credentialHasOverride;
};
- } else if ($scope.nodeBeingEdited.originalNodeObj.job_type) {
- formValues.job_type = {
- value: $scope.nodeBeingEdited.originalNodeObj.job_type
- };
- } else if ($scope.nodeBeingEdited.unifiedJobTemplate.job_type) {
- formValues.job_type = {
- value: $scope.nodeBeingEdited.unifiedJobTemplate.job_type
- };
- } else {
- formValues.job_type = {
- value: null
- };
- }
- }
+ if(_.has(launchConf, 'defaults.credentials')) {
+ launchConf.defaults.credentials.forEach((defaultCred) => {
+ if(!credentialHasScheduleOverride(defaultCred)) {
+ defaultCredsWithoutOverrides.push(defaultCred);
+ }
+ });
+ }
- if ($scope.nodeBeingEdited.unifiedJobTemplate.ask_limit_on_launch) {
- if ($scope.nodeBeingEdited.promptValues && typeof $scope.nodeBeingEdited.promptValues.limit === 'string') {
- formValues.limit = $scope.nodeBeingEdited.promptValues.limit;
- } else if (typeof $scope.nodeBeingEdited.originalNodeObj.limit === 'string') {
- formValues.limit = $scope.nodeBeingEdited.originalNodeObj.limit;
- } else if (typeof $scope.nodeBeingEdited.unifiedJobTemplate.limit === 'string') {
- formValues.limit = $scope.nodeBeingEdited.unifiedJobTemplate.limit;
- } else {
- formValues.limit = null;
- }
- }
- if ($scope.nodeBeingEdited.unifiedJobTemplate.ask_skip_tags_on_launch) {
- if ($scope.nodeBeingEdited.promptValues && typeof $scope.nodeBeingEdited.promptValues.skip_tags === 'string') {
- formValues.skip_tags = $scope.nodeBeingEdited.promptValues.skip_tags;
- } else if (typeof $scope.nodeBeingEdited.originalNodeObj.skip_tags === 'string') {
- formValues.skip_tags = $scope.nodeBeingEdited.originalNodeObj.skip_tags;
- } else if (typeof $scope.nodeBeingEdited.unifiedJobTemplate.skip_tags === 'string') {
- formValues.skip_tags = $scope.nodeBeingEdited.unifiedJobTemplate.skip_tags;
- } else {
- formValues.skip_tags = null;
- }
- }
- if ($scope.nodeBeingEdited.unifiedJobTemplate.ask_tags_on_launch) {
- if ($scope.nodeBeingEdited.promptValues && typeof $scope.nodeBeingEdited.promptValues.job_tags === 'string') {
- formValues.job_tags = $scope.nodeBeingEdited.promptValues.job_tags;
- } else if (typeof $scope.nodeBeingEdited.originalNodeObj.job_tags === 'string') {
- formValues.job_tags = $scope.nodeBeingEdited.originalNodeObj.job_tags;
- } else if (typeof $scope.nodeBeingEdited.unifiedJobTemplate.job_tags === 'string') {
- formValues.job_tags = $scope.nodeBeingEdited.unifiedJobTemplate.job_tags;
- } else {
- formValues.job_tags = null;
- }
- }
+ prompts.credentials.value = workflowNodeCredentials.concat(defaultCredsWithoutOverrides);
+
+ if(!launchConf.survey_enabled &&
+ !launchConf.ask_inventory_on_launch &&
+ !launchConf.ask_credential_on_launch &&
+ !launchConf.ask_verbosity_on_launch &&
+ !launchConf.ask_job_type_on_launch &&
+ !launchConf.ask_limit_on_launch &&
+ !launchConf.ask_tags_on_launch &&
+ !launchConf.ask_skip_tags_on_launch &&
+ !launchConf.ask_diff_mode_on_launch &&
+ !launchConf.survey_enabled &&
+ !launchConf.credential_needed_to_start &&
+ !launchConf.inventory_needed_to_start &&
+ launchConf.passwords_needed_to_start.length === 0 &&
+ launchConf.variables_needed_to_start.length === 0) {
+ $scope.showPromptButton = false;
+ } else {
+ $scope.showPromptButton = true;
+
+ if(launchConf.ask_inventory_on_launch && !_.has(launchConf, 'defaults.inventory') && !_.has($scope, 'nodeBeingEdited.originalNodeObj.summary_fields.inventory')) {
+ $scope.promptModalMissingReqFields = true;
+ }
+
+ if(responses[1].data.survey_enabled) {
+ // go out and get the survey questions
+ jobTemplate.getSurveyQuestions($scope.nodeBeingEdited.unifiedJobTemplate.id)
+ .then((surveyQuestionRes) => {
+
+ let processed = PromptService.processSurveyQuestions({
+ surveyQuestions: surveyQuestionRes.data.spec,
+ extra_data: $scope.nodeBeingEdited.originalNodeObj.extra_data
+ });
+
+ $scope.missingSurveyValue = processed.missingSurveyValue;
+
+ $scope.extraVars = (processed.extra_data === '' || _.isEmpty(processed.extra_data)) ? '---' : '---\n' + jsyaml.safeDump(processed.extra_data);
+
+ $scope.promptData = {
+ launchConf: launchConf,
+ launchOptions: launchOptions,
+ prompts: prompts,
+ surveyQuestions: surveyQuestionRes.data.spec,
+ template: $scope.nodeBeingEdited.unifiedJobTemplate.id
+ };
+
+ $scope.$watch('promptData.surveyQuestions', () => {
+ let missingSurveyValue = false;
+ _.each($scope.promptData.surveyQuestions, (question) => {
+ if(question.required && (Empty(question.model) || question.model === [])) {
+ missingSurveyValue = true;
+ }
+ });
+ $scope.missingSurveyValue = missingSurveyValue;
+ }, true);
+
+ watchForPromptChanges();
+ });
+ }
+ else {
+ $scope.promptData = {
+ launchConf: launchConf,
+ launchOptions: launchOptions,
+ prompts: prompts,
+ template: $scope.nodeBeingEdited.unifiedJobTemplate.id
+ };
+ watchForPromptChanges();
+ }
+ }
+ });
if ($scope.nodeBeingEdited.unifiedJobTemplate.type === "job_template") {
$scope.workflowMakerFormConfig.activeTab = "jobs";
@@ -641,31 +773,30 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
childId: nodeToEdit.id
});
- if (parent && parent.isStartNode) {
- // We don't want to give the user the option to select
- // a type as this node will always be executed
- $scope.edgeFlags.showTypeOptions = false;
- } else {
- if (nodeToEdit.edgeConflict) {
- // This is a conflicted scenario but we'll just let the user keep building - they will have to remediate before saving
- $scope.edgeFlags.typeRestriction = null;
- } else if (_.includes(siblingConnectionTypes, "success") || _.includes(siblingConnectionTypes, "failure")) {
- $scope.edgeFlags.typeRestriction = "successFailure";
- } else if (_.includes(siblingConnectionTypes, "always")) {
- $scope.edgeFlags.typeRestriction = "always";
- } else {
- $scope.edgeFlags.typeRestriction = null;
- }
+ let edgeDropdownOptions = null;
- $scope.edgeFlags.showTypeOptions = true;
- }
+ switch($scope.nodeBeingEdited.edgeType) {
+ case "always":
+ $scope.edgeType = {label: "Always", value: "always"};
+ if(siblingConnectionTypes.length === 0 || (siblingConnectionTypes.length === 1 && _.includes(siblingConnectionTypes, "always"))) {
+ edgeDropdownOptions = ["always"];
+ }
+ break;
+ case "success":
+ $scope.edgeType = {label: "On Success", value: "success"};
+ if(siblingConnectionTypes.length === 0 || (!_.includes(siblingConnectionTypes, "always"))) {
+ edgeDropdownOptions = ["success", "failure"];
+ }
+ break;
+ case "failure":
+ $scope.edgeType = {label: "On Failure", value: "failure"};
+ if(siblingConnectionTypes.length === 0 || (!_.includes(siblingConnectionTypes, "always"))) {
+ edgeDropdownOptions = ["success", "failure"];
+ }
+ break;
+ }
- $scope.$broadcast('setEdgeType', $scope.nodeBeingEdited.edgeType);
-
- $scope.$broadcast('templateSelected', {
- presetValues: formValues,
- activeTab: $scope.workflowMakerFormConfig.activeTab
- });
+ updateEdgeDropdownOptions(edgeDropdownOptions);
$scope.$broadcast("refreshWorkflowChart");
};
@@ -679,47 +810,8 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
TemplatesService.getUnifiedJobTemplate($scope.nodeBeingEdited.unifiedJobTemplate.id)
.then(function(data) {
-
$scope.nodeBeingEdited.unifiedJobTemplate = _.clone(data.data.results[0]);
-
- let defers = [];
- let retrievingCredential = false;
- let retrievingInventory = false;
-
- if ($scope.nodeBeingEdited.unifiedJobTemplate.ask_credential_on_launch && $scope.nodeBeingEdited.originalNodeObj.credential) {
- defers.push(TemplatesService.getCredential($scope.nodeBeingEdited.originalNodeObj.credential));
- retrievingCredential = true;
- }
-
- if ($scope.nodeBeingEdited.unifiedJobTemplate.ask_inventory_on_launch && $scope.nodeBeingEdited.originalNodeObj.inventory) {
- defers.push(TemplatesService.getInventory($scope.nodeBeingEdited.originalNodeObj.inventory));
- retrievingInventory = true;
- }
-
- $q.all(defers)
- .then(function(responses) {
- if (retrievingCredential) {
- $scope.nodeBeingEdited.promptValues.credential = {
- name: responses[0].data.name,
- id: responses[0].data.id
- };
-
- if (retrievingInventory) {
- $scope.nodeBeingEdited.promptValues.inventory = {
- name: responses[1].data.name,
- id: responses[1].data.id
- };
- }
- } else if (retrievingInventory) {
- $scope.nodeBeingEdited.promptValues.inventory = {
- name: responses[0].data.name,
- id: responses[0].data.id
- };
- }
- finishConfiguringEdit();
- });
-
-
+ finishConfiguringEdit();
}, function(error) {
ProcessErrors($scope, error.data, error.status, form, {
hdr: 'Error!',
@@ -779,7 +871,6 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
if($scope.placeholderNode) {
let edgeType = "success";
if($scope.placeholderNode.isRoot) {
- $scope.edgeFlags.showTypeOptions = false;
edgeType = "always";
}
else {
@@ -790,49 +881,45 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
childId: $scope.placeholderNode.id
});
- if ($scope.placeholderNode.edgeConflict) {
- // This is a conflicted scenario but we'll just let the user keep building - they will have to remediate before saving
- $scope.edgeFlags.typeRestriction = null;
- } else if (_.includes(siblingConnectionTypes, "success") || _.includes(siblingConnectionTypes, "failure")) {
- $scope.edgeFlags.typeRestriction = "successFailure";
+ if (_.includes(siblingConnectionTypes, "success") || _.includes(siblingConnectionTypes, "failure")) {
+ updateEdgeDropdownOptions(["success", "failure"]);
} else if (_.includes(siblingConnectionTypes, "always")) {
- $scope.edgeFlags.typeRestriction = "always";
+ updateEdgeDropdownOptions(["always"]);
edgeType = "always";
} else {
- $scope.edgeFlags.typeRestriction = null;
+ updateEdgeDropdownOptions();
}
- $scope.edgeFlags.showTypeOptions = true;
-
}
- $scope.$broadcast("setEdgeType", edgeType);
+ $scope.edgeType = edgeType;
+ // $scope.$broadcast("setEdgeType", edgeType);
}
else if($scope.nodeBeingEdited) {
- if($scope.nodeBeingEdited.isRoot) {
- $scope.edgeFlags.showTypeOptions = false;
+ let siblingConnectionTypes = WorkflowService.getSiblingConnectionTypes({
+ tree: $scope.treeData.data,
+ parentId: $scope.nodeBeingEdited.parent.id,
+ childId: $scope.nodeBeingEdited.id
+ });
+
+ if (_.includes(siblingConnectionTypes, "success") || _.includes(siblingConnectionTypes, "failure")) {
+ updateEdgeDropdownOptions(["success", "failure"]);
+ } else if (_.includes(siblingConnectionTypes, "always") && $scope.nodeBeingEdited.edgeType === "always") {
+ updateEdgeDropdownOptions(["always"]);
+ } else {
+ updateEdgeDropdownOptions();
}
- else {
- let siblingConnectionTypes = WorkflowService.getSiblingConnectionTypes({
- tree: $scope.treeData.data,
- parentId: $scope.nodeBeingEdited.parent.id,
- childId: $scope.nodeBeingEdited.id
- });
- if ($scope.nodeBeingEdited.edgeConflict) {
- // This is a conflicted scenario but we'll just let the user keep building - they will have to remediate before saving
- $scope.edgeFlags.typeRestriction = null;
- } else if (_.includes(siblingConnectionTypes, "success") || _.includes(siblingConnectionTypes, "failure")) {
- $scope.edgeFlags.typeRestriction = "successFailure";
- } else if (_.includes(siblingConnectionTypes, "always") && $scope.nodeBeingEdited.edgeType === "always") {
- $scope.edgeFlags.typeRestriction = "always";
- } else {
- $scope.edgeFlags.typeRestriction = null;
- }
-
- $scope.edgeFlags.showTypeOptions = true;
-
- }
- $scope.$broadcast("setEdgeType", $scope.nodeBeingEdited.edgeType);
+ switch($scope.nodeBeingEdited.edgeType) {
+ case "always":
+ $scope.edgeType = {label: "Always", value: "always"};
+ break;
+ case "success":
+ $scope.edgeType = {label: "On Success", value: "success"};
+ break;
+ case "failure":
+ $scope.edgeType = {label: "On Failure", value: "failure"};
+ break;
+ }
}
$scope.treeData.data.totalNodes--;
@@ -846,63 +933,93 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
}
};
- $scope.templateSelected = function(selectedTemplate) {
+ $scope.templateManuallySelected = function(selectedTemplate) {
$scope.selectedTemplate = angular.copy(selectedTemplate);
- let formValues = {};
+ if(selectedTemplate.type === "job_template") {
+ let jobTemplate = new JobTemplate();
- if ($scope.selectedTemplate.ask_credential_on_launch) {
- if ($scope.selectedTemplate.summary_fields.credential) {
- formValues.credential_name = $scope.selectedTemplate.summary_fields.credential.name ? $scope.selectedTemplate.summary_fields.credential.name : null;
- formValues.credential = $scope.selectedTemplate.summary_fields.credential.id ? $scope.selectedTemplate.summary_fields.credential.id : null;
- } else {
- formValues.credential_name = null;
- formValues.credential = null;
- }
+ $q.all([jobTemplate.optionsLaunch(selectedTemplate.id), jobTemplate.getLaunch(selectedTemplate.id)])
+ .then((responses) => {
+ let launchConf = responses[1].data;
+
+ if(!launchConf.survey_enabled &&
+ !launchConf.ask_inventory_on_launch &&
+ !launchConf.ask_credential_on_launch &&
+ !launchConf.ask_verbosity_on_launch &&
+ !launchConf.ask_job_type_on_launch &&
+ !launchConf.ask_limit_on_launch &&
+ !launchConf.ask_tags_on_launch &&
+ !launchConf.ask_skip_tags_on_launch &&
+ !launchConf.ask_diff_mode_on_launch &&
+ !launchConf.survey_enabled &&
+ !launchConf.credential_needed_to_start &&
+ !launchConf.inventory_needed_to_start &&
+ launchConf.passwords_needed_to_start.length === 0 &&
+ launchConf.variables_needed_to_start.length === 0) {
+ $scope.showPromptButton = false;
+ } else {
+ $scope.showPromptButton = true;
+
+ if(launchConf.ask_inventory_on_launch && !_.has(launchConf, 'defaults.inventory')) {
+ $scope.promptModalMissingReqFields = true;
+ }
+
+ if(launchConf.survey_enabled) {
+ // go out and get the survey questions
+ jobTemplate.getSurveyQuestions(selectedTemplate.id)
+ .then((surveyQuestionRes) => {
+
+ let processed = PromptService.processSurveyQuestions({
+ surveyQuestions: surveyQuestionRes.data.spec
+ });
+
+ $scope.missingSurveyValue = processed.missingSurveyValue;
+
+ $scope.promptData = {
+ launchConf: responses[1].data,
+ launchOptions: responses[0].data,
+ surveyQuestions: processed.surveyQuestions,
+ template: selectedTemplate.id,
+ prompts: PromptService.processPromptValues({
+ launchConf: responses[1].data,
+ launchOptions: responses[0].data
+ }),
+ };
+
+ $scope.$watch('promptData.surveyQuestions', () => {
+ let missingSurveyValue = false;
+ _.each($scope.promptData.surveyQuestions, (question) => {
+ if(question.required && (Empty(question.model) || question.model === [])) {
+ missingSurveyValue = true;
+ }
+ });
+ $scope.missingSurveyValue = missingSurveyValue;
+ }, true);
+
+ watchForPromptChanges();
+ });
+ }
+ else {
+ $scope.promptData = {
+ launchConf: responses[1].data,
+ launchOptions: responses[0].data,
+ template: selectedTemplate.id,
+ prompts: PromptService.processPromptValues({
+ launchConf: responses[1].data,
+ launchOptions: responses[0].data
+ }),
+ };
+
+ watchForPromptChanges();
+ }
+ }
+ });
+ } else {
+ // TODO - clear out prompt data?
+ $scope.showPromptButton = false;
}
-
- if ($scope.selectedTemplate.ask_inventory_on_launch) {
- if ($scope.selectedTemplate.summary_fields.inventory) {
- formValues.inventory_name = $scope.selectedTemplate.summary_fields.inventory.name ? $scope.selectedTemplate.summary_fields.inventory.name : null;
- formValues.inventory = $scope.selectedTemplate.summary_fields.inventory.id ? $scope.selectedTemplate.summary_fields.inventory.id : null;
- } else {
- formValues.inventory_name = null;
- formValues.inventory = null;
- }
- }
-
- if ($scope.selectedTemplate.ask_job_type_on_launch) {
- formValues.job_type = {
- value: $scope.selectedTemplate.job_type ? $scope.selectedTemplate.job_type : null
- };
-
- // The default needs to be in place before we can select2-ify the dropdown
- CreateSelect2({
- element: '#workflow_maker_job_type',
- multiple: false
- });
- }
-
- if ($scope.selectedTemplate.ask_limit_on_launch) {
- formValues.limit = $scope.selectedTemplate.limit ? $scope.selectedTemplate.limit : null;
- }
-
- if ($scope.selectedTemplate.ask_skip_tags_on_launch) {
- formValues.skip_tags = $scope.selectedTemplate.skip_tags ? $scope.selectedTemplate.skip_tags : null;
- }
-
- if ($scope.selectedTemplate.ask_tags_on_launch) {
- formValues.job_tags = $scope.selectedTemplate.job_tags ? $scope.selectedTemplate.job_tags : null;
- }
-
- // Communicate down the scope chain to our children that a template has been selected. This
- // will handle populating the form properly as well as clearing out any previously selected
- // templates in different lists
- $scope.$broadcast('templateSelected', {
- presetValues: formValues,
- activeTab: $scope.workflowMakerFormConfig.activeTab
- });
};
function resetEdgeConflict(){
@@ -944,7 +1061,61 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
$scope.$broadcast('zoomToFitChart');
};
- init();
+ $scope.openPromptModal = function() {
+ $scope.promptData.triggerModalOpen = true;
+ };
+
+ let allNodes = [];
+ let page = 1;
+
+ let buildTreeFromNodes = function(){
+ WorkflowService.buildTree({
+ workflowNodes: allNodes
+ }).then(function(data){
+ $scope.treeData = data;
+
+ // TODO: I think that the workflow chart directive (and eventually d3) is meddling with
+ // this treeData object and removing the children object for some reason (?)
+ // This happens on occasion and I think is a race condition (?)
+ if(!$scope.treeData.data.children) {
+ $scope.treeData.data.children = [];
+ }
+
+ $scope.treeData.workflow_job_template_obj = $scope.workflowJobTemplateObj;
+
+ $scope.treeDataMaster = angular.copy($scope.treeData.data);
+ $scope.showManualControls = false;
+ });
+ };
+
+ let getNodes = function(){
+ // Get the workflow nodes
+ TemplatesService.getWorkflowJobTemplateNodes($scope.workflowJobTemplateObj.id, page)
+ .then(function(data){
+ for(var i=0; i
-
+
+
+
+
+
+
+
+
+
@@ -101,4 +125,5 @@
+