diff --git a/awx/ui/client/src/job-templates/edit-workflow/workflow-edit.controller.js b/awx/ui/client/src/job-templates/edit-workflow/workflow-edit.controller.js
index 18a07e5fe5..b79b10ce83 100644
--- a/awx/ui/client/src/job-templates/edit-workflow/workflow-edit.controller.js
+++ b/awx/ui/client/src/job-templates/edit-workflow/workflow-edit.controller.js
@@ -14,7 +14,7 @@
ClearScope, GetBasePath, $q, ParseTypeChange, Wait, Empty,
ToJSON, SurveyControllerInit, $state, CreateSelect2, ParseVariableString,
JobTemplateService, OrganizationList, Rest
- ) {
+ ) {window.state = $state;
ClearScope();
diff --git a/awx/ui/client/src/job-templates/main.js b/awx/ui/client/src/job-templates/main.js
index 6b2ea34945..ba0fae8dd5 100644
--- a/awx/ui/client/src/job-templates/main.js
+++ b/awx/ui/client/src/job-templates/main.js
@@ -76,10 +76,17 @@ angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemp
workflowMaker = {
name: 'templates.editWorkflowJobTemplate.workflowMaker',
url: '/workflow-maker',
+ // ncyBreadcrumb: {
+ // label: 'WORKFLOW MAKER'
+ // },
+ data: {
+ formChildState: true
+ },
params: {
- template_search: {
+ job_template_search: {
value: {
- page_size: '5'
+ page_size: '5',
+ type: 'job_template'
},
squash: true,
dynamic: true
@@ -104,26 +111,18 @@ angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemp
template: ` `
},
'jobTemplateList@templates.editWorkflowJobTemplate.workflowMaker': {
- templateProvider: function(JobTemplateList, generateList) {
- let list = _.cloneDeep(JobTemplateList);
- delete list.fields.type;
- delete list.fields.description;
- delete list.fields.smart_status;
- delete list.fields.labels;
- delete list.fieldActions;
- list.fields.name.columnClass = "col-md-11";
+ templateProvider: function(WorkflowMakerJobTemplateList, generateList) {
+ //debugger;
let html = generateList.build({
- list: list,
+ list: WorkflowMakerJobTemplateList,
input_type: 'radio',
mode: 'lookup'
});
return html;
},
// $scope encapsulated in this controller will be a initialized as child of 'modal' $scope, because of element hierarchy
- controller: ['$scope', 'JobTemplateList', 'JobTemplateDataset', '$log',
- function($scope, list, Dataset, $log) {
- // name of this tab
- let tab = 'jobs';
+ controller: ['$scope', 'WorkflowMakerJobTemplateList', 'JobTemplateDataset',
+ function($scope, list, Dataset) {
init();
@@ -133,14 +132,25 @@ angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemp
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
}
- // resets any selected list items, if this tab is not active
- $scope.$on('resetWorkflowList', function(e, active) {
- // e.targetScope is a reference to the outer scope if you need to manipulate it!
+ $scope.toggle_job_template = function(id) {
- // a reference to the currently-selected radio is stored in $scope.selection[list.iterator]
- // clear it out!
- if (active !== tab) {
- $scope.selection[list.iterator] = null;
+ $scope.job_templates.forEach(function(row, i) {
+ if (row.id === id) {
+ $scope.job_templates[i].checked = 1;
+ $scope.selection[list.iterator] = {
+ id: row.id,
+ name: row.name
+ };
+
+ $scope.$emit('templateSelected', row);
+ }
+ });
+
+ };
+
+ $scope.$on('clearOtherTemplateLists', function(e, tab) {
+ if(tab !== 'jobs') {
+ // Clear out any selected job
}
});
}
@@ -160,7 +170,6 @@ angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemp
// encapsulated $scope in this controller will be a initialized as child of 'modal' $scope, because of element hierarchy
controller: ['$scope', 'InventorySourcesList', 'InventorySourcesDataset',
function($scope, list, Dataset) {
- let tab = 'inventory_sync';
init();
@@ -171,35 +180,42 @@ angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemp
}
- // resets any selected list items, if this tab is not active
- $scope.$on('resetWorkflowList', function(e, active) {
- // e.targetScope is a reference to the outer scope if you need to manipulate it!
+ $scope.toggle_inventory_source = function(id) {
+
+ $scope.inventory_sources.forEach(function(row, i) {
+ if (row.id === id) {
+ $scope.inventory_sources[i].checked = 1;
+ $scope.selection[list.iterator] = {
+ id: row.id,
+ name: row.name
+ };
+
+ $scope.$emit('templateSelected', row);
+ }
+ });
+
+ };
+
+ $scope.$on('clearOtherTemplateLists', function(e, tab) {
+ if(tab !== 'project_sync') {
- if (active !== tab) {
- $scope.selection[list.iterator] = null;
}
});
}
]
},
'projectSyncList@templates.editWorkflowJobTemplate.workflowMaker': {
- templateProvider: function(ProjectList, generateList) {
- let list = _.cloneDeep(ProjectList);
- delete list.fields.status;
- delete list.fields.scm_type;
- delete list.fields.last_updated;
- list.fields.name.columnClass = "col-md-11";
+ templateProvider: function(WorkflowProjectList, generateList) {
let html = generateList.build({
- list: list,
+ list: WorkflowProjectList,
input_type: 'radio',
mode: 'lookup'
});
return html;
},
// encapsulated $scope in this controller will be a initialized as child of 'modal' $scope, because of element hierarchy
- controller: ['$scope', 'ProjectList', 'ProjectDataset',
+ controller: ['$scope', 'WorkflowProjectList', 'ProjectDataset',
function($scope, list, Dataset) {
- let tab = 'project_sync';
init();
@@ -209,12 +225,26 @@ angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemp
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
}
- // resets any selected list items, if this tab is not active
- $scope.$on('resetWorkflowList', function(e, active) {
- // e.targetScope is a reference to the outer scope if you need to manipulate it!
- if (active !== tab) {
- $scope.selection[list.iterator] = null;
+ $scope.toggle_project = function(id) {
+
+ $scope.projects.forEach(function(row, i) {
+ if (row.id === id) {
+ $scope.projects[i].checked = 1;
+ $scope.selection[list.iterator] = {
+ id: row.id,
+ name: row.name
+ };
+
+ $scope.$emit('templateSelected', row);
+ }
+ });
+
+ };
+
+ $scope.$on('clearOtherTemplateLists', function(e, tab) {
+ if(tab !== 'inventory_sync') {
+
}
});
}
@@ -233,7 +263,7 @@ angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemp
}
},
resolve: {
- JobTemplateDataset: ['JobTemplateList', 'QuerySet', '$stateParams', 'GetBasePath',
+ JobTemplateDataset: ['WorkflowMakerJobTemplateList', 'QuerySet', '$stateParams', 'GetBasePath',
(list, qs, $stateParams, GetBasePath) => {
let path = GetBasePath(list.basePath);
return qs.search(path, $stateParams[`${list.iterator}_search`]);
@@ -250,6 +280,32 @@ angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemp
let path = GetBasePath(list.basePath);
return qs.search(path, $stateParams[`${list.iterator}_search`]);
}
+ ],
+ WorkflowMakerJobTemplateList: ['JobTemplateList',
+ (JobTemplateList) => {
+ let list = _.cloneDeep(JobTemplateList);
+ delete list.fields.type;
+ delete list.fields.description;
+ delete list.fields.smart_status;
+ delete list.fields.labels;
+ delete list.fieldActions;
+ list.fields.name.columnClass = "col-md-11";
+ list.iterator = 'job_template';
+ list.name = 'job_templates';
+
+ return list;
+ }
+ ],
+ WorkflowProjectList: ['ProjectList',
+ (ProjectList) => {
+ let list = _.cloneDeep(ProjectList);
+ delete list.fields.status;
+ delete list.fields.scm_type;
+ delete list.fields.last_updated;
+ list.fields.name.columnClass = "col-md-11";
+
+ return list;
+ }
]
}
};
@@ -259,7 +315,7 @@ angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemp
name: 'templates.editWorkflowJobTemplate.workflowMaker.inventory',
url: '/inventory',
data: {
- lookup: true
+ formChildState: true
},
params: {
inventory_search: {
@@ -309,7 +365,7 @@ angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemp
name: 'templates.editWorkflowJobTemplate.workflowMaker.credential',
url: '/credential',
data: {
- lookup: true
+ formChildState: true
},
params: {
credential_search: {
@@ -334,7 +390,7 @@ angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemp
}
},
resolve: {
- ListDefinition: ['ListDefinition', function(list) {
+ ListDefinition: ['CredentialList', function(list) {
// mutate the provided list definition here
return list;
}],
diff --git a/awx/ui/client/src/job-templates/workflow-maker/workflow-help.service.js b/awx/ui/client/src/job-templates/workflow-maker/workflow-help.service.js
index 24c7fd9679..25b889e4fd 100644
--- a/awx/ui/client/src/job-templates/workflow-maker/workflow-help.service.js
+++ b/awx/ui/client/src/job-templates/workflow-maker/workflow-help.service.js
@@ -1,49 +1,9 @@
-export default ['CreateDialog', 'Wait', '$q', function(CreateDialog, Wait, $q){
+export default ['CreateDialog', 'Wait', '$q', '$state', function(CreateDialog, Wait, $q, $state){
return {
- openDialog: function(params){
- // params.scope
-
- // let deferred = $q.defer();
-
- // if (params.scope.removeWorkflowDialogReady) {
- // params.scope.removeWorkflowDialogReady();
- // }
- // params.scope.removeWorkflowDialogReady = params.scope.$on('WorkflowDialogReady', function() {
- // $('#workflow-modal-dialog').dialog('open');
-
- // deferred.resolve();
- // });
- // Wait('start');
- // debugger;
- // CreateDialog({
- // id: 'workflow-modal-dialog',
- // scope: params.scope,
- // width: 1400,
- // height: 720,
- // draggable: false,
- // dialogClass: 'SurveyMaker-dialog',
- // position: ['center',20],
- // onClose: function() {
- // $('#workflow-modal-dialog').empty();
- // },
- // onOpen: function() {
- // Wait('stop');
-
- // // Let the modal height be variable based on the content
- // // and set a uniform padding
- // $('#workflow-modal-dialog').css({'padding': '20px'});
-
- // },
- // _allowInteraction: function(e) {
- // return !!$(e.target).is('.select2-input') || this._super(e);
- // },
- // callback: 'WorkflowDialogReady'
- // });
-
- // return deferred.promise;
- },
closeDialog: function() {
$('#workflow-modal-dialog').dialog('destroy');
+
+ $state.go('^');
},
searchTree: function(params) {
// params.element
diff --git a/awx/ui/client/src/job-templates/workflow-maker/workflow-maker.controller.js b/awx/ui/client/src/job-templates/workflow-maker/workflow-maker.controller.js
index 498dd73965..c68a4fbf63 100644
--- a/awx/ui/client/src/job-templates/workflow-maker/workflow-maker.controller.js
+++ b/awx/ui/client/src/job-templates/workflow-maker/workflow-maker.controller.js
@@ -32,78 +32,10 @@ export default ['$scope', 'WorkflowHelpService', 'generateList', 'JobTemplateLis
value: "check"
}];
- let job_template_url = GetBasePath('job_templates');
- // TODO: we won't be able to rely on this in the future for security purposes. Will need to come up
- // with another way to get the list of job templates that have credentials that don't require passwords
- // on launch
- job_template_url += "?not__credential__vault_password=ASK¬__credential__password=ASK";
- //http://localhost:3000/api/v1/job_templates/?not__credential__vault_password=ASK¬__credential__password=ASK
-
- // Set up the lists for the add/edit node form
- // let jobTemplatesList = _.cloneDeep(JobTemplateList);
- // delete jobTemplatesList.fields.type;
- // delete jobTemplatesList.fields.description;
- // delete jobTemplatesList.fields.smart_status;
- // delete jobTemplatesList.fields.labels;
- // jobTemplatesList.fields.name.columnClass = "col-md-11";
- // jobTemplatesList.name = "workflow_job_templates";
-
- // let project_url = GetBasePath('projects');
-
- // let projectList = _.cloneDeep(ProjectList);
- // delete projectList.fields.status;
- // delete projectList.fields.scm_type;
- // delete projectList.fields.last_updated;
- // projectList.fields.name.columnClass = "col-md-11";
- // projectList.name = "workflow_projects";
-
- //let inventory_sources_url = GetBasePath('inventory_sources');
-
- //let inventorySourcesList = _.cloneDeep(InventorySourcesList);
-
function init() {
$scope.treeDataMaster = angular.copy($scope.treeData.data);
$scope.$broadcast("refreshWorkflowChart");
- $scope.$watchCollection('workflow_job_templates', function() {
- if ($scope.selectedTemplate) {
- // Loop across the inventories and see if one of them should be "checked"
- $scope.workflow_job_templates.forEach(function(row, i) {
- if (row.id === $scope.selectedTemplate.id) {
- $scope.workflow_job_templates[i].checked = 1;
- } else {
- $scope.workflow_job_templates[i].checked = 0;
- }
- });
- }
- });
-
- $scope.$watchCollection('workflow_projects', function() {
- if ($scope.selectedTemplate) {
- // Loop across the inventories and see if one of them should be "checked"
- $scope.workflow_projects.forEach(function(row, i) {
- if (row.id === $scope.selectedTemplate.id) {
- $scope.workflow_projects[i].checked = 1;
- } else {
- $scope.workflow_projects[i].checked = 0;
- }
- });
- }
- });
-
- $scope.$watchCollection('workflow_inventory_sources', function() {
- if ($scope.selectedTemplate) {
- // Loop across the inventories and see if one of them should be "checked"
- $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.$watchGroup(['selectedTemplate', 'edgeType'], function() {
if ($scope.selectedTemplate && $scope.edgeType) {
$scope.workflowMakerFormConfig.formIsValid = true;
@@ -143,7 +75,11 @@ export default ['$scope', 'WorkflowHelpService', 'generateList', 'JobTemplateLis
}
$scope.lookUpInventory = function(){
- $state.go('.inventory')
+ $state.go('.inventory');
+ };
+
+ $scope.lookUpCredential = function(){
+ $state.go('.credential');
};
$scope.closeWorkflowMaker = function() {
@@ -540,123 +476,63 @@ export default ['$scope', 'WorkflowHelpService', 'generateList', 'JobTemplateLis
};
$scope.toggleFormTab = function(tab) {
- // a dictionary of settings required by each encapsulated tab
- $scope.$broadcast('resetWorkflowList', tab);
if ($scope.workflowMakerFormConfig.activeTab !== tab) {
$scope.workflowMakerFormConfig.activeTab = tab;
}
};
- $scope.toggle_job_template = function(id) {
-
- // $scope.workflow_projects.forEach(function(row, i) {
- // $scope.workflow_projects[i].checked = 0;
- // });
-
- // $scope.workflow_inventory_sources.forEach(function(row, i) {
- // $scope.workflow_inventory_sources[i].checked = 0;
- // });
-
- $scope.workflow_job_templates.forEach(function(row, i) {
- if (row.id === id) {
- $scope.selectedTemplate = angular.copy(row);
- if ($scope.selectedTemplate.ask_credential_on_launch) {
- if ($scope.selectedTemplate.summary_fields.credential) {
- $scope.credential_name = $scope.selectedTemplate.summary_fields.credential.name ? $scope.selectedTemplate.summary_fields.credential.name : null;
- $scope.credential = $scope.selectedTemplate.summary_fields.credential.id ? $scope.selectedTemplate.summary_fields.credential.id : null;
- } else {
- $scope.credential_name = null;
- $scope.credential = null;
- }
- }
-
- if ($scope.selectedTemplate.ask_inventory_on_launch) {
- if ($scope.selectedTemplate.summary_fields.inventory) {
- $scope.inventory_name = $scope.selectedTemplate.summary_fields.inventory.name ? $scope.selectedTemplate.summary_fields.inventory.name : null;
- $scope.inventory = $scope.selectedTemplate.summary_fields.inventory.id ? $scope.selectedTemplate.summary_fields.inventory.id : null;
- } else {
- $scope.inventory_name = null;
- $scope.inventory = null;
- }
- }
-
- if ($scope.selectedTemplate.ask_job_type_on_launch) {
- $scope.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) {
- $scope.limit = $scope.selectedTemplate.limit ? $scope.selectedTemplate.limit : null;
- }
-
- if ($scope.selectedTemplate.ask_skip_tags_on_launch) {
- $scope.skip_tags = $scope.selectedTemplate.skip_tags ? $scope.selectedTemplate.skip_tags : null;
- }
-
- if ($scope.selectedTemplate.ask_tags_on_launch) {
- $scope.job_tags = $scope.selectedTemplate.job_tags ? $scope.selectedTemplate.job_tags : null;
- }
-
- $scope.workflow_job_templates[i].checked = 1;
- } else {
- $scope.workflow_job_templates[i].checked = 0;
- }
- });
-
- };
-
- $scope.toggle_project = function(id) {
+ $scope.$on('templateSelected', function(e, selectedTemplate) {
resetPromptFields();
- // $scope.workflow_job_templates.forEach(function(row, i) {
- // $scope.workflow_job_templates[i].checked = 0;
- // });
+ $scope.selectedTemplate = angular.copy(selectedTemplate);
- // $scope.workflow_inventory_sources.forEach(function(row, i) {
- // $scope.workflow_inventory_sources[i].checked = 0;
- // });
-
- $scope.workflow_projects.forEach(function(row, i) {
- if (row.id === id) {
- $scope.selectedTemplate = angular.copy(row);
- $scope.workflow_projects[i].checked = 1;
+ if ($scope.selectedTemplate.ask_credential_on_launch) {
+ if ($scope.selectedTemplate.summary_fields.credential) {
+ $scope.credential_name = $scope.selectedTemplate.summary_fields.credential.name ? $scope.selectedTemplate.summary_fields.credential.name : null;
+ $scope.credential = $scope.selectedTemplate.summary_fields.credential.id ? $scope.selectedTemplate.summary_fields.credential.id : null;
} else {
- $scope.workflow_projects[i].checked = 0;
+ $scope.credential_name = null;
+ $scope.credential = null;
}
- });
+ }
- };
-
- $scope.toggle_inventory_source = function(id) {
-
- resetPromptFields();
-
- // $scope.workflow_job_templates.forEach(function(row, i) {
- // $scope.workflow_job_templates[i].checked = 0;
- // });
-
- // $scope.workflow_projects.forEach(function(row, i) {
- // $scope.workflow_projects[i].checked = 0;
- // });
-
- $scope.workflow_inventory_sources.forEach(function(row, i) {
- if (row.id === id) {
- $scope.selectedTemplate = angular.copy(row);
- $scope.workflow_inventory_sources[i].checked = 1;
+ if ($scope.selectedTemplate.ask_inventory_on_launch) {
+ if ($scope.selectedTemplate.summary_fields.inventory) {
+ $scope.inventory_name = $scope.selectedTemplate.summary_fields.inventory.name ? $scope.selectedTemplate.summary_fields.inventory.name : null;
+ $scope.inventory = $scope.selectedTemplate.summary_fields.inventory.id ? $scope.selectedTemplate.summary_fields.inventory.id : null;
} else {
- $scope.workflow_inventory_sources[i].checked = 0;
+ $scope.inventory_name = null;
+ $scope.inventory = null;
}
- });
+ }
- };
+ if ($scope.selectedTemplate.ask_job_type_on_launch) {
+ $scope.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) {
+ $scope.limit = $scope.selectedTemplate.limit ? $scope.selectedTemplate.limit : null;
+ }
+
+ if ($scope.selectedTemplate.ask_skip_tags_on_launch) {
+ $scope.skip_tags = $scope.selectedTemplate.skip_tags ? $scope.selectedTemplate.skip_tags : null;
+ }
+
+ if ($scope.selectedTemplate.ask_tags_on_launch) {
+ $scope.job_tags = $scope.selectedTemplate.job_tags ? $scope.selectedTemplate.job_tags : null;
+ }
+
+ $scope.$broadcast('clearOtherTemplateLists', $scope.workflowMakerFormConfig.activeTab);
+ });
init();
diff --git a/awx/ui/client/src/shared/form-generator.js b/awx/ui/client/src/shared/form-generator.js
index 955a5d1e7e..d0cfb46a92 100644
--- a/awx/ui/client/src/shared/form-generator.js
+++ b/awx/ui/client/src/shared/form-generator.js
@@ -1274,7 +1274,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
if(this.mode === "edit"){
html += `
` +
+ `ng-class="{'is-selected': $state.is('${this.form.activeEditState}') || $state.is('${this.form.stateTree}.edit') || $state.$current.data.formChildState }">` +
`${details}
`;
for (itm in this.form.related) {
@@ -1372,8 +1372,8 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
html += "";//tabHolder
}
- if(!_.isEmpty(this.form.related) && this.mode === "edit"){
- html += `
diff --git a/awx/ui/client/src/shared/stateDefinitions.factory.js b/awx/ui/client/src/shared/stateDefinitions.factory.js
index 79170ac8bb..d3c5806698 100644
--- a/awx/ui/client/src/shared/stateDefinitions.factory.js
+++ b/awx/ui/client/src/shared/stateDefinitions.factory.js
@@ -372,7 +372,7 @@ export default ['$injector', '$stateExtender', '$log', function($injector, $stat
// a lookup field's basePath takes precedence over generic list definition's basePath, if supplied
data: {
basePath: field.basePath || null,
- lookup: true
+ formChildState: true
},
params: {
[field.sourceModel + '_search']: {
diff --git a/awx/ui/grunt-tasks/browserSync.js b/awx/ui/grunt-tasks/browserSync.js
index 107444ae0f..b4c9e179c6 100644
--- a/awx/ui/grunt-tasks/browserSync.js
+++ b/awx/ui/grunt-tasks/browserSync.js
@@ -17,7 +17,13 @@ module.exports = {
ws: true
},
keepalive: false,
- watchTask: true
+ watchTask: true,
+ // The browser-sync-client lib will write your current scroll position to window.name
+ // https://github.com/BrowserSync/browser-sync-client/blob/a2718faa91e11553feca7a3962313bf1ec6ba3e5/dist/index.js#L500
+ // This strategy is enabled in the core browser-sync lib, and not externally documented as an option. Yay!
+ // https://github.com/BrowserSync/browser-sync/blob/a522aaf12b6167d5591ed285eb3086f43a4d9ac2/lib/default-config.js#L312
+ scrollRestoreTechnique: null,
+ injectChanges: true
}
}
};