diff --git a/awx/ui/static/js/app.js b/awx/ui/static/js/app.js
index c92697f086..7752795972 100644
--- a/awx/ui/static/js/app.js
+++ b/awx/ui/static/js/app.js
@@ -83,7 +83,8 @@ angular.module('ansible', [
'CredentialsHelper',
'TimerService',
'StreamListDefinition',
- 'HomeGroupListDefinition'
+ 'HomeGroupListDefinition',
+ 'HomeHostListDefinition'
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.
@@ -250,6 +251,8 @@ angular.module('ansible', [
when('/home', { templateUrl: urlPrefix + 'partials/home.html', controller: Home }).
when('/home/groups', { templateUrl: urlPrefix + 'partials/subhome.html', controller: HomeGroups }).
+
+ when('/home/hosts', { templateUrl: urlPrefix + 'partials/subhome.html', controller: HomeHosts }).
otherwise({redirectTo: '/home'});
}])
diff --git a/awx/ui/static/js/controllers/Home.js b/awx/ui/static/js/controllers/Home.js
index 922f4e0fa5..db95ce2cf9 100644
--- a/awx/ui/static/js/controllers/Home.js
+++ b/awx/ui/static/js/controllers/Home.js
@@ -94,20 +94,14 @@ function HomeGroups ($location, $routeParams, HomeGroupList, GenerateList, Proce
SearchInit({ scope: scope, set: 'groups', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
- if ($routeParams['status']) {
- // with status param, called post update-submit
- 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.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];
- break;
- }
- }
+ if ($routeParams['has_active_failures']) {
+ scope[HomeGroupList.iterator + 'InputDisable'] = true;
+ scope[HomeGroupList.iterator + 'SearchValue'] = $routeParams['has_active_failures'];
+ scope[HomeGroupList.iterator + 'SearchField'] = 'has_active_failures';
+ scope[HomeGroupList.iterator + 'SearchFieldLabel'] = HomeGroupList.fields['has_active_failures'].label;
+ scope[HomeGroupList.iterator + 'SearchSelectValue'] = ($routeParams['has_active_failures'] == 'true') ? { value: 1 } : { value: 0 };
}
-
+
scope.search(list.iterator);
LoadBreadCrumbs();
@@ -118,5 +112,53 @@ function HomeGroups ($location, $routeParams, HomeGroupList, GenerateList, Proce
HomeGroups.$inject = [ '$location', '$routeParams', 'HomeGroupList', 'GenerateList', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller',
'ClearScope', 'GetBasePath', 'SearchInit', 'PaginateInit', 'FormatDate', 'HostsStatusMsg', 'UpdateStatusMsg', 'ViewUpdateStatus'
+ ];
+
+
+function HomeHosts ($location, $routeParams, HomeHostList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
+ GetBasePath, SearchInit, PaginateInit, FormatDate, SetHostStatus) {
+
+ ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
+ //scope.
+
+ var generator = GenerateList;
+ var list = HomeHostList;
+ var defaultUrl=GetBasePath('hosts');
+
+ var scope = generator.inject(list, { mode: 'edit' });
+ var base = $location.path().replace(/^\//,'').split('/')[0];
+
+ if (scope.removePostRefresh) {
+ scope.removePostRefresh();
+ }
+ scope.removePostRefresh = scope.$on('PostRefresh', function() {
+ for (var i=0; i < scope.hosts.length; i++) {
+ scope['hosts'][i]['inventory_name'] = scope['hosts'][i]['summary_fields']['inventory']['name'];
+ SetHostStatus(scope['hosts'][i]);
+ }
+ });
+
+ SearchInit({ scope: scope, set: 'hosts', list: list, url: defaultUrl });
+ PaginateInit({ scope: scope, list: list, url: defaultUrl });
+
+ if ($routeParams['has_active_failures']) {
+ scope[HomeHostList.iterator + 'InputDisable'] = true;
+ scope[HomeHostList.iterator + 'SearchValue'] = $routeParams['has_active_failures'];
+ scope[HomeHostList.iterator + 'SearchField'] = 'has_active_failures';
+ scope[HomeHostList.iterator + 'SearchFieldLabel'] = HomeHostList.fields['has_active_failures'].label;
+ scope[HomeHostList.iterator + 'SearchSelectValue'] = ($routeParams['has_active_failures'] == 'true') ? { value: 1 } : { value: 0 };
+ }
+
+ scope.search(list.iterator);
+
+ LoadBreadCrumbs();
+
+ scope.viewUpdateStatus = function(id) { ViewUpdateStatus({ scope: scope, group_id: id }) };
+
+ }
+
+HomeGroups.$inject = [ '$location', '$routeParams', 'HomeGroupList', 'GenerateList', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller',
+ 'ClearScope', 'GetBasePath', 'SearchInit', 'PaginateInit', 'FormatDate', 'HostsStatusMsg', 'UpdateStatusMsg', 'ViewUpdateStatus',
+ 'SetHostStatus'
];
\ No newline at end of file
diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js
index 8ece087afb..02d49e7911 100644
--- a/awx/ui/static/js/controllers/Inventories.js
+++ b/awx/ui/static/js/controllers/Inventories.js
@@ -24,9 +24,19 @@ function InventoriesList ($scope, $rootScope, $location, $log, $routeParams, Res
var scope = view.inject(InventoryList, { mode: mode }); // Inject our view
$rootScope.flashMessage = null;
-
+
SearchInit({ scope: scope, set: 'inventories', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
+
+ if ($routeParams['has_active_failures']) {
+ //scope.resetSearch(InventoryHostsForm.iterator);
+ scope[InventoryList.iterator + 'InputDisable'] = true;
+ scope[InventoryList.iterator + 'SearchValue'] = $routeParams['has_active_failures'];
+ scope[InventoryList.iterator + 'SearchField'] = 'has_active_failures';
+ scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields['has_active_failures'].label;
+ scope[InventoryList.iterator + 'SearchSelectValue'] = ($routeParams['has_active_failures'] == 'true') ? { value: 1 } : { value: 0 };
+ }
+
scope.search(list.iterator);
LoadBreadCrumbs();
diff --git a/awx/ui/static/js/helpers/Hosts.js b/awx/ui/static/js/helpers/Hosts.js
index 529f29ebf2..51cbc1c0e0 100644
--- a/awx/ui/static/js/helpers/Hosts.js
+++ b/awx/ui/static/js/helpers/Hosts.js
@@ -13,6 +13,42 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
'InventoryFormDefinition', 'SelectionHelper', 'HostGroupsFormDefinition',
'InventoryHostsFormDefinition'
])
+
+
+ .factory('SetHostStatus', [ function() {
+ return function(host) {
+ // Set status related fields on a host object
+ host.activeFailuresLink = '/#/hosts/' + host.id + '/job_host_summaries/?inventory=' + host.inventory +
+ '&host_name=' + escape(host.name);
+ if (host.has_active_failures == true) {
+ host.badgeToolTip = 'Most recent job failed. Click to view jobs.';
+ host.active_failures = 'failed';
+ }
+ else if (host.has_active_failures == false && host.last_job == null) {
+ host.has_active_failures = 'none';
+ host.badgeToolTip = "No job data available.";
+ host.active_failures = 'n/a';
+ }
+ else if (host.has_active_failures == false && host.last_job !== null) {
+ hast.badgeToolTip = "Most recent job successful. Click to view jobs.";
+ host.active_failures = 'success';
+ }
+
+ host.enabled_flag = host.enabled;
+ if (host.has_inventory_sources) {
+ // Inventory sync managed, so not clickable
+ host.enabledToolTip = (host.enabled) ? 'Ready! Availabe to running jobs.' :
+ 'Out to lunch! This host is not available to running jobs.';
+ }
+ else {
+ // Clickable
+ host.enabledToolTip = (host.enabled) ? 'Ready! Available to running jobs. Click to toggle.' :
+ 'Out to lunch! Host not available to running jobs. Click to toggle.';
+ }
+
+ }
+ }])
+
.factory('HostsList', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostList', 'GenerateList',
'Prompt', 'SearchInit', 'PaginateInit', 'ProcessErrors', 'GetBasePath', 'HostsAdd', 'HostsReload',
@@ -404,7 +440,8 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
.factory('HostsReload', ['$location', '$routeParams', 'SearchInit', 'PaginateInit', 'InventoryHostsForm', 'GetBasePath', 'Wait',
- function($location, $routeParams, SearchInit, PaginateInit, InventoryHostsForm, GetBasePath, Wait) {
+ 'SetHostStatus',
+ function($location, $routeParams, SearchInit, PaginateInit, InventoryHostsForm, GetBasePath, Wait, SetHostStatus) {
return function(params) {
// Rerfresh the Hosts view on right side of page
@@ -439,34 +476,7 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
}
for (var i=0; i < scope.hosts.length; i++) {
- // Add the value displayed in Job Status column
- scope.hosts[i].activeFailuresLink = '/#/hosts/' + scope.hosts[i].id + '/job_host_summaries/?inventory=' + scope['inventory_id'] +
- '&host_name=' + escape(scope.hosts[i].name);
- if (scope.hosts[i].has_active_failures == true) {
- scope.hosts[i].badgeToolTip = 'Most recent job failed. Click to view jobs.';
- scope.hosts[i].active_failures = 'failed';
- }
- else if (scope.hosts[i].has_active_failures == false && scope.hosts[i].last_job == null) {
- scope.hosts[i].has_active_failures = 'none';
- scope.hosts[i].badgeToolTip = "No job data available.";
- scope.hosts[i].active_failures = 'n/a';
- }
- else if (scope.hosts[i].has_active_failures == false && scope.hosts[i].last_job !== null) {
- scope.hosts[i].badgeToolTip = "Most recent job successful. Click to view jobs.";
- scope.hosts[i].active_failures = 'success';
- }
-
- scope.hosts[i].enabled_flag = scope.hosts[i].enabled;
- if (scope.hosts[i].has_inventory_sources) {
- // Inventory sync managed, so not clickable
- scope.hosts[i].enabledToolTip = (scope.hosts[i].enabled) ? 'Ready! Availabe to running jobs.' :
- 'Out to lunch! This host is not available to running jobs.';
- }
- else {
- // Clickable
- scope.hosts[i].enabledToolTip = (scope.hosts[i].enabled) ? 'Ready! Available to running jobs. Click to toggle.' :
- 'Out to lunch! Host not available to running jobs. Click to toggle.';
- }
+ SetHostStatus(scope.hosts[i]);
}
if (group_id == null || group_id == undefined) {
diff --git a/awx/ui/static/js/lists/HomeHosts.js b/awx/ui/static/js/lists/HomeHosts.js
new file mode 100644
index 0000000000..0f3cd755f4
--- /dev/null
+++ b/awx/ui/static/js/lists/HomeHosts.js
@@ -0,0 +1,93 @@
+/*********************************************
+ * Copyright (c) 2013 AnsibleWorks, Inc.
+ *
+ * HomeHosts.js
+ *
+ * List view object for Hosts data model. Used
+ * on the home tab.
+ *
+ */
+angular.module('HomeHostListDefinition', [])
+ .value(
+ 'HomeHostList', {
+
+ name: 'hosts',
+ iterator: 'host',
+ selectTitle: 'Add Existing Hosts',
+ editTitle: 'Hosts',
+ index: true,
+ well: true,
+
+ fields: {
+ name: {
+ key: true,
+ label: 'Name',
+ columnClass: 'col-lg-3 col-md3 col-sm-2',
+ ngClick: "editHost(\{\{ host.id \}\}, '\{\{ host.name \}\}')"
+ },
+ inventory_name: {
+ label: 'Inventory',
+ sourceModel: 'inventory',
+ sourceField: 'name',
+ columnClass: 'col-lg-3 col-md3 col-sm-2',
+ linkTo: "\{\{ '/#/inventories/' + group.inventory \}\}"
+ },
+ active_failures: {
+ label: 'Job Status',
+ ngHref: "\{\{ host.activeFailuresLink \}\}",
+ awToolTip: "\{\{ host.badgeToolTip \}\}",
+ dataPlacement: 'top',
+ badgeNgHref: '\{\{ host.activeFailuresLink \}\}',
+ badgeIcon: "\{\{ 'icon-failures-' + host.has_active_failures \}\}",
+ badgePlacement: 'left',
+ badgeToolTip: "\{\{ host.badgeToolTip \}\}",
+ badgeTipPlacement: 'top',
+ searchable: false,
+ nosort: true
+ },
+ enabled_flag: {
+ label: 'Enabled',
+ badgeIcon: "\{\{ 'icon-enabled-' + host.enabled \}\}",
+ badgePlacement: 'left',
+ badgeToolTip: "\{\{ host.enabledToolTip \}\}",
+ badgeTipPlacement: "top",
+ ngClick: "toggle_host_enabled(\{\{ host.id \}\}, \{\{ host.has_inventory_sources \}\})",
+ searchable: false,
+ showValue: false
+ },
+ groups: {
+ label: 'Groups',
+ searchable: true,
+ sourceModel: 'groups',
+ sourceField: 'name',
+ nosort: true
+ },
+ enabled: {
+ label: 'Disabled?',
+ searchSingleValue: true,
+ searchType: 'boolean',
+ searchValue: 'false',
+ searchOnly: true
+ },
+ has_active_failures: {
+ label: 'Has failed jobs?',
+ searchSingleValue: true,
+ searchType: 'boolean',
+ searchValue: 'true',
+ searchOnly: true
+ },
+ has_inventory_sources: {
+ label: 'Has external source?',
+ searchSingleValue: true,
+ searchType: 'boolean',
+ searchValue: 'true',
+ searchOnly: true
+ }
+ },
+
+ actions: {
+ },
+
+ fieldActions: {
+ }
+ });
diff --git a/awx/ui/static/js/widgets/JobStatus.js b/awx/ui/static/js/widgets/JobStatus.js
index a95801577c..238c56e302 100644
--- a/awx/ui/static/js/widgets/JobStatus.js
+++ b/awx/ui/static/js/widgets/JobStatus.js
@@ -74,10 +74,10 @@ angular.module('JobStatusWidget', ['RestServices', 'Utilities'])
if (inventoryCount > 0) {
html += makeRow({
label: 'Inventories',
- link: '/#/home/inventories',
+ link: '/#/inventories',
count: inventoryCount,
fail: inventoryFails,
- fail_link: '/#/home/inventories/?has_active_failures=true'
+ fail_link: '/#/inventories/?has_active_failures=true'
});
rowcount++;
}
@@ -94,7 +94,7 @@ angular.module('JobStatusWidget', ['RestServices', 'Utilities'])
if (hostCount > 0) {
html += makeRow({
label: 'Hosts',
- link: '#/home/hosts',
+ link: '/#/home/hosts',
count: hostCount,
fail: hostFails,
fail_link: '/#/home/hosts/?has_active_failures=true'
diff --git a/awx/ui/templates/ui/index.html b/awx/ui/templates/ui/index.html
index 152a1be3c4..e3d5e6378a 100644
--- a/awx/ui/templates/ui/index.html
+++ b/awx/ui/templates/ui/index.html
@@ -92,6 +92,7 @@
+