diff --git a/awx/ui/static/js/helpers/Groups.js b/awx/ui/static/js/helpers/Groups.js
index 1f68ff75ae..6e817d1a5c 100644
--- a/awx/ui/static/js/helpers/Groups.js
+++ b/awx/ui/static/js/helpers/Groups.js
@@ -738,7 +738,9 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
elem = document.getElementById('group-modal-dialog');
$compile(elem)(modal_scope);
+ var form_scope =
generator.inject(GroupForm, { mode: 'edit', id: 'properties-tab', breadCrumbs: false, related: false, scope: properties_scope });
+ var source_form_scope =
generator.inject(SourceForm, { mode: 'edit', id: 'sources-tab', breadCrumbs: false, related: false, scope: sources_scope });
//generator.reset();
@@ -881,6 +883,11 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
modal_scope.cancelModal();
},
open: function () {
+ function updateButtonStatus(isValid) {
+ $('.ui-dialog[aria-describedby="group-modal-dialog"]').find('.btn-primary').prop('disabled', !isValid);
+ }
+ form_scope.$watch('group_form.$valid', updateButtonStatus);
+ source_form_scope.$watch('source_form.$valid', updateButtonStatus);
$('#group_name').focus();
Wait('stop');
}
diff --git a/awx/ui/static/js/helpers/Hosts.js b/awx/ui/static/js/helpers/Hosts.js
index 280e398599..df9e045bf7 100644
--- a/awx/ui/static/js/helpers/Hosts.js
+++ b/awx/ui/static/js/helpers/Hosts.js
@@ -231,543 +231,545 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
};
}])
- .factory('InjectHosts', ['GenerateList', 'InventoryHosts', 'HostsReload',
- function(GenerateList, InventoryHosts, HostsReload) {
- return function(params) {
-
- var group_scope = params.group_scope,
- host_scope = params.host_scope,
- inventory_id = params.inventory_id,
- group_id = params.group_id,
- pageSize = params.pageSize,
- generator = GenerateList;
-
- // Inject the list html
- generator.inject(InventoryHosts, { scope: host_scope, mode: 'edit', id: 'hosts-container', breadCrumbs: false, searchSize: 'col-lg-6 col-md-6 col-sm-6' });
-
- // Load data
- HostsReload({ scope: host_scope, group_id: group_id, inventory_id: inventory_id, parent_scope: group_scope, pageSize: pageSize });
- };
- }])
-
- .factory('ToggleHostEnabled', [ 'GetBasePath', 'Rest', 'Wait', 'ProcessErrors', 'Alert', 'Find', 'SetEnabledMsg',
- function(GetBasePath, Rest, Wait, ProcessErrors, Alert, Find, SetEnabledMsg) {
- return function(params) {
-
- var id = params.host_id,
- external_source = params.external_source,
- parent_scope = params.parent_scope,
- host_scope = params.host_scope,
- host;
-
- function setMsg(host) {
- host.enabled = (host.enabled) ? false : true;
- host.enabled_flag = host.enabled;
- SetEnabledMsg(host);
- }
-
- if (!external_source) {
- // Host is not managed by an external source
- Wait('start');
- host = Find({ list: host_scope.hosts, key: 'id', val: id });
- setMsg(host);
-
- Rest.setUrl(GetBasePath('hosts') + id + '/');
- Rest.put(host)
- .success( function() {
- Wait('stop');
- })
- .error( function(data, status) {
- // Flip the enabled flag back
- setMsg(host);
- ProcessErrors(parent_scope, data, status, null,
- { hdr: 'Error!', msg: 'Failed to update host. PUT returned status: ' + status });
- });
- }
- else {
- Alert('Action Not Allowed', 'This host is managed by an external cloud source. Disable it at the external source, ' +
- 'then run an inventory sync to update Tower with the new status.', 'alert-info');
- }
- };
- }])
-
- .factory('HostsList', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostList', 'GenerateList',
- 'Prompt', 'SearchInit', 'PaginateInit', 'ProcessErrors', 'GetBasePath', 'HostsAdd', 'HostsReload', 'SelectionInit',
- function($rootScope, $location, $log, $routeParams, Rest, Alert, HostList, GenerateList, Prompt, SearchInit,
- PaginateInit, ProcessErrors, GetBasePath, HostsAdd, HostsReload, SelectionInit) {
- return function(params) {
-
- var inventory_id = params.inventory_id,
- group_id = params.group_id,
- list = HostList,
- generator = GenerateList,
- defaultUrl, scope;
-
- list.iterator = 'subhost'; //Override the iterator and name so the scope of the modal dialog
- list.name = 'subhosts'; //will not conflict with the parent scope
-
-
-
- scope = generator.inject(list, {
- id: 'form-modal-body',
- mode: 'select',
- breadCrumbs: false,
- selectButton: false
- });
-
- defaultUrl = GetBasePath('inventory') + inventory_id + '/hosts/?not__groups__id=' + scope.group_id;
-
- scope.formModalActionLabel = 'Select';
- scope.formModalHeader = 'Add Existing Hosts';
- scope.formModalCancelShow = true;
-
- SelectionInit({ scope: scope, list: list, url: GetBasePath('groups') + group_id + '/hosts/' });
-
- if (scope.removeModalClosed) {
- scope.removeModalClosed();
- }
- scope.removeModalClosed = scope.$on('modalClosed', function() {
- // if the modal closed, assume something got changed and reload the host list
- HostsReload(params);
- });
-
- $('.popover').popover('hide'); //remove any lingering pop-overs
- $('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success');
- $('#form-modal').modal({ backdrop: 'static', keyboard: false });
-
- SearchInit({ scope: scope, set: 'subhosts', list: list, url: defaultUrl });
- PaginateInit({ scope: scope, list: list, url: defaultUrl, mode: 'lookup' });
- scope.search(list.iterator);
-
- if (!scope.$$phase) {
- scope.$digest();
- }
-
- scope.createHost = function() {
- $('#form-modal').modal('hide');
- HostsAdd({ scope: params.scope, inventory_id: inventory_id, group_id: group_id });
- };
-
- };
- }])
-
-
- .factory('HostsCreate', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostForm', 'GenerateForm',
- 'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'ToJSON',
- function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, GenerateForm, Prompt, ProcessErrors,
- GetBasePath, HostsReload, ParseTypeChange, Wait, ToJSON) {
- return function(params) {
-
- var parent_scope = params.scope,
- inventory_id = parent_scope.inventory_id,
- group_id = parent_scope.selected_group_id,
- defaultUrl = GetBasePath('groups') + group_id + '/hosts/',
- form = HostForm,
- generator = GenerateForm,
- scope = generator.inject(form, {mode: 'add', modal: true, related: false}),
- master={};
-
- scope.formModalActionLabel = 'Save';
- scope.formModalHeader = 'Create New Host';
- scope.formModalCancelShow = true;
-
- scope.parseType = 'yaml';
- ParseTypeChange({ scope: scope, field_id: 'host_variables' });
-
- if (scope.removeHostsReload) {
- scope.removeHostsReload();
- }
- scope.removeHostsReload = scope.$on('hostsReload', function() {
- HostsReload(params);
- });
-
- $('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success');
- //$('#form-modal').unbind('hidden');
- //$('#form-modal').on('hidden', function () { scope.$emit('hostsReload'); });
-
- generator.reset();
- master={};
-
- if (!scope.$$phase) {
- scope.$digest();
- }
-
- if (scope.removeHostSaveComplete) {
- scope.removeHostSaveComplete();
- }
- scope.removeHostSaveComplete = scope.$on('HostSaveComplete', function() {
- Wait('stop');
- $('#form-modal').modal('hide');
-
- HostsReload({
- scope: parent_scope,
- group_id: parent_scope.selected_group_id,
- tree_id: parent_scope.selected_tree_id,
- inventory_id: parent_scope.inventory_id
- });
-
- //WatchInventoryWindowResize();
- });
-
- // Save
- scope.formModalAction = function() {
-
- Wait('start');
-
- var fld, data={};
- scope.formModalActionDisabled = true;
- data.variables = ToJSON(scope.parseType, scope.variables, true);
- for (fld in form.fields) {
- if (fld !== 'variables') {
- data[fld] = scope[fld];
- }
- }
- data.inventory = inventory_id;
-
- Rest.setUrl(defaultUrl);
- Rest.post(data)
- .success( function() {
- scope.$emit('HostSaveComplete');
- })
- .error( function(data, status) {
- Wait('stop');
- scope.formModalActionDisabled = false;
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to add new host. POST returned status: ' + status });
- });
- };
-
- // Cancel
- scope.formReset = function() {
- // Defaults
- generator.reset();
- };
-
- scope.cancelModal = function() {
- // WatchInventoryWindowResize();
- };
-
- };
- }])
-
-
- .factory('HostsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostForm', 'GenerateForm',
- 'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'Find', 'SetStatus', 'ApplyEllipsis',
- 'ToJSON', 'ParseVariableString', 'CreateDialog', 'TextareaResize',
- function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, GenerateForm, Prompt, ProcessErrors,
- GetBasePath, HostsReload, ParseTypeChange, Wait, Find, SetStatus, ApplyEllipsis, ToJSON,
- ParseVariableString, CreateDialog, TextareaResize) {
- return function(params) {
-
- var parent_scope = params.host_scope,
- group_scope = params.group_scope,
- host_id = params.host_id,
- inventory_id = params.inventory_id,
- mode = params.mode, // 'add' or 'edit'
- selected_group_id = params.selected_group_id,
- generator = GenerateForm,
- form = HostForm,
- defaultUrl,
- scope = parent_scope.$new(),
- master = {},
- relatedSets = {},
- buttons, url;
-
- generator.inject(HostForm, { mode: 'edit', id: 'host-modal-dialog', breadCrumbs: false, related: false, scope: scope });
- generator.reset();
-
- buttons = [{
- label: "Cancel",
- onClick: function() {
- scope.cancelModal();
- },
- icon: "fa-times",
- "class": "btn btn-default",
- "id": "host-cancel-button"
- },{
- label: "Save",
- onClick: function() {
- scope.saveModal();
- },
- icon: "fa-check",
- "class": "btn btn-primary",
- "id": "host-save-button"
- }];
-
- CreateDialog({
- scope: scope,
- buttons: buttons,
- width: 675,
- height: 750,
- minWidth: 400,
- title: 'Host Properties',
- id: 'host-modal-dialog',
- clonseOnEscape: false,
- onClose: function() {
- Wait('stop');
- scope.codeMirror.destroy();
- $('#host-modal-dialog').empty();
- },
- onResizeStop: function() {
- TextareaResize({
- scope: scope,
- textareaId: 'host_variables',
- modalId: 'host-modal-dialog',
- formId: 'host_form'
- });
- },
- beforeDestroy: function() {
- if (scope.codeMirror) {
- scope.codeMirror.destroy();
- }
- $('#host-modal-dialog').empty();
- },
- onOpen: function() {
- $('#host_name').focus();
- },
- callback: 'HostEditDialogReady'
- });
-
- scope.parseType = 'yaml';
-
- if (scope.hostVariablesLoadedRemove) {
- scope.hostVariablesLoadedRemove();
- }
- scope.hostVariablesLoadedRemove = scope.$on('hostVariablesLoaded', function() {
- $('#host-modal-dialog').dialog('open');
- setTimeout(function() {
- TextareaResize({
- scope: scope,
- textareaId: 'host_variables',
- modalId: 'host-modal-dialog',
- formId: 'host_form',
- parse: true
- });
- }, 300);
- //ParseTypeChange({ scope: scope, field_id: 'host_variables', onReady: callback });
- });
-
- if (scope.hostLoadedRemove) {
- scope.hostLoadedRemove();
- }
- scope.hostLoadedRemove = scope.$on('hostLoaded', function() {
- // Retrieve host variables
- if (scope.variable_url) {
- Rest.setUrl(scope.variable_url);
- Rest.get()
- .success( function(data) {
- scope.variables = ParseVariableString(data);
- scope.$emit('hostVariablesLoaded');
- })
- .error( function(data, status) {
- scope.variables = null;
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to retrieve host variables. GET returned status: ' + status });
- });
- }
- else {
- scope.variables = "---";
- scope.$emit('hostVariablesLoaded');
- }
- master.variables = scope.variables;
- });
-
- Wait('start');
-
- // Retrieve detail record and prepopulate the form
- if (mode === 'edit') {
- defaultUrl = GetBasePath('hosts') + host_id + '/';
- Rest.setUrl(defaultUrl);
- Rest.get()
- .success( function(data) {
- var set, fld, related;
- for (fld in form.fields) {
- if (data[fld]) {
- scope[fld] = data[fld];
- master[fld] = scope[fld];
- }
- }
- related = data.related;
- for (set in form.related) {
- if (related[set]) {
- relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
- }
- }
- scope.variable_url = data.related.variable_data;
- scope.has_inventory_sources = data.has_inventory_sources;
- scope.$emit('hostLoaded');
- })
- .error( function(data, status) {
- ProcessErrors(parent_scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to retrieve host: ' + host_id + '. GET returned status: ' + status });
- });
- }
- else {
- // Add mode
- url = GetBasePath('groups') + selected_group_id + '/';
- Rest.setUrl(url);
- Rest.get()
- .success( function(data) {
- scope.has_inventory_sources = data.has_inventory_sources;
- scope.enabled = true;
- scope.variables = '---';
- defaultUrl = data.related.hosts;
- scope.$emit('hostVariablesLoaded');
- })
- .error( function(data, status) {
- ProcessErrors(parent_scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to retrieve group: ' + selected_group_id + '. GET returned status: ' + status });
- });
- }
-
- if (scope.removeSaveCompleted) {
- scope.removeSaveCompleted();
- }
- scope.removeSaveCompleted = scope.$on('saveCompleted', function() {
- try {
- $('#host-modal-dialog').dialog('close');
- }
- catch(err) {
- // ignore
- }
- if (group_scope && group_scope.refreshHosts) {
- group_scope.refreshHosts();
- }
- if (parent_scope.refreshHosts) {
- parent_scope.refreshHosts();
- }
- scope.$destroy();
- });
-
- // Save changes to the parent
- scope.saveModal = function() {
-
- Wait('start');
- var fld, data={};
-
- try {
- data.variables = ToJSON(scope.parseType, scope.variables, true);
- for (fld in form.fields) {
- data[fld] = scope[fld];
- }
- data.inventory = inventory_id;
- Rest.setUrl(defaultUrl);
- if (mode === 'edit') {
- Rest.put(data)
- .success( function() {
- scope.$emit('saveCompleted');
- })
- .error( function(data, status) {
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to update host: ' + host_id + '. PUT returned status: ' + status });
- });
- }
- else {
- Rest.post(data)
- .success( function() {
- scope.$emit('saveCompleted');
- })
- .error( function(data, status) {
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to create host. POST returned status: ' + status });
- });
- }
- }
- catch(e) {
- // ignore. ToJSON will have already alerted the user
- }
- };
-
- // Cancel
- scope.formReset = function() {
- generator.reset();
- for (var fld in master) {
- scope[fld] = master[fld];
- }
- scope.parseType = 'yaml';
- };
-
- scope.cancelModal = function() {
- try {
- $('#host-modal-dialog').dialog('close');
- }
- catch(err) {
- // ignore
- }
- scope.$destroy();
- };
-
- };
- }])
-
-
- .factory('HostsDelete', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'Wait',
- function($rootScope, $location, $log, $routeParams, Rest, Alert, Prompt, ProcessErrors, GetBasePath, HostsReload, Wait) {
- return function(params) {
- // Remove the selected host from the current group by disassociating
-
- var action_to_take, body,
- scope = params.parent_scope,
- host_id = params.host_id,
- host_name = params.host_name,
- group,
- url_list = [];
-
- if (scope.selected_group_id) {
- //group = Find({ list: parent_scope.groups, key: 'id', val: parent_scope.selected_group_id });
- //getChildren(group.id);
- url_list.push(GetBasePath('groups') + scope.selected_group_id + '/hosts/');
- }
- else {
- url_list.push(GetBasePath('inventory') + scope.inventory.id + '/hosts/');
- }
-
- if (scope.removeHostsReload) {
- scope.removeHostsReload();
- }
- scope.removeHostsReload = scope.$on('hostsReload', function() {
- $('#prompt-modal').modal('hide');
- scope.refreshHosts();
- });
-
- $('#prompt-modal').on('hidden.bs.modal', function(){ Wait('stop'); });
-
- action_to_take = function() {
- var count=0, i;
-
- Wait('start');
-
- if (scope.removeHostRemoved) {
- scope.removeHostRemoved();
- }
- scope.removeHostRemoved = scope.$on('hostRemoved', function(){
- count++;
- if (count === url_list.length) {
- Wait('start');
- scope.$emit('hostsReload');
- }
- });
-
- for(i=0; i < url_list.length; i++) {
- Rest.setUrl(url_list[i]);
- Rest.post({ id: host_id, disassociate: 1 })
- .success( function() {
- scope.$emit('hostRemoved');
- })
- .error( function(data, status) {
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Attempt to delete ' + host_name + ' failed. DELETE returned status: ' + status });
- });
- }
- };
-
- body = (group) ? '
Are you sure you want to remove host ' + host_name + ' from group ' + group.name + '?' +
- ' It will still be part of the inventory and available in All Hosts.
' :
- 'Are you sure you want to permanently delete host ' + host_name + ' from the inventory?
';
- Prompt({ hdr: 'Delete Host', body: body, action: action_to_take, 'class': 'btn-danger' });
-
- };
- }])
+.factory('InjectHosts', ['GenerateList', 'InventoryHosts', 'HostsReload',
+ function(GenerateList, InventoryHosts, HostsReload) {
+ return function(params) {
+
+ var group_scope = params.group_scope,
+ host_scope = params.host_scope,
+ inventory_id = params.inventory_id,
+ group_id = params.group_id,
+ pageSize = params.pageSize,
+ generator = GenerateList;
+
+ // Inject the list html
+ generator.inject(InventoryHosts, { scope: host_scope, mode: 'edit', id: 'hosts-container', breadCrumbs: false, searchSize: 'col-lg-6 col-md-6 col-sm-6' });
+
+ // Load data
+ HostsReload({ scope: host_scope, group_id: group_id, inventory_id: inventory_id, parent_scope: group_scope, pageSize: pageSize });
+ };
+ }])
+
+.factory('ToggleHostEnabled', [ 'GetBasePath', 'Rest', 'Wait', 'ProcessErrors', 'Alert', 'Find', 'SetEnabledMsg',
+ function(GetBasePath, Rest, Wait, ProcessErrors, Alert, Find, SetEnabledMsg) {
+ return function(params) {
+
+ var id = params.host_id,
+ external_source = params.external_source,
+ parent_scope = params.parent_scope,
+ host_scope = params.host_scope,
+ host;
+
+ function setMsg(host) {
+ host.enabled = (host.enabled) ? false : true;
+ host.enabled_flag = host.enabled;
+ SetEnabledMsg(host);
+ }
+
+ if (!external_source) {
+ // Host is not managed by an external source
+ Wait('start');
+ host = Find({ list: host_scope.hosts, key: 'id', val: id });
+ setMsg(host);
+
+ Rest.setUrl(GetBasePath('hosts') + id + '/');
+ Rest.put(host)
+ .success( function() {
+ Wait('stop');
+ })
+ .error( function(data, status) {
+ // Flip the enabled flag back
+ setMsg(host);
+ ProcessErrors(parent_scope, data, status, null,
+ { hdr: 'Error!', msg: 'Failed to update host. PUT returned status: ' + status });
+ });
+ }
+ else {
+ Alert('Action Not Allowed', 'This host is managed by an external cloud source. Disable it at the external source, ' +
+ 'then run an inventory sync to update Tower with the new status.', 'alert-info');
+ }
+ };
+ }])
+
+.factory('HostsList', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostList', 'GenerateList',
+ 'Prompt', 'SearchInit', 'PaginateInit', 'ProcessErrors', 'GetBasePath', 'HostsAdd', 'HostsReload', 'SelectionInit',
+ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostList, GenerateList, Prompt, SearchInit,
+ PaginateInit, ProcessErrors, GetBasePath, HostsAdd, HostsReload, SelectionInit) {
+ return function(params) {
+
+ var inventory_id = params.inventory_id,
+ group_id = params.group_id,
+ list = HostList,
+ generator = GenerateList,
+ defaultUrl, scope;
+
+ list.iterator = 'subhost'; //Override the iterator and name so the scope of the modal dialog
+ list.name = 'subhosts'; //will not conflict with the parent scope
+
+
+
+ scope = generator.inject(list, {
+ id: 'form-modal-body',
+ mode: 'select',
+ breadCrumbs: false,
+ selectButton: false
+ });
+
+ defaultUrl = GetBasePath('inventory') + inventory_id + '/hosts/?not__groups__id=' + scope.group_id;
+
+ scope.formModalActionLabel = 'Select';
+ scope.formModalHeader = 'Add Existing Hosts';
+ scope.formModalCancelShow = true;
+
+ SelectionInit({ scope: scope, list: list, url: GetBasePath('groups') + group_id + '/hosts/' });
+
+ if (scope.removeModalClosed) {
+ scope.removeModalClosed();
+ }
+ scope.removeModalClosed = scope.$on('modalClosed', function() {
+ // if the modal closed, assume something got changed and reload the host list
+ HostsReload(params);
+ });
+
+ $('.popover').popover('hide'); //remove any lingering pop-overs
+ $('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success');
+ $('#form-modal').modal({ backdrop: 'static', keyboard: false });
+
+ SearchInit({ scope: scope, set: 'subhosts', list: list, url: defaultUrl });
+ PaginateInit({ scope: scope, list: list, url: defaultUrl, mode: 'lookup' });
+ scope.search(list.iterator);
+
+ if (!scope.$$phase) {
+ scope.$digest();
+ }
+
+ scope.createHost = function() {
+ $('#form-modal').modal('hide');
+ HostsAdd({ scope: params.scope, inventory_id: inventory_id, group_id: group_id });
+ };
+
+ };
+ }])
+
+
+.factory('HostsCreate', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostForm', 'GenerateForm',
+ 'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'ToJSON',
+ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, GenerateForm, Prompt, ProcessErrors,
+ GetBasePath, HostsReload, ParseTypeChange, Wait, ToJSON) {
+ return function(params) {
+
+ var parent_scope = params.scope,
+ inventory_id = parent_scope.inventory_id,
+ group_id = parent_scope.selected_group_id,
+ defaultUrl = GetBasePath('groups') + group_id + '/hosts/',
+ form = HostForm,
+ generator = GenerateForm,
+ scope = generator.inject(form, {mode: 'add', modal: true, related: false}),
+ master={};
+
+ scope.formModalActionLabel = 'Save';
+ scope.formModalHeader = 'Create New Host';
+ scope.formModalCancelShow = true;
+
+ scope.parseType = 'yaml';
+ ParseTypeChange({ scope: scope, field_id: 'host_variables' });
+
+ if (scope.removeHostsReload) {
+ scope.removeHostsReload();
+ }
+ scope.removeHostsReload = scope.$on('hostsReload', function() {
+ HostsReload(params);
+ });
+
+ $('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success');
+ //$('#form-modal').unbind('hidden');
+ //$('#form-modal').on('hidden', function () { scope.$emit('hostsReload'); });
+
+ generator.reset();
+ master={};
+
+ if (!scope.$$phase) {
+ scope.$digest();
+ }
+
+ if (scope.removeHostSaveComplete) {
+ scope.removeHostSaveComplete();
+ }
+ scope.removeHostSaveComplete = scope.$on('HostSaveComplete', function() {
+ Wait('stop');
+ $('#form-modal').modal('hide');
+
+ HostsReload({
+ scope: parent_scope,
+ group_id: parent_scope.selected_group_id,
+ tree_id: parent_scope.selected_tree_id,
+ inventory_id: parent_scope.inventory_id
+ });
+
+ //WatchInventoryWindowResize();
+ });
+
+ // Save
+ scope.formModalAction = function() {
+
+ Wait('start');
+
+ var fld, data={};
+ scope.formModalActionDisabled = true;
+ data.variables = ToJSON(scope.parseType, scope.variables, true);
+ for (fld in form.fields) {
+ if (fld !== 'variables') {
+ data[fld] = scope[fld];
+ }
+ }
+ data.inventory = inventory_id;
+
+ Rest.setUrl(defaultUrl);
+ Rest.post(data)
+ .success( function() {
+ scope.$emit('HostSaveComplete');
+ })
+ .error( function(data, status) {
+ Wait('stop');
+ scope.formModalActionDisabled = false;
+ ProcessErrors(scope, data, status, form,
+ { hdr: 'Error!', msg: 'Failed to add new host. POST returned status: ' + status });
+ });
+ };
+
+ // Cancel
+ scope.formReset = function() {
+ // Defaults
+ generator.reset();
+ };
+
+ scope.cancelModal = function() {
+ // WatchInventoryWindowResize();
+ };
+
+ };
+ }])
+
+
+.factory('HostsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostForm', 'GenerateForm',
+ 'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'Find', 'SetStatus', 'ApplyEllipsis',
+ 'ToJSON', 'ParseVariableString', 'CreateDialog', 'TextareaResize',
+ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, GenerateForm, Prompt, ProcessErrors,
+ GetBasePath, HostsReload, ParseTypeChange, Wait, Find, SetStatus, ApplyEllipsis, ToJSON,
+ ParseVariableString, CreateDialog, TextareaResize) {
+ return function(params) {
+
+ var parent_scope = params.host_scope,
+ group_scope = params.group_scope,
+ host_id = params.host_id,
+ inventory_id = params.inventory_id,
+ mode = params.mode, // 'add' or 'edit'
+ selected_group_id = params.selected_group_id,
+ generator = GenerateForm,
+ form = HostForm,
+ defaultUrl,
+ scope = parent_scope.$new(),
+ master = {},
+ relatedSets = {},
+ buttons, url, form_scope;
+
+ var form_scope =
+ generator.inject(HostForm, { mode: 'edit', id: 'host-modal-dialog', breadCrumbs: false, related: false, scope: scope });
+ generator.reset();
+
+ buttons = [{
+ label: "Cancel",
+ onClick: function() {
+ scope.cancelModal();
+ },
+ icon: "fa-times",
+ "class": "btn btn-default",
+ "id": "host-cancel-button"
+ },{
+ label: "Save",
+ onClick: function() {
+ scope.saveModal();
+ },
+ icon: "fa-check",
+ "class": "btn btn-primary",
+ "id": "host-save-button"
+ }];
+
+ CreateDialog({
+ scope: scope,
+ buttons: buttons,
+ width: 675,
+ height: 750,
+ minWidth: 400,
+ title: 'Host Properties',
+ id: 'host-modal-dialog',
+ clonseOnEscape: false,
+ form: form_scope.host_form,
+ onClose: function() {
+ Wait('stop');
+ scope.codeMirror.destroy();
+ $('#host-modal-dialog').empty();
+ },
+ onResizeStop: function() {
+ TextareaResize({
+ scope: scope,
+ textareaId: 'host_variables',
+ modalId: 'host-modal-dialog',
+ formId: 'host_form'
+ });
+ },
+ beforeDestroy: function() {
+ if (scope.codeMirror) {
+ scope.codeMirror.destroy();
+ }
+ $('#host-modal-dialog').empty();
+ },
+ onOpen: function() {
+ $('#host_name').focus();
+ },
+ callback: 'HostEditDialogReady'
+ });
+
+ scope.parseType = 'yaml';
+
+ if (scope.hostVariablesLoadedRemove) {
+ scope.hostVariablesLoadedRemove();
+ }
+ scope.hostVariablesLoadedRemove = scope.$on('hostVariablesLoaded', function() {
+ $('#host-modal-dialog').dialog('open');
+ setTimeout(function() {
+ TextareaResize({
+ scope: scope,
+ textareaId: 'host_variables',
+ modalId: 'host-modal-dialog',
+ formId: 'host_form',
+ parse: true
+ });
+ }, 300);
+ //ParseTypeChange({ scope: scope, field_id: 'host_variables', onReady: callback });
+ });
+
+ if (scope.hostLoadedRemove) {
+ scope.hostLoadedRemove();
+ }
+ scope.hostLoadedRemove = scope.$on('hostLoaded', function() {
+ // Retrieve host variables
+ if (scope.variable_url) {
+ Rest.setUrl(scope.variable_url);
+ Rest.get()
+ .success( function(data) {
+ scope.variables = ParseVariableString(data);
+ scope.$emit('hostVariablesLoaded');
+ })
+ .error( function(data, status) {
+ scope.variables = null;
+ ProcessErrors(scope, data, status, form,
+ { hdr: 'Error!', msg: 'Failed to retrieve host variables. GET returned status: ' + status });
+ });
+ }
+ else {
+ scope.variables = "---";
+ scope.$emit('hostVariablesLoaded');
+ }
+ master.variables = scope.variables;
+ });
+
+ Wait('start');
+
+ // Retrieve detail record and prepopulate the form
+ if (mode === 'edit') {
+ defaultUrl = GetBasePath('hosts') + host_id + '/';
+ Rest.setUrl(defaultUrl);
+ Rest.get()
+ .success( function(data) {
+ var set, fld, related;
+ for (fld in form.fields) {
+ if (data[fld]) {
+ scope[fld] = data[fld];
+ master[fld] = scope[fld];
+ }
+ }
+ related = data.related;
+ for (set in form.related) {
+ if (related[set]) {
+ relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
+ }
+ }
+ scope.variable_url = data.related.variable_data;
+ scope.has_inventory_sources = data.has_inventory_sources;
+ scope.$emit('hostLoaded');
+ })
+ .error( function(data, status) {
+ ProcessErrors(parent_scope, data, status, form,
+ { hdr: 'Error!', msg: 'Failed to retrieve host: ' + host_id + '. GET returned status: ' + status });
+ });
+ }
+ else {
+ // Add mode
+ url = GetBasePath('groups') + selected_group_id + '/';
+ Rest.setUrl(url);
+ Rest.get()
+ .success( function(data) {
+ scope.has_inventory_sources = data.has_inventory_sources;
+ scope.enabled = true;
+ scope.variables = '---';
+ defaultUrl = data.related.hosts;
+ scope.$emit('hostVariablesLoaded');
+ })
+ .error( function(data, status) {
+ ProcessErrors(parent_scope, data, status, form,
+ { hdr: 'Error!', msg: 'Failed to retrieve group: ' + selected_group_id + '. GET returned status: ' + status });
+ });
+ }
+
+ if (scope.removeSaveCompleted) {
+ scope.removeSaveCompleted();
+ }
+ scope.removeSaveCompleted = scope.$on('saveCompleted', function() {
+ try {
+ $('#host-modal-dialog').dialog('close');
+ }
+ catch(err) {
+ // ignore
+ }
+ if (group_scope && group_scope.refreshHosts) {
+ group_scope.refreshHosts();
+ }
+ if (parent_scope.refreshHosts) {
+ parent_scope.refreshHosts();
+ }
+ scope.$destroy();
+ });
+
+ // Save changes to the parent
+ scope.saveModal = function() {
+
+ Wait('start');
+ var fld, data={};
+
+ try {
+ data.variables = ToJSON(scope.parseType, scope.variables, true);
+ for (fld in form.fields) {
+ data[fld] = scope[fld];
+ }
+ data.inventory = inventory_id;
+ Rest.setUrl(defaultUrl);
+ if (mode === 'edit') {
+ Rest.put(data)
+ .success( function() {
+ scope.$emit('saveCompleted');
+ })
+ .error( function(data, status) {
+ ProcessErrors(scope, data, status, form,
+ { hdr: 'Error!', msg: 'Failed to update host: ' + host_id + '. PUT returned status: ' + status });
+ });
+ }
+ else {
+ Rest.post(data)
+ .success( function() {
+ scope.$emit('saveCompleted');
+ })
+ .error( function(data, status) {
+ ProcessErrors(scope, data, status, form,
+ { hdr: 'Error!', msg: 'Failed to create host. POST returned status: ' + status });
+ });
+ }
+ }
+ catch(e) {
+ // ignore. ToJSON will have already alerted the user
+ }
+ };
+
+ // Cancel
+ scope.formReset = function() {
+ generator.reset();
+ for (var fld in master) {
+ scope[fld] = master[fld];
+ }
+ scope.parseType = 'yaml';
+ };
+
+ scope.cancelModal = function() {
+ try {
+ $('#host-modal-dialog').dialog('close');
+ }
+ catch(err) {
+ // ignore
+ }
+ scope.$destroy();
+ };
+
+ };
+ }])
+
+
+.factory('HostsDelete', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'Wait',
+ function($rootScope, $location, $log, $routeParams, Rest, Alert, Prompt, ProcessErrors, GetBasePath, HostsReload, Wait) {
+ return function(params) {
+ // Remove the selected host from the current group by disassociating
+
+ var action_to_take, body,
+ scope = params.parent_scope,
+ host_id = params.host_id,
+ host_name = params.host_name,
+ group,
+ url_list = [];
+
+ if (scope.selected_group_id) {
+ //group = Find({ list: parent_scope.groups, key: 'id', val: parent_scope.selected_group_id });
+ //getChildren(group.id);
+ url_list.push(GetBasePath('groups') + scope.selected_group_id + '/hosts/');
+ }
+ else {
+ url_list.push(GetBasePath('inventory') + scope.inventory.id + '/hosts/');
+ }
+
+ if (scope.removeHostsReload) {
+ scope.removeHostsReload();
+ }
+ scope.removeHostsReload = scope.$on('hostsReload', function() {
+ $('#prompt-modal').modal('hide');
+ scope.refreshHosts();
+ });
+
+ $('#prompt-modal').on('hidden.bs.modal', function(){ Wait('stop'); });
+
+ action_to_take = function() {
+ var count=0, i;
+
+ Wait('start');
+
+ if (scope.removeHostRemoved) {
+ scope.removeHostRemoved();
+ }
+ scope.removeHostRemoved = scope.$on('hostRemoved', function(){
+ count++;
+ if (count === url_list.length) {
+ Wait('start');
+ scope.$emit('hostsReload');
+ }
+ });
+
+ for(i=0; i < url_list.length; i++) {
+ Rest.setUrl(url_list[i]);
+ Rest.post({ id: host_id, disassociate: 1 })
+ .success( function() {
+ scope.$emit('hostRemoved');
+ })
+ .error( function(data, status) {
+ ProcessErrors(scope, data, status, null,
+ { hdr: 'Error!', msg: 'Attempt to delete ' + host_name + ' failed. DELETE returned status: ' + status });
+ });
+ }
+ };
+
+ body = (group) ? 'Are you sure you want to remove host ' + host_name + ' from group ' + group.name + '?' +
+ ' It will still be part of the inventory and available in All Hosts.
' :
+ 'Are you sure you want to permanently delete host ' + host_name + ' from the inventory?
';
+ Prompt({ hdr: 'Delete Host', body: body, action: action_to_take, 'class': 'btn-danger' });
+
+ };
+ }])
.factory('HostsCopy', ['$compile', 'Rest', 'ProcessErrors', 'CreateDialog', 'GetBasePath', 'Wait', 'GenerateList', 'GroupList', 'SearchInit',
'PaginateInit',
diff --git a/awx/ui/static/js/helpers/inventory.js b/awx/ui/static/js/helpers/inventory.js
index 67ca22c3e1..f6c44525fc 100644
--- a/awx/ui/static/js/helpers/inventory.js
+++ b/awx/ui/static/js/helpers/inventory.js
@@ -201,15 +201,16 @@ export default
form.well = false;
- generator.inject(form, {
- mode: 'edit',
- showButtons: false,
- showActions: false,
- id: 'inventory-edit-modal-dialog',
- breadCrumbs: false,
- related: false,
- scope: scope
- });
+ var form_scope =
+ generator.inject(form, {
+ mode: 'edit',
+ showButtons: false,
+ showActions: false,
+ id: 'inventory-edit-modal-dialog',
+ breadCrumbs: false,
+ related: false,
+ scope: scope
+ });
/* Reset form properties. Otherwise it screws up future requests of the Inventories detail page */
form.well = true;
@@ -241,6 +242,7 @@ export default
title: 'Inventory Properties',
id: 'inventory-edit-modal-dialog',
clonseOnEscape: false,
+ form: form_scope.inventory_form,
onClose: function() {
Wait('stop');
scope.codeMirror.destroy();
diff --git a/awx/ui/static/lib/ansible/Modal.js b/awx/ui/static/lib/ansible/Modal.js
index 8754d989c0..c34ef22971 100644
--- a/awx/ui/static/lib/ansible/Modal.js
+++ b/awx/ui/static/lib/ansible/Modal.js
@@ -57,10 +57,15 @@ angular.module('ModalDialog', ['Utilities', 'ParseHelper'])
beforeDestroy = params.beforeDestroy,
closeOnEscape = (params.closeOnEscape === undefined) ? false : params.closeOnEscape,
resizable = (params.resizable === undefined) ? true : params.resizable,
+ forms = _.chain([params.form]).flatten().compact().value(),
buttons,
id = params.id,
x, y, wh, ww;
+ function updateButtonStatus(isValid) {
+ $('.ui-dialog[aria-describedby="' + id + '"]').find('.btn-primary').prop('disabled', !isValid);
+ }
+
if (Empty(buttonSet)) {
// Default button object
buttonSet = [{
@@ -115,6 +120,12 @@ angular.module('ModalDialog', ['Utilities', 'ParseHelper'])
});
}, 300);
+ if (forms.length > 0) {
+ forms.map(function(form_ctrl) {
+ scope.$watch(form_ctrl.$name + '.$valid', updateButtonStatus);
+ });
+ }
+
setTimeout(function() {
scope.$apply(function() {
scope.$emit(callback);
@@ -226,4 +237,4 @@ angular.module('ModalDialog', ['Utilities', 'ParseHelper'])
ParseTypeChange({ scope: scope, field_id: textareaId, onReady: waitStop, variable: fld, onChange: onChange });
}
};
- }]);
\ No newline at end of file
+ }]);