diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js index a112b87717..916a01650e 100644 --- a/awx/ui/static/js/controllers/Inventories.js +++ b/awx/ui/static/js/controllers/Inventories.js @@ -350,6 +350,9 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis if ($scope.groups.length > 0) { $scope.selected_tree_id = $scope.groups[0].id; $scope.selected_group_id = $scope.groups[0].group_id; + $scope.groups[0].selected_class = 'selected'; + $scope.groups[0].active_class = 'active-row'; + $scope.selected_group_name = $scope.groups[0].name; } else { $scope.selected_tree_id = null; @@ -357,9 +360,9 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis } // Add hosts view + $scope.show_failures = false; InjectHosts({ scope: $scope, inventory_id: $scope.inventory_id, tree_id: $scope.selected_tree_id, group_id: $scope.selected_group_id }); - Wait('stop'); }); if ($scope.removeGroupTreeRefreshed) { @@ -379,11 +382,25 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: true }); }); - $scope.showHosts = function(tree_id, group_id) { + $scope.showHosts = function(tree_id, group_id, show_failures) { // Clicked on group if (tree_id !== null) { + Wait('start'); $scope.selected_tree_id = tree_id; $scope.selected_group_id = group_id; + $scope.hosts = []; + $scope.show_failures = show_failures; // turn on failed hosts filter in hosts view + for (var i=0; i < $scope.groups.length; i++) { + if ($scope.groups[i].id == tree_id) { + $scope.groups[i].selected_class = 'selected'; + $scope.groups[i].active_class = 'active-row'; + $scope.selected_group_name = $scope.groups[i].name; + } + else { + $scope.groups[i].selected_class = ''; + $scope.groups[i].active_class = ''; + } + } HostsReload({ scope: $scope, group_id: group_id, tree_id: tree_id, inventory_id: $scope.inventory_id }); } } diff --git a/awx/ui/static/js/helpers/Groups.js b/awx/ui/static/js/helpers/Groups.js index 14e3dcba85..e8d850c7a9 100644 --- a/awx/ui/static/js/helpers/Groups.js +++ b/awx/ui/static/js/helpers/Groups.js @@ -137,41 +137,37 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' var inventory_id = params.inventory_id; var group_id = params.group_id; - var tip, link, html_class; + var tip, failures, html_class; // Return values for use on host status indicator if (active_failures > 0) { tip = "Contains " + active_failures + - [ (active_failures == 1) ? ' host' : ' hosts' ] + ' with failed jobs. Click to view the offending ' + + [ (active_failures == 1) ? ' host' : ' hosts' ] + ' with failed jobs.' + [ (active_failures == 1) ? ' host' : ' hosts' ] + '.'; - link = '/#/inventories/' + inventory_id + '/hosts?group=' + group_id + '&has_active_failures=true'; html_class = 'true'; + failures = true; } else { + failures = false; if (total_hosts == 0) { // no hosts - tip = "There are no hosts in this group. It's a sad empty shell. Click to view the hosts page and add a host."; - link = '/#/inventories/' + inventory_id + '/hosts/?group=' + group_id; + tip = "There are no hosts in this group."; html_class = 'na'; } else if (total_hosts == 1) { // on host with 0 failures - tip = "The 1 host in this group is happy! It does not have a job failure. " + - " Click to view the host."; - link = '/#/inventories/' + inventory_id + '/hosts/?group=' + group_id; + tip = "The host in this group does not have a recent job failure."; html_class = 'false'; } else { // many hosts with 0 failures - tip = "All " + total_hosts + " hosts in this group are happy! None of them have " + - " a recent job failure. Click to view the hosts."; - link = '/#/inventories/' + inventory_id + '/hosts/?group=' + group_id; + tip = "None of the " + total_hosts + " hosts in this group have a recent job failure."; html_class = 'false'; } } - return { tooltip: tip, url: link, 'class': html_class }; + return { tooltip: tip, failures: failures, 'class': html_class }; } }]) diff --git a/awx/ui/static/js/helpers/Hosts.js b/awx/ui/static/js/helpers/Hosts.js index fb24216f7c..6a2905f71d 100644 --- a/awx/ui/static/js/helpers/Hosts.js +++ b/awx/ui/static/js/helpers/Hosts.js @@ -26,12 +26,6 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H var url = ( !Empty(group_id) ) ? GetBasePath('groups') + group_id + '/all_hosts/' : GetBasePath('inventory') + inventory_id + '/hosts/'; - for (var i=0; i < scope.groups.length; i++) { - scope.groups[i].selected_class = (scope.groups[i].id == tree_id) ? 'selected' : ''; - if (scope.groups[i].id == tree_id) { - scope.selected_group_name = scope.groups[i].name; - } - } scope.search_place_holder='Search ' + scope.selected_group_name; SearchInit({ scope: scope, set: 'hosts', list: InventoryHosts, url: url }); @@ -50,7 +44,7 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H var tree_id = params.tree_id; var generator = GenerateList; - generator.inject(InventoryHosts, { mode: 'edit', id: 'hosts-container', breadCrumbs: false, searchSize: 'col-lg-6 col-md-6 col-sm-6' }); + generator.inject(InventoryHosts, { scope: scope, mode: 'edit', id: 'hosts-container', breadCrumbs: false, searchSize: 'col-lg-6 col-md-6 col-sm-6' }); HostsReload({ scope: scope, group_id: group_id, tree_id: tree_id, inventory_id: inventory_id }); } }]) diff --git a/awx/ui/static/js/lists/InventoryGroups.js b/awx/ui/static/js/lists/InventoryGroups.js index 1b855a5b66..d86e6a6dd9 100644 --- a/awx/ui/static/js/lists/InventoryGroups.js +++ b/awx/ui/static/js/lists/InventoryGroups.js @@ -16,16 +16,16 @@ angular.module('InventoryGroupsDefinition', []) showTitle: false, well: true, index: false, - hover: true, + hover: false, hasChildren: true, filterBy: '\{ show: true \}', - 'class': 'table-condensed', + 'class': 'table-condensed table-no-border', fields: { name: { label: 'Groups', key: true, - ngClick: "\{\{ 'showHosts(' + group.id + ',' + group.group_id + ')' \}\}", + ngClick: "\{\{ 'showHosts(' + group.id + ',' + group.group_id + ', false)' \}\}", ngClass: "group.selected_class", hasChildren: true, columnClass: 'col-lg-9', @@ -121,7 +121,7 @@ angular.module('InventoryGroupsDefinition', []) awToolTip: "\{\{ group.hosts_status_tip \}\}", ngShow: "group.id > 1", // hide for all hosts dataPlacement: "top", - ngClick: "viewFailedHosts(\{\{ group.id \}\})", + ngClick: "\{\{ 'showHosts(' + group.id + ',' + group.group_id + ',' + group.show_failures + ')' \}\}", iconClass: "\{\{ 'fa icon-failures-' + group.hosts_status_class \}\}" }, group_update: { diff --git a/awx/ui/static/js/lists/InventoryHosts.js b/awx/ui/static/js/lists/InventoryHosts.js index 32553e0609..d53fbb6295 100644 --- a/awx/ui/static/js/lists/InventoryHosts.js +++ b/awx/ui/static/js/lists/InventoryHosts.js @@ -16,9 +16,9 @@ angular.module('InventoryHostsDefinition', []) showTitle: false, well: true, index: false, - hover: true, + hover: false, hasChildren: true, - 'class': 'table-condensed', + 'class': 'table-condensed table-no-border', fields: { name: { @@ -85,15 +85,15 @@ angular.module('InventoryHostsDefinition', []) fieldActions: { edit: { - label: 'Edit', + //label: 'Edit', ngClick: "editGroup(\{\{ host.id \}\})", icon: 'icon-edit', "class": 'btn-xs btn-primary', awToolTip: 'Edit host' }, "delete": { - label: 'Delete', - ngClick: "deleteHoust(\{\{ host.id \}\},'\{\{ host.name \}\}')", + //label: 'Delete', + ngClick: "deleteHost(\{\{ host.id \}\},'\{\{ host.name \}\}')", icon: 'icon-trash', "class": 'btn-xs btn-primary', awToolTip: 'Delete host' @@ -104,8 +104,7 @@ angular.module('InventoryHostsDefinition', []) create: { mode: 'all', ngClick: "createHost()", - ngHide: "hostCreateHide", - ngDisabled: 'BtnDisabled', + ngHide: "!selected_tree_id", awToolTip: "Create a new host" }, stream: { diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less index d082e2bb5e..07e09a9581 100644 --- a/awx/ui/static/less/ansible-ui.less +++ b/awx/ui/static/less/ansible-ui.less @@ -21,7 +21,6 @@ @blue-dark: #2a6496; /* link hover */ @grey: #A9A9A9; @well: #f5f5f5; /* well background color */ -@green: #5bb75b; @info: #d9edf7; /* alert info background color */ @info-border: #bce8f1; /* alert info border color */ @info-color: #3a87ad; @@ -735,6 +734,17 @@ input[type="checkbox"].checkbox-no-label { border-bottom: 1px solid #ccc; } +/* Table without row borders */ + +.table-no-border thead > tr > th, +.table-no-border tbody > tr > th, +.table-no-border tfoot > tr > th, +.table-no-border thead > tr > td, +.table-no-border tbody > tr > td, +.table-no-border tfoot > tr > td { + border-top: none; +} + /* Jobs pages */ .license-expired, @@ -1028,6 +1038,10 @@ input[type="checkbox"].checkbox-no-label { font-weight: bold; } +.active-row { + background-color: @white; +} + .node-toggle { /* also used on job evetns */ float: none; diff --git a/awx/ui/static/lib/ansible/InventoryTree.js b/awx/ui/static/lib/ansible/InventoryTree.js index 78dd068bba..a8b798a216 100644 --- a/awx/ui/static/lib/ansible/InventoryTree.js +++ b/awx/ui/static/lib/ansible/InventoryTree.js @@ -186,7 +186,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper']) var all_hosts = { name: 'All Hosts', id: 1, group_id: null, parent: 0, description: '', show: true, ngicon: null, - has_children: false, related: {}, selected_class: '' }; + has_children: false, related: {}, selected_class: '', show_failures: false }; groups.push(all_hosts); function buildGroups(tree_data, parent, level) { @@ -228,7 +228,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper']) launch_tooltip: stat['launch_tip'], launch_class: stat['launch_class'], hosts_status_tip: hosts_status['tooltip'], - hosts_status_link: hosts_status['link'], + show_failures: hosts_status['failures'], hosts_status_class: hosts_status['class'], selected_class: '', show: true @@ -249,7 +249,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper']) Rest.get() .success( function(data, status, headers, config) { buildGroups(data, 0, 0); - //console.log(groups); + console.log(groups); if (refresh) { scope.groups = groups; scope.$emit('groupTreeRefreshed'); diff --git a/awx/ui/static/lib/ansible/list-generator.js b/awx/ui/static/lib/ansible/list-generator.js index 0e34aff63c..a87f9321d2 100644 --- a/awx/ui/static/lib/ansible/list-generator.js +++ b/awx/ui/static/lib/ansible/list-generator.js @@ -62,9 +62,14 @@ angular.module('ListGenerator', ['GeneratorHelpers']) if (options.append) { element.append(options.prepend); } - - this.scope = element.scope(); // Set scope specific to the element we're compiling, avoids circular reference - // From here use 'scope' to manipulate the form, as the form is not in '$scope' + + if (options.scope) { + this.scope = options.scope; + } + else { + this.scope = element.scope(); // Set scope specific to the element we're compiling, avoids circular reference + } // From here use 'scope' to manipulate the form, as the form is not in '$scope' + $compile(element)(this.scope); // Reset the scope to prevent displaying old data from our last visit to this list @@ -294,8 +299,9 @@ angular.module('ListGenerator', ['GeneratorHelpers']) // table body html += "\n"; - html += "