From 47261bd069ecde5b3cc4b391cb5a835c71131141 Mon Sep 17 00:00:00 2001 From: chouseknecht Date: Thu, 17 Oct 2013 07:49:11 +0000 Subject: [PATCH] Changed status flags on Invnentory, Groups and Hosts pages --- awx/ui/static/js/controllers/Inventories.js | 76 +++++++++++++++++---- awx/ui/static/js/forms/InventoryHosts.js | 10 +-- awx/ui/static/js/helpers/Groups.js | 35 +++++++++- awx/ui/static/js/helpers/search.js | 3 + awx/ui/static/js/lists/Inventories.js | 44 ++++++------ awx/ui/static/js/lists/InventorySummary.js | 29 ++++---- awx/ui/static/less/ansible-ui.less | 15 ++-- awx/ui/static/lib/ansible/form-generator.js | 2 +- 8 files changed, 154 insertions(+), 60 deletions(-) diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js index de2c723e2e..e94647e71c 100644 --- a/awx/ui/static/js/controllers/Inventories.js +++ b/awx/ui/static/js/controllers/Inventories.js @@ -36,23 +36,73 @@ function InventoriesList ($scope, $rootScope, $location, $log, $routeParams, Res } scope.projectsPostRefresh = scope.$on('PostRefresh', function() { for (var i=0; i < scope.inventories.length; i++) { + + // Set values for Failed Hosts column + scope.inventories[i].failed_hosts = scope.inventories[i].hosts_with_active_failures + ' / ' + scope.inventories[i].total_hosts; if (scope.inventories[i].hosts_with_active_failures > 0) { - scope.inventories[i].active_failures_params = "/?has_active_failures=true"; - } - if (scope.inventories[i].has_inventory_sources) { - //scope.inventories[i].inventory_source = 'external'; - scope.inventories[i].has_inv_sources_tip = 'Has one or more external sources. Click to view details.'; - scope.inventories[i].has_inv_sources_link = '/#/inventories/' + scope.inventories[i].id + - '/groups?has_external_source=true'; - scope.inventories[i].inventory_sources = 'yes'; + scope.inventories[i].failed_hosts_tip = "Contains " + scope.inventories[i].hosts_with_active_failures + + [ (scope.inventories[i].hosts_with_active_failures == 1) ? ' host' : ' hosts' ] + ' where the latest job failed. Click to view the ' + + [ (scope.inventories[i].hosts_with_active_failures == 1) ? ' offending host.' : ' hosts with failed jobs.' ]; + scope.inventories[i].failed_hosts_link = '/#/inventories/' + scope.inventories[i].id + '/hosts?has_active_failures=true'; + scope.inventories[i].failed_hosts_class = 'true'; } else { - //scope.inventories[i].inventory_source = 'manual'; - scope.inventories[i].has_inv_sources_tip = 'Has no external sources.'; - scope.inventories[i].has_inv_sources_link = '/#/inventories/' + scope.inventories[i].id + - '/groups'; - scope.inventories[i].inventory_sources = 'no'; + if (scope.inventories[i].total_hosts == 0) { + // no hosts + scope.inventories[i].failed_hosts_tip = "There are no hosts in this inventory. It's a sad empty shell. Click to view the hosts page and add a host."; + scope.inventories[i].failed_hosts_link = '/#/inventories/' + scope.inventories[i].id + '/hosts'; + scope.inventories[i].failed_hosts_class = 'na'; + } + else if (scope.inventories[i].total_hosts == 1) { + // on host with 0 failures + scope.inventories[i].failed_hosts_tip = "The 1 host contained in this inventory does not have a current job failure. It's happy!" + + " Click to view the host."; + scope.inventories[i].failed_hosts_link = '/#/inventories/' + scope.inventories[i].id + '/hosts'; + scope.inventories[i].failed_hosts_class = 'false'; + } + else { + // many hosts with 0 failures + scope.inventories[i].failed_hosts_tip = "All " + scope.inventories[i].total_hosts + " hosts are happy! None of them have " + + " a recent job failure. Click to view the hosts."; + scope.inventories[i].failed_hosts_link = '/#/inventories/' + scope.inventories[i].id + '/hosts'; + scope.inventories[i].failed_hosts_class = 'false'; + } } + + // Set values for Status column + scope.inventories[i].status = scope.inventories[i].inventory_sources_with_failures + ' / ' + scope.inventories[i].total_inventory_sources; + if (scope.inventories[i].inventory_sources_with_failures > 0) { + scope.inventories[i].status_tip = "Contains " + scope.inventories[i].inventory_sources_with_failures + + [ (scope.inventories[i].inventory_sources_with_failures == 1) ? ' group' : ' groups' ] + ' where the latest inventory update failed. ' + + 'Click to view the ' + + [ (scope.inventories[i].inventory_sources_with_failures == 1) ? ' offending group.' : ' groups with failures.' ]; + scope.inventories[i].status_link = '/#/inventories/' + scope.inventories[i].id + '/groups?status=failed'; + scope.inventories[i].status_class = 'failed'; + } + else { + if (scope.inventories[i].total_inventory_sources == 0) { + // no groups are reporting a source + scope.inventories[i].status_tip = "There are no groups configured for an external inventory source. Click to view groups and " + + "and add an inventory source."; + scope.inventories[i].status_link = '/#/inventories/' + scope.inventories[i].id + '/groups'; + scope.inventories[i].status_class = 'na'; + } + else if (scope.inventories[i].total_inventory_sources == 1) { + // on host with 0 failures + scope.inventories[i].status_tip = "The 1 group configured with an inventory source was updated successfully. It's happy!" + + " Click to view the group."; + scope.inventories[i].status_link = '/#/inventories/' + scope.inventories[i].id + '/groups?has_external_source=true'; + scope.inventories[i].status_class = 'successful'; + } + else { + // many hosts with 0 failures + scope.inventories[i].status_tip = "The " + scope.inventories[i].total_inventory_sources + " groups with an inventory source are happy! " + + " The most recent update of each group was successful. Click to view the groups."; + scope.inventories[i].status_link = '/#/inventories/' + scope.inventories[i].id + '/groups?has_external_source=true'; + scope.inventories[i].status_class = 'successful'; + } + } + } }); diff --git a/awx/ui/static/js/forms/InventoryHosts.js b/awx/ui/static/js/forms/InventoryHosts.js index 62b89ad048..afc479486a 100644 --- a/awx/ui/static/js/forms/InventoryHosts.js +++ b/awx/ui/static/js/forms/InventoryHosts.js @@ -22,7 +22,7 @@ angular.module('InventoryHostsFormDefinition', []) ngClick: "editHost(\{\{ host.id \}\}, '\{\{ host.name \}\}')" }, active_failures: { - label: 'Current
Job Status?', + label: 'Job Status?', ngHref: "\{\{ host.activeFailuresLink \}\}", awToolTip: "\{\{ host.badgeToolTip \}\}", dataPlacement: 'top', @@ -34,7 +34,7 @@ angular.module('InventoryHostsFormDefinition', []) searchable: false, nosort: true }, - inventory_sources: { + /*inventory_sources: { label: 'External
Source?', ngHref: "\{\{ host.has_inv_source_link \}\}", badgeNgHref: "\{\{ host.has_inv_source_link \}\}", @@ -46,7 +46,7 @@ angular.module('InventoryHostsFormDefinition', []) badgeTipPlacement: 'top', searchable: false, nosort: true - }, + },*/ groups: { label: 'Groups', searchable: true, @@ -55,7 +55,7 @@ angular.module('InventoryHostsFormDefinition', []) nosort: true }, has_active_failures: { - label: 'Current job failed?', + label: 'Has failed job?', searchSingleValue: true, searchType: 'boolean', searchValue: 'true', @@ -90,7 +90,7 @@ angular.module('InventoryHostsFormDefinition', []) icon: 'icon-plus' }, help: { - dataPlacement: 'left', + dataPlacement: 'top', icon: "icon-question-sign", mode: 'all', 'class': 'btn-xs btn-info btn-help', diff --git a/awx/ui/static/js/helpers/Groups.js b/awx/ui/static/js/helpers/Groups.js index 1bbf847d27..5debd67972 100644 --- a/awx/ui/static/js/helpers/Groups.js +++ b/awx/ui/static/js/helpers/Groups.js @@ -232,6 +232,39 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' else { scope.groups[i].active_failures_params = "/?has_active_failures=false"; } + + + // Set values for Failed Hosts column + scope.groups[i].failed_hosts = scope.groups[i].hosts_with_active_failures + ' / ' + scope.groups[i].total_hosts; + if (scope.groups[i].hosts_with_active_failures > 0) { + scope.groups[i].failed_hosts_tip = "Contains " + scope.groups[i].hosts_with_active_failures + + [ (scope.groups[i].hosts_with_active_failures == 1) ? ' host' : ' hosts' ] + ' where the latest job failed. Click to view the ' + + [ (scope.groups[i].hosts_with_active_failures == 1) ? ' offending host.' : ' hosts with failed jobs.' ]; + scope.groups[i].failed_hosts_link = '/#/inventories/' + scope.groups[i].inventory + '/hosts?has_active_failures=true'; + scope.groups[i].failed_hosts_class = 'true'; + } + else { + if (scope.groups[i].total_hosts == 0) { + // no hosts + scope.groups[i].failed_hosts_tip = "There are no hosts in this inventory. It's a sad empty shell. Click to view the hosts page and add a host."; + scope.groups[i].failed_hosts_link = '/#/inventories/' + scope.groups[i].inventory + '/hosts'; + scope.groups[i].failed_hosts_class = 'na'; + } + else if (scope.groups[i].total_hosts == 1) { + // on host with 0 failures + scope.groups[i].failed_hosts_tip = "The 1 host contained in this inventory does not have a current job failure. It's happy!" + + " Click to view the host."; + scope.groups[i].failed_hosts_link = '/#/inventories/' + scope.groups[i].inventory + '/hosts'; + scope.groups[i].failed_hosts_class = 'false'; + } + else { + // many hosts with 0 failures + scope.groups[i].failed_hosts_tip = "All " + scope.groups[i].total_hosts + " hosts are happy! None of them have " + + " a recent job failure. Click to view the hosts."; + scope.groups[i].failed_hosts_link = '/#/inventories/' + scope.groups[i].inventory + '/hosts'; + scope.groups[i].failed_hosts_class = 'false'; + } + } scope.groups[i].status = stat; scope.groups[i].source = scope.groups[i].summary_fields.inventory_source.source; @@ -263,7 +296,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' scope[list.iterator + 'SearchField'] = 'status'; scope[list.iterator + 'SelectShow'] = true; scope[list.iterator + 'SearchSelectOpts'] = list.fields['status'].searchOptions; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['status'].label; + scope[list.iterator + 'SearchFieldLabel'] = list.fields['status'].label.replace(/\/g,' '); for (var opt in list.fields['status'].searchOptions) { if (list.fields['status'].searchOptions[opt].value == $routeParams['status']) { scope[list.iterator + 'SearchSelectValue'] = list.fields['status'].searchOptions[opt]; diff --git a/awx/ui/static/js/helpers/search.js b/awx/ui/static/js/helpers/search.js index ec8afd46a6..ecd693fd6c 100644 --- a/awx/ui/static/js/helpers/search.js +++ b/awx/ui/static/js/helpers/search.js @@ -263,6 +263,9 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) if (list.fields[fld].searchField) { sort_order = direction + list.fields[fld].searchField; } + else if (list.fields[fld].sortField) { + sort_order = direction + list.fields[fld].sortField; + } else { if (list.fields[fld].sourceModel) { sort_order = direction + list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField; diff --git a/awx/ui/static/js/lists/Inventories.js b/awx/ui/static/js/lists/Inventories.js index e7282cf55a..a65130fdae 100644 --- a/awx/ui/static/js/lists/Inventories.js +++ b/awx/ui/static/js/lists/Inventories.js @@ -31,29 +31,33 @@ angular.module('InventoriesListDefinition', []) sourceField: 'name', excludeModal: true }, - hosts_with_active_failures: { - label: 'Hosts with
Failed Job?', - ngHref: '/#/inventories/{{ inventory.id }}/hosts{{ inventory.active_failures_params }}', - type: 'badgeCount', - "class": "{{ 'failures-' + inventory.has_active_failures }}", - awToolTip: '# of hosts with failed jobs. Click to view hosts.', - dataPlacement: 'top', - searchable: false, - excludeModal: true - }, - inventory_sources: { - label: 'External
Sources?', - ngHref: '\{\{ inventory.has_inv_sources_link \}\}', - badgeNgHref: '\{\{ inventory.has_inv_sources_link \}\}', - badgeIcon: "\{\{ 'icon-cloud-' + inventory.has_inventory_sources \}\}", + failed_hosts: { + label: 'Failed Hosts', + ngHref: "\{\{ inventory.failed_hosts_link \}\}", + badgeIcon: "\{\{ 'icon-failures-' + inventory.failed_hosts_class \}\}", + badgeNgHref: "\{\{ inventory.failed_hosts_link \}\}", badgePlacement: 'left', - badgeToolTip: "\{\{ inventory.has_inv_sources_tip \}\}", - awToolTip: "\{\{ inventory.has_inv_sources_tip \}\}", - dataPlacement: "top", + badgeToolTip: "\{\{ inventory.failed_hosts_tip \}\}", badgeTipPlacement: 'top', + awToolTip: "\{\{ inventory.failed_hosts_tip \}\}", + dataPlacement: "top", searchable: false, excludeModal: true, - nosort: true + sortField: "hosts_with_active_failures" + }, + status: { + label: 'Status', + ngHref: "\{\{ inventory.status_link \}\}", + badgeIcon: "\{\{ 'icon-cloud-' + inventory.status_class \}\}", + badgeNgHref: "\{\{ inventory.status_link \}\}", + badgePlacement: 'left', + badgeTipPlacement: 'top', + badgeToolTip: "\{\{ inventory.status_tip \}\}", + awToolTip: "\{\{ inventory.status_tip \}\}", + dataPlacement: "top", + searchable: false, + excludeModal: true, + sortField: "inventory_sources_with_failures" }, has_inventory_sources: { label: 'Has external sources?', @@ -63,7 +67,7 @@ angular.module('InventoriesListDefinition', []) searchOnly: true }, has_active_failures: { - label: 'Has hosts with failed jobs?', + label: 'Has failed hosts?', searchSingleValue: true, searchType: 'boolean', searchValue: 'true', diff --git a/awx/ui/static/js/lists/InventorySummary.js b/awx/ui/static/js/lists/InventorySummary.js index e6474d101d..f34f57d427 100644 --- a/awx/ui/static/js/lists/InventorySummary.js +++ b/awx/ui/static/js/lists/InventorySummary.js @@ -25,18 +25,22 @@ angular.module('InventorySummaryDefinition', []) ngClick: "\{\{ 'GroupsEdit(' + group.id + ')' \}\}", columnClass: 'col-lg-3 col-md3 col-sm-2' }, - hosts_with_active_failures: { - label: 'Hosts with
Job Failures?', - ngHref: '/#/inventories/{{ inventory_id }}/hosts{{ group.active_failures_params }}', - type: 'badgeCount', - "class": "{{ 'failures-' + group.has_active_failures }}", - awToolTip: '# of hosts with job failures. Click to view hosts.', - dataPlacement: 'top', + failed_hosts: { + label: 'Failed Hosts', + ngHref: "\{\{ group.failed_hosts_link \}\}", + badgeIcon: "\{\{ 'icon-failures-' + group.failed_hosts_class \}\}", + badgeNgHref: "\{\{ group.failed_hosts_link \}\}", + badgePlacement: 'left', + badgeToolTip: "\{\{ group.failed_hosts_tip \}\}", + badgeTipPlacement: 'top', + awToolTip: "\{\{ group.failed_hosts_tip \}\}", + dataPlacement: "top", searchable: false, - nosort: false + excludeModal: true, + sortField: "hosts_with_active_failures" }, status: { - label: 'Update
Status', + label: 'Status', ngClick: "viewUpdateStatus(\{\{ group.id \}\})", searchType: 'select', badgeIcon: "\{\{ 'icon-cloud-' + group.status_badge_class \}\}", @@ -69,7 +73,8 @@ angular.module('InventorySummaryDefinition', []) { name: "none", value: "" }, { name: "rackspace", value: "rackspace" }], sourceModel: 'inventory_source', - sourceField: 'source' + sourceField: 'source', + searchOnly: true }, has_external_source: { label: 'Has external source?', @@ -80,7 +85,7 @@ angular.module('InventorySummaryDefinition', []) sourceField: 'source' }, has_active_failures: { - label: 'Hosts have job failures?', + label: 'Has failed hosts?', searchSingleValue: true, searchType: 'boolean', searchValue: 'true', @@ -110,7 +115,7 @@ angular.module('InventorySummaryDefinition', []) dataPlacement: 'top' }, help: { - dataPlacement: 'left', + dataPlacement: 'top', icon: "icon-question-sign", mode: 'all', 'class': 'btn-xs btn-info btn-help', diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less index 802712be49..82aade7cac 100644 --- a/awx/ui/static/less/ansible-ui.less +++ b/awx/ui/static/less/ansible-ui.less @@ -689,7 +689,8 @@ select.field-mini-height { color: @red; } - .icon-failures-none { + .icon-failures-none, + .icon-failures-na { color: @grey; } @@ -698,6 +699,7 @@ select.field-mini-height { } .icon-failures-none:before, + .icon-failures-na:before, .icon-failures-false:before { content: "\f111"; } @@ -733,17 +735,14 @@ select.field-mini-height { content: "\f06a"; } - .icon-cloud-na { - color: #888; - } - + .icon-cloud-na, .icon-cloud-never { - color: #888; + color: @grey; } .icon-cloud-updating, .icon-cloud-successful { - color: #5bb75b; + color: @green; } .icon-cloud-failed { @@ -1041,7 +1040,7 @@ select.field-mini-height { .field-badge { font-size: 10px; line-height: normal; - vertical-align: middle; + vertical-align: baseline; } } diff --git a/awx/ui/static/lib/ansible/form-generator.js b/awx/ui/static/lib/ansible/form-generator.js index 6a1321af36..3c8e9038ba 100644 --- a/awx/ui/static/lib/ansible/form-generator.js +++ b/awx/ui/static/lib/ansible/form-generator.js @@ -1280,7 +1280,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) html += SearchWidget({ iterator: form.iterator, template: form, mini: true, size: 'col-md-5 col-lg-5'}); - html += "
\n" + html += "
\n" html += "
\n"; // Add actions(s) for (var action in form.actions) {