diff --git a/awx/ui/static/js/helpers/Groups.js b/awx/ui/static/js/helpers/Groups.js
index 20a1034dac..57c23472d5 100644
--- a/awx/ui/static/js/helpers/Groups.js
+++ b/awx/ui/static/js/helpers/Groups.js
@@ -789,6 +789,11 @@ function($compile, SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize, Sched
if (sources_scope.codeMirror) {
sources_scope.codeMirror.destroy();
}
+ $('#properties-tab').empty();
+ $('#sources-tab').empty();
+ $('#schedules-list').empty();
+ $('#schedules-form').empty();
+ $('#schedules-detail').empty();
$('#group-modal-dialog').hide();
$('#group-modal-dialog').dialog('destroy');
modal_scope.cancelModal();
@@ -1265,45 +1270,149 @@ function($compile, SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize, Sched
.factory('GroupsDelete', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
- 'Prompt', 'ProcessErrors', 'GetBasePath', 'Wait', 'BuildTree', 'Find',
+ 'Prompt', 'ProcessErrors', 'GetBasePath', 'Wait', 'BuildTree', 'Find', 'CreateDialog',
function ($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
- GetBasePath, Wait, BuildTree, Find) {
+ GetBasePath, Wait, BuildTree, Find, CreateDialog) {
return function (params) {
// Delete the selected group node. Disassociates it from its parent.
var scope = params.scope,
tree_id = params.tree_id,
- inventory_id = params.inventory_id,
node = Find({ list: scope.groups, key: 'id', val: tree_id }),
- url = GetBasePath('inventory') + inventory_id + '/groups/',
- action_to_take;
+ hosts = [],
+ groups = [],
+ childCount = 0,
+ buttonSet;
- action_to_take = function () {
- $('#prompt-modal').on('hidden.bs.modal', function () {
- Wait('start');
+ // action_to_take = function () {
+ // $('#prompt-modal').on('hidden.bs.modal', function () {
+ // Wait('start');
+ // });
+ // $('#prompt-modal').modal('hide');
+ // Rest.setUrl(url);
+ // Rest.post({ id: node.group_id, disassociate: 1 })
+ // .success(function () {
+ // $('#prompt-modal').modal('hide');
+ // scope.$emit('GroupDeleteCompleted'); // Signal a group refresh to start
+ // })
+ // .error(function (data, status) {
+ // Wait('stop');
+ // ProcessErrors(scope, data, status, null, {
+ // hdr: 'Error!',
+ // msg: 'Call to ' + url + ' failed. POST returned status: ' + status
+ // });
+ // });
+ // };
+
+ scope.deleteOption = "preserve-all";
+
+ buttonSet = [{
+ label: "Cancel",
+ onClick: function() {
+ scope.cancel();
+ },
+ icon: "fa-times",
+ "class": "btn btn-default",
+ "id": "group-delete-cancel-button"
+ },{
+ label: "Continue",
+ onClick: function() {
+ scope.performDelete();
+ },
+ icon: "fa-check",
+ "class": "btn btn-primary",
+ "id": "group-delete-ok-button"
+ }];
+
+ if (scope.removeDeleteDialogReady) {
+ scope.removeDeleteDialogReady();
+ }
+ scope.removeDeleteDialogReady = scope.$on('DeleteDialogReady', function() {
+ Wait('stop');
+ $('#group-delete-dialog').dialog('open');
+ });
+
+ if (scope.removeShowDeleteDialog) {
+ scope.removeShowDeleteDialog();
+ }
+ scope.removeShowDeleteDialog = scope.$on('ShowDeleteDialog', function() {
+ scope.group_name = node.name;
+ scope.groupsCount = groups.length;
+ scope.hostsCount = hosts.length;
+ CreateDialog({
+ id: 'group-delete-dialog',
+ scope: scope,
+ buttons: buttonSet,
+ width: 650,
+ height: 350,
+ minWidth: 500,
+ title: 'Delete Group',
+ callback: 'DeleteDialogReady'
});
- $('#prompt-modal').modal('hide');
- Rest.setUrl(url);
- Rest.post({ id: node.group_id, disassociate: 1 })
- .success(function () {
- $('#prompt-modal').modal('hide');
- scope.$emit('GroupDeleteCompleted'); // Signal a group refresh to start
+ });
+
+ if (scope.removeChildrenReady) {
+ scope.removeChildrenReady();
+ }
+ scope.removeChildrenReady = scope.$on('ChildrenReady', function() {
+ childCount++;
+ if (childCount === 2) {
+ scope.$emit('ShowDeleteDialog');
+ }
+ });
+
+ Wait('start');
+
+ if (node.related.children) {
+ Rest.setUrl(node.related.children);
+ Rest.get()
+ .success(function(data) {
+ if (data.count) {
+ data.results.forEach(function(group) {
+ groups.push(group);
+ });
+ }
+ scope.$emit('ChildrenReady');
})
- .error(function (data, status) {
- Wait('stop');
- ProcessErrors(scope, data, status, null, {
- hdr: 'Error!',
- msg: 'Call to ' + url + ' failed. POST returned status: ' + status
+ .error(function(data, status) {
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
+ msg: 'Failed to retrieve related groups. GET returned: ' + status
});
});
+ }
+ else {
+ scope.$emit('ChildrenReady');
+ }
+
+ if (node.related.all_hosts) {
+ Rest.setUrl(node.related.all_hosts);
+ Rest.get()
+ .success( function(data) {
+ if (data.count) {
+ data.results.forEach(function(host) {
+ hosts.push(host);
+ });
+ }
+ scope.$emit('ChildrenReady');
+ })
+ .error( function(data, status) {
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
+ msg: 'Failed to retrieve related hosts. GET returned: ' + status
+ });
+ });
+ }
+ else {
+ scope.$emit('ChildrenReady');
+ }
+
+ scope.cancel = function() {
+ $('#group-delete-dialog').dialog('close');
+ };
+
+ scope.performDelete = function() {
+ $('#group-delete-dialog').dialog('close');
};
- Prompt({
- hdr: 'Delete Group',
- body: '
Are you sure you want to delete group ' + node.name + '?
',
- action: action_to_take,
- 'class': 'btn-danger'
- });
};
}
])
diff --git a/awx/ui/static/js/helpers/Hosts.js b/awx/ui/static/js/helpers/Hosts.js
index 7fdb7127f6..3c33eaa566 100644
--- a/awx/ui/static/js/helpers/Hosts.js
+++ b/awx/ui/static/js/helpers/Hosts.js
@@ -498,28 +498,35 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
formId: 'host_form'
});
},
+ beforeDestroy: function() {
+ if (scope.codeMirror) {
+ scope.codeMirror.destroy();
+ }
+ $('#host-modal-dialog').empty();
+ },
onOpen: function() {
$('#host_name').focus();
- setTimeout(function() {
- TextareaResize({
- scope: scope,
- textareaId: 'host_variables',
- modalId: 'host-modal-dialog',
- formId: 'host_form'
- });
- }, 300);
- }
+ },
+ callback: 'HostEditDialogReady'
});
scope.parseType = 'yaml';
-
+
if (scope.hostVariablesLoadedRemove) {
scope.hostVariablesLoadedRemove();
}
scope.hostVariablesLoadedRemove = scope.$on('hostVariablesLoaded', function() {
- var callback = function() { Wait('stop'); };
$('#host-modal-dialog').dialog('open');
- ParseTypeChange({ scope: scope, field_id: 'host_variables', onReady: callback });
+ 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) {
diff --git a/awx/ui/static/js/helpers/refresh.js b/awx/ui/static/js/helpers/refresh.js
index 54339c5076..203e4bfe84 100644
--- a/awx/ui/static/js/helpers/refresh.js
+++ b/awx/ui/static/js/helpers/refresh.js
@@ -25,7 +25,8 @@ angular.module('RefreshHelper', ['RestServices', 'Utilities', 'PaginationHelpers
set = params.set,
iterator = params.iterator,
url = params.url;
-
+
+ scope[iterator + 'Loading'] = true;
scope.current_url = url;
Rest.setUrl(url);
Rest.get()
@@ -38,13 +39,12 @@ angular.module('RefreshHelper', ['RestServices', 'Utilities', 'PaginationHelpers
previous: data.previous,
iterator: iterator
});
- scope[iterator + 'Loading'] = false;
for (i = 1; i <= 3; i++) {
modifier = (i === 1) ? '' : i;
scope[iterator + 'HoldInput' + modifier] = false;
}
scope[set] = data.results;
- //window.scrollTo(0, 0);
+ scope[iterator + 'Loading'] = false;
Wait('stop');
scope.$emit('PostRefresh');
})
diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less
index fb17e9d192..5c8313bf8a 100644
--- a/awx/ui/static/less/ansible-ui.less
+++ b/awx/ui/static/less/ansible-ui.less
@@ -942,9 +942,9 @@ input[type="checkbox"].checkbox-no-label {
/* Table info rows */
.loading-info {
- color: @grey-txt;
- font-weight: bold;
- padding: 15px 0;
+ color: @grey-txt;
+ font-weight: normal;
+ padding: 15px 0;
}
/* Jobs pages */
diff --git a/awx/ui/static/lib/ansible/InventoryTree.js b/awx/ui/static/lib/ansible/InventoryTree.js
index ac9a8173e8..7da0fa6675 100644
--- a/awx/ui/static/lib/ansible/InventoryTree.js
+++ b/awx/ui/static/lib/ansible/InventoryTree.js
@@ -116,10 +116,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
event_level: level,
children: children,
ngicon: (sorted[i].children.length > 0) ? 'fa fa-minus-square-o node-toggle' : 'fa fa-square-o node-no-toggle',
- related: {
- children: (sorted[i].children.length > 0) ? sorted[i].related.children : '',
- inventory_source: sorted[i].related.inventory_source
- },
+ related: sorted[i].related,
status: sorted[i].summary_fields.inventory_source.status,
status_class: stat['class'],
status_tooltip: stat.tooltip,
diff --git a/awx/ui/static/lib/ansible/Modal.js b/awx/ui/static/lib/ansible/Modal.js
index 66f680e445..80eed2950e 100644
--- a/awx/ui/static/lib/ansible/Modal.js
+++ b/awx/ui/static/lib/ansible/Modal.js
@@ -26,6 +26,7 @@ angular.module('ModalDialog', ['Utilities', 'ParseHelper'])
* onResizeStop: - Function to call when user stops resizing the dialog, optional
* onClose: - Function to call after window closes, optional
* onOpen: - Function to call after window opens, optional
+ * beforeDestroy: - Function to call during onClose and prior to destroying the window
* callback: - String to pass to scope.$emit() after dialog is created, optional
* })
*
@@ -46,6 +47,7 @@ angular.module('ModalDialog', ['Utilities', 'ParseHelper'])
onClose = params.onClose,
onOpen = params.onOpen,
callback = params.callback,
+ beforeDestroy = params.beforeDestroy,
closeOnEscape = (params.closeOnEscape === undefined) ? false : params.closeOnEscape,
buttons,
id = params.id,
@@ -132,6 +134,9 @@ angular.module('ModalDialog', ['Utilities', 'ParseHelper'])
// remove lingering popover elements
$(this).remove();
});
+ if (beforeDestroy) {
+ beforeDestroy();
+ }
$('#' + id).dialog('destroy');
$('#' + id).hide();
if (onClose) {
@@ -161,6 +166,7 @@ angular.module('ModalDialog', ['Utilities', 'ParseHelper'])
* textareaId: - id attribute value of the textarea
* modalId: - id attribute of the
element used to create the modal
* formId: - id attribute of the textarea's parent form
+ * parse: - if true, call ParseTypeChange and replace textarea with codemirror editor
* })
*
* Use to resize a textarea field contained on a modal. Has only been tested where the
diff --git a/awx/ui/static/partials/inventory-edit.html b/awx/ui/static/partials/inventory-edit.html
index 1fa1b2205c..3737b77693 100644
--- a/awx/ui/static/partials/inventory-edit.html
+++ b/awx/ui/static/partials/inventory-edit.html
@@ -49,6 +49,59 @@
+
+
+
+
+
Deleting group {{ group_name }}.
+ This group has {{ groupsCount }} child groups and {{ hostsCount }} child hosts.
+ This group has {{ hostsCount }} child hosts.
+ This group has {{ groupsCount }} child groups.
+ Delete or preserve the group's children?
+
+
+
+
+
Delete group {{ group_name }}?
+
+
+
+
\ No newline at end of file