1
0
mirror of https://github.com/ansible/awx.git synced 2024-11-01 16:51:11 +03:00

Merge pull request #1489 from mabashian/169-workflow-nodes

Implemented new workflow node prompting
This commit is contained in:
Michael Abashian 2018-03-14 16:58:35 -04:00 committed by GitHub
commit 597874b849
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 681 additions and 613 deletions

View File

@ -349,7 +349,7 @@ function($filter, $state, $stateParams, Wait, $scope, moment,
let processed = PromptService.processSurveyQuestions({
surveyQuestions: surveyQuestionRes.data.spec,
extra_data: data.extra_data
extra_data: _.cloneDeep(data.extra_data)
});
$scope.missingSurveyValue = processed.missingSurveyValue;

View File

@ -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,116 +731,6 @@ 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 `<lookup-modal>${list_html}</lookup-modal>`;
}
}
},
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 `<lookup-modal>${list_html}</lookup-modal>`;
}
}
},
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([
addJobTemplate,
editJobTemplate,
@ -919,9 +742,7 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p
return result.concat(definition.states);
}, [
stateExtender.buildDefinition(listRoute),
stateExtender.buildDefinition(workflowMaker),
stateExtender.buildDefinition(inventoryLookup),
stateExtender.buildDefinition(credentialLookup)
stateExtender.buildDefinition(workflowMaker)
])
};
});

View File

@ -1,5 +1,5 @@
<div class="Prompt">
<at-modal>
<at-modal ng-if="vm.promptData">
<at-tab-group>
<at-tab ng-if="vm.steps.inventory.tab" state="vm.steps.inventory.tab">{{:: vm.strings.get('prompt.INVENTORY') }}</at-tab>
<at-tab ng-if="vm.steps.credential.tab" state="vm.steps.credential.tab">{{:: vm.strings.get('prompt.CREDENTIAL') }}</at-tab>

View File

@ -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]}));

View File

@ -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;
}
});
});
});
}

View File

@ -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'
});
});
}
};

View File

@ -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);
}
};
}];

View File

@ -93,7 +93,31 @@
<div id="workflow-project-sync-list" ng-show="workflowMakerFormConfig.activeTab === 'project_sync'" ui-view="projectSyncList"></div>
<div id="workflow-inventory-sync-list" ng-show="workflowMakerFormConfig.activeTab === 'inventory_sync'" ui-view="inventorySyncList"></div>
</div>
<div id="workflow-maker-form" ui-view="workflowForm"></div>
<div ng-show="selectedTemplate">
<div class="form-group Form-formGroup Form-formGroup--singleColumn">
<label for="verbosity" class="Form-inputLabelContainer">
<span class="Form-requiredAsterisk">*</span>
<span class="Form-inputLabel">RUN</span>
</label>
<div>
<select
id="workflow_node_edge"
ng-options="v as v.label for v in edgeTypeOptions track by v.value"
ng-model="edgeType"
class="form-control Form-dropDown"
name="edgeType"
tabindex="-1"
aria-hidden="true">
</select>
</div>
</div>
<div class="buttons Form-buttons" id="workflow_maker_controls">
<button type="button" class="btn btn-sm Form-primaryButton Form-primaryButton--noMargin" id="workflow_maker_prompt_btn" ng-show="showPromptButton" ng-click="openPromptModal()"> Prompt</button>
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_cancel_btn" ng-show="(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)" ng-click="cancelNodeForm()"> Cancel</button>
<button type="button" class="btn btn-sm Form-cancelButton" id="workflow_maker_close_btn" ng-show="!(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)" ng-click="cancelNodeForm()"> Close</button>
<button type="button" class="btn btn-sm Form-saveButton" id="workflow_maker_select_btn" ng-show="(workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate)" ng-click="confirmNodeForm()" ng-disabled="workflow_maker_form.$invalid || !selectedTemplate || promptModalMissingReqFields" disabled="disabled"> Select</button>
</div>
</div>
</div>
</div>
</div>
@ -101,4 +125,5 @@
<button type="button" class="btn btn-sm WorkflowMaker-cancelButton" ng-click="closeWorkflowMaker()"> Close</button>
<button type="button" class="btn btn-sm WorkflowMaker-saveButton" ng-click="saveWorkflowMaker()" ng-show="workflowJobTemplateObj.summary_fields.user_capabilities.edit || canAddWorkflowJobTemplate" ng-disabled="edgeFlags.conflict || workflowMakerFormConfig.nodeMode === 'add'"> Save</button>
</div>
<prompt prompt-data="promptData" action-text="CONFIRM"></launch>
</div>