1
0
mirror of https://github.com/ansible/awx.git synced 2024-11-01 08:21:15 +03:00

route activity stream > groups links to inventory manage, remove HomeGroups code, resolves #1660 (#2488)

This commit is contained in:
Leigh 2016-06-17 20:37:17 -04:00 committed by GitHub
parent 283b62e598
commit 94a0f22b39
5 changed files with 5 additions and 561 deletions

View File

@ -21,7 +21,7 @@ import './lists';
import './widgets';
import './help';
import './filters';
import {Home, HomeGroups} from './controllers/Home';
import {Home} from './controllers/Home';
import {SocketsController} from './controllers/Sockets';
import {CredentialsAdd, CredentialsEdit, CredentialsList} from './controllers/Credentials';
import {JobsListController} from './controllers/Jobs';
@ -173,7 +173,6 @@ var tower = angular.module('Tower', [
'InventoryGroupsHelpDefinition',
'CredentialsHelper',
'StreamListDefinition',
'HomeGroupListDefinition',
'ActivityDetailDefinition',
'VariablesHelper',
'SchedulesListDefinition',
@ -256,16 +255,6 @@ var tower = angular.module('Tower', [
}
}).
state('dashboardGroups', {
url: '/home/groups?id&name&has_active_failures&status&source&has_external_source&inventory_source__id',
templateUrl: urlPrefix + 'partials/subhome.html',
controller: HomeGroups,
ncyBreadcrumb: {
parent: 'dashboard',
label: "GROUPS"
}
}).
state('jobs', {
url: '/jobs',
templateUrl: urlPrefix + 'partials/jobs.html',

View File

@ -140,378 +140,3 @@ export function Home($scope, $compile, $stateParams, $rootScope, $location, $log
Home.$inject = ['$scope', '$compile', '$stateParams', '$rootScope', '$location', '$log','Wait',
'ClearScope', 'Rest', 'GetBasePath', 'ProcessErrors', '$window', 'graphData'
];
/**
* @ngdoc method
* @name controllers.function:Home#HomeGroups
* @methodOf controllers.function:Home
* @description This controls the 'home/groups' page that is loaded from the dashboard
*
*/
export function HomeGroups($rootScope, $log, $scope, $filter, $compile, $location, $stateParams, HomeGroupList, GenerateList, ProcessErrors, ReturnToCaller, ClearScope,
GetBasePath, SearchInit, PaginateInit, FormatDate, GetHostsStatusMsg, GetSyncStatusMsg, ViewUpdateStatus, GroupsEdit, Wait,
Alert, Rest, Empty, InventoryUpdate, Find, GroupsCancelUpdate, Store) {
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var generator = GenerateList,
list = HomeGroupList,
defaultUrl = GetBasePath('groups'),
scope = $scope,
opt, PreviousSearchParams;
generator.inject(list, { mode: 'edit', scope: scope });
function ellipsis(a) {
if (a.length > 20) {
return a.substr(0,20) + '...';
}
return a;
}
function attachElem(event, html, title) {
var elem = $(event.target).parent();
try {
elem.tooltip('hide');
elem.popover('destroy');
}
catch(err) {
//ignore
}
$('.popover').each(function() {
// remove lingering popover <div>. Seems to be a bug in TB3 RC1
$(this).remove();
});
$('.tooltip').each( function() {
// close any lingering tool tipss
$(this).hide();
});
elem.attr({ "aw-pop-over": html, "data-popover-title": title, "data-placement": "right" });
$compile(elem)(scope);
elem.on('shown.bs.popover', function() {
$('.popover').each(function() {
$compile($(this))(scope); //make nested directives work!
});
$('.popover-content, .popover-title').click(function() {
elem.popover('hide');
});
});
elem.popover('show');
}
if (scope.removePostRefresh) {
scope.removePostRefresh();
}
scope.removePostRefresh = scope.$on('PostRefresh', function () {
var i, hosts_status, stat;
for (i = 0; i < scope.home_groups.length; i++) {
scope.home_groups[i].inventory_name = scope.home_groups[i].summary_fields.inventory.name;
stat = GetSyncStatusMsg({
status: scope.home_groups[i].summary_fields.inventory_source.status,
source: scope.home_groups[i].summary_fields.inventory_source.source,
has_inventory_sources: scope.home_groups[i].has_inventory_sources
}); // from helpers/Groups.js
hosts_status = GetHostsStatusMsg({
active_failures: scope.home_groups[i].hosts_with_active_failures,
total_hosts: scope.home_groups[i].total_hosts,
inventory_id: scope.home_groups[i].inventory,
group_id: scope.home_groups[i].id
});
scope.home_groups[i].status_class = stat['class'];
scope.home_groups[i].status_tooltip = stat.tooltip;
scope.home_groups[i].launch_tooltip = stat.launch_tip;
scope.home_groups[i].launch_class = stat.launch_class;
scope.home_groups[i].hosts_status_tip = hosts_status.tooltip;
scope.home_groups[i].show_failures = hosts_status.failures;
scope.home_groups[i].hosts_status_class = hosts_status['class'];
scope.home_groups[i].status = scope.home_groups[i].summary_fields.inventory_source.status;
scope.home_groups[i].source = (scope.home_groups[i].summary_fields.inventory_source) ?
scope.home_groups[i].summary_fields.inventory_source.source : null;
}
});
SearchInit({
scope: scope,
set: 'home_groups',
list: list,
url: defaultUrl
});
PaginateInit({
scope: scope,
list: list,
url: defaultUrl
});
// Process search params
if ($stateParams.name) {
scope[list.iterator + 'InputDisable'] = false;
scope[list.iterator + 'SearchValue'] = $stateParams.name;
scope[list.iterator + 'SearchField'] = 'name';
scope[list.iterator + 'SearchFieldLabel'] = list.fields.name.label;
scope[list.iterator + 'SearchSelectValue'] = null;
}
if ($stateParams.id) {
scope[list.iterator + 'InputDisable'] = false;
scope[list.iterator + 'SearchValue'] = $stateParams.id;
scope[list.iterator + 'SearchField'] = 'id';
scope[list.iterator + 'SearchFieldLabel'] = list.fields.id.label;
scope[list.iterator + 'SearchSelectValue'] = null;
}
if ($stateParams.has_active_failures) {
scope[list.iterator + 'InputDisable'] = true;
scope[list.iterator + 'SearchValue'] = $stateParams.has_active_failures;
scope[list.iterator + 'SearchField'] = 'has_active_failures';
scope[list.iterator + 'SearchFieldLabel'] = list.fields.has_active_failures.label;
scope[list.iterator + 'SearchSelectValue'] = ($stateParams.has_active_failures === 'true') ? { value: 1 } : { value: 0 };
}
if ($stateParams.status && !$stateParams.source) {
scope[list.iterator + 'SearchField'] = 'last_update_failed';
scope[list.iterator + 'SearchFieldLabel'] = list.fields.last_update_failed.label;
scope[list.iterator + 'SelectShow'] = false;
scope[list.iterator + 'SearchValue'] = 'failed';
scope[list.iterator + 'SearchSelectValue'] = { value: 'failed' };
//scope[list.iterator + 'SelectShow'] = true;
//scope[list.iterator + 'SearchSelectOpts'] = list.fields.status.searchOptions;
//scope[list.iterator + 'SearchFieldLabel'] = list.fields.status.label.replace(/<br\>/g, ' ');
//for (opt in list.fields.status.searchOptions) {
// if (list.fields.status.searchOptions[opt].value === $stateParams.status) {
// scope[list.iterator + 'SearchSelectValue'] = list.fields.status.searchOptions[opt];
// break;
// }
//}
}
if ($stateParams.source) {
scope[list.iterator + 'SearchField'] = 'source';
scope[list.iterator + 'SelectShow'] = true;
scope[list.iterator + 'SearchSelectOpts'] = list.fields.source.searchOptions;
scope[list.iterator + 'SearchFieldLabel'] = list.fields.source.label.replace(/<br\>/g, ' ');
for (opt in list.fields.source.searchOptions) {
if (list.fields.source.searchOptions[opt].value === $stateParams.source) {
scope[list.iterator + 'SearchSelectValue'] = list.fields.source.searchOptions[opt];
break;
}
}
if ($stateParams.status) {
scope[list.iterator + 'ExtraParms'] = 'inventory_source__status__icontains=' + $stateParams.status;
}
}
if ($stateParams.has_external_source) {
scope[list.iterator + 'SearchField'] = 'has_external_source';
scope[list.iterator + 'SearchValue'] = list.fields.has_external_source.searchValue;
scope[list.iterator + 'InputDisable'] = true;
scope[list.iterator + 'SearchType'] = 'in';
scope[list.iterator + 'SearchFieldLabel'] = list.fields.has_external_source.label;
}
if ($stateParams.inventory_source__id) {
scope[list.iterator + 'SearchField'] = 'inventory_source';
scope[list.iterator + 'SearchValue'] = $stateParams.inventory_source__id;
scope[list.iterator + 'SearchFieldLabel'] = 'Source ID';
}
scope.search(list.iterator);
scope.$emit('WatchUpdateStatus'); // Start watching for live updates
if ($rootScope.removeJobStatusChange) {
$rootScope.removeJobStatusChange();
}
$rootScope.removeJobStatusChange = $rootScope.$on('JobStatusChange-home', function(e, data) {
var stat, group;
if (data.group_id) {
group = Find({ list: scope[list.name], key: 'id', val: data.group_id });
if (group && (data.status === "failed" || data.status === "successful")) {
// job completed, fefresh all groups
$log.debug('Update completed. Refreshing the list');
scope.refresh();
}
else if (group) {
// incremental update, just update
$log.debug('Status of group: ' + data.group_id + ' changed to: ' + data.status);
stat = GetSyncStatusMsg({
status: data.status,
has_inventory_sources: group.has_inventory_sources,
source: group.source
});
$log.debug('changing tooltip to: ' + stat.tooltip);
group.status = data.status;
group.status_class = stat['class'];
group.status_tooltip = stat.tooltip;
group.launch_tooltip = stat.launch_tip;
group.launch_class = stat.launch_class;
}
}
});
scope.editGroup = function (group_id, inventory_id) {
PreviousSearchParams = Store('group_current_search_params');
GroupsEdit({
scope: scope,
group_id: group_id,
inventory_id: inventory_id,
groups_reload: false,
mode: 'edit'
});
};
scope.restoreSearch = function() {
SearchInit({
scope: scope,
set: PreviousSearchParams.set,
list: PreviousSearchParams.list,
url: PreviousSearchParams.defaultUrl,
iterator: PreviousSearchParams.iterator,
sort_order: PreviousSearchParams.sort_order,
setWidgets: false
});
scope.refresh();
};
scope.viewUpdateStatus = function (id) {
scope.groups = scope.home_groups;
ViewUpdateStatus({
scope: scope,
group_id: id
});
};
// Launch inventory sync
scope.updateGroup = function (id) {
var group = Find({ list: scope.home_groups, key: 'id', val: id });
if (group) {
if (Empty(group.source)) {
// if no source, do nothing.
} else if (group.status === 'updating') {
Alert('Update in Progress', 'The inventory update process is currently running for group <em>' +
group.name + '</em>. Use the Refresh button to monitor the status.', 'alert-info');
} else {
Wait('start');
Rest.setUrl(group.related.inventory_source);
Rest.get()
.success(function (data) {
InventoryUpdate({
scope: scope,
url: data.related.update,
group_name: data.summary_fields.group.name,
group_source: data.source,
tree_id: group.id,
group_id: group.id
});
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve inventory source: ' + group.related.inventory_source + ' POST returned status: ' + status
});
});
}
}
};
scope.refresh = function () {
scope.search(list.iterator);
};
if (scope.removeHostSummaryReady) {
scope.removeHostSummaryReady();
}
scope.removeHostSummaryReady = scope.$on('HostSummaryReady', function(e, event, data) {
var html, title = "Recent Jobs";
Wait('stop');
if (data.length > 0) {
html = "<table class=\"table table-condensed flyout\" style=\"width: 100%\">\n";
html += "<thead>\n";
html += "<tr>";
html += "<th>Status</th>";
html += "<th>Finished</th>";
html += "<th>Name</th>";
html += "</tr>\n";
html += "</thead>\n";
html += "<tbody>\n";
data.forEach(function(row) {
html += "<tr>\n";
html += "<td><a href=\"#/jobs/" + row.id + "\" " + "aw-tool-tip=\"" + row.status.charAt(0).toUpperCase() + row.status.slice(1) +
". Click for details\" aw-tip-placement=\"top\"><i class=\"fa icon-job-" +
row.status + "\"></i></a></td>\n";
html += "<td>" + ($filter('longDate')(row.finished)).replace(/ /,'<br />') + "</td>";
html += "<td><a href=\"#/jobs/" + row.id + "\" " + "aw-tool-tip=\"" + row.status.charAt(0).toUpperCase() + row.status.slice(1) +
". Click for details\" aw-tip-placement=\"top\">" + ellipsis(row.name) + "</a></td>";
html += "</tr>\n";
});
html += "</tbody>\n";
html += "</table>\n";
}
else {
html = "<p>No recent job data available for this inventory.</p>\n";
}
attachElem(event, html, title);
});
scope.showHostSummary = function(event, id) {
var url, jobs = [];
if (!Empty(id)) {
Wait('start');
url = GetBasePath('hosts') + "?groups__id=" + id + "&last_job__isnull=false&order_by=-last_job&page_size=5";
Rest.setUrl(url);
Rest.get()
.success( function(data) {
data.results.forEach(function(host) {
var found = false;
jobs.every(function(existing_job) {
if (host.last_job === existing_job.id) {
found = true;
return false;
}
return true;
});
if (!found) {
jobs.push({
id: host.last_job,
status: host.summary_fields.last_job.status,
name: host.summary_fields.last_job.name,
finished: host.summary_fields.last_job.finished
});
}
});
scope.$emit('HostSummaryReady', event, jobs);
})
.error( function(data, status) {
ProcessErrors( scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. GET returned: ' + status
});
});
}
};
scope.cancelUpdate = function(id) {
var group = Find({ list: scope.home_groups, key: 'id', val: id });
GroupsCancelUpdate({ scope: scope, group: group });
};
}
HomeGroups.$inject = ['$rootScope', '$log', '$scope', '$filter', '$compile', '$location', '$stateParams', 'HomeGroupList', 'generateList', 'ProcessErrors', 'ReturnToCaller',
'ClearScope', 'GetBasePath', 'SearchInit', 'PaginateInit', 'FormatDate', 'GetHostsStatusMsg', 'GetSyncStatusMsg', 'ViewUpdateStatus',
'GroupsEdit', 'Wait', 'Alert', 'Rest', 'Empty', 'InventoryUpdate', 'Find', 'GroupsCancelUpdate', 'Store', 'Socket'
];
/**
* @ngdoc method
* @name controllers.function:Home#HomeHosts
* @methodOf controllers.function:Home
* @description This loads the page for 'home/hosts'
*
*/

View File

@ -9,7 +9,6 @@ import CompletedJobs from "./lists/CompletedJobs";
import AllJobs from "./lists/AllJobs";
import Credentials from "./lists/Credentials";
import Groups from "./lists/Groups";
import HomeGroups from "./lists/HomeGroups";
import Hosts from "./lists/Hosts";
import Inventories from "./lists/Inventories";
import InventoryGroups from "./lists/InventoryGroups";
@ -35,7 +34,6 @@ export
AllJobs,
Credentials,
Groups,
HomeGroups,
Hosts,
Inventories,
InventoryGroups,

View File

@ -1,170 +0,0 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
export default
angular.module('HomeGroupListDefinition', [])
.value('HomeGroupList', {
name: 'home_groups',
iterator: 'group',
editTitle: 'Groups',
index: false,
hover: true,
well: true,
fields: {
status: {
label: '',
columnClass: 'List-staticColumn--mediumStatus',
searchable: false,
nosort: true,
ngClick: "null",
iconOnly: true,
icons: [{
icon: "{{ 'icon-cloud-' + group.status_class }}",
awToolTip: "{{ group.status_tooltip }}",
dataTipWatch: "group.launch_tooltip",
awTipPlacement: "right",
ngClick: "viewUpdateStatus(group.id)",
ngClass: "group.launch_class"
},{
icon: "{{ 'icon-job-' + group.hosts_status_class }}",
awToolTip: "{{ group.hosts_status_tip }}",
awTipPlacement: "right",
ngClick: "showHostSummary($event, group.id)",
ngClass: ""
}]
},
name: {
key: true,
label: 'Group',
ngClick: "editGroup(group.id, group.inventory)",
columnClass: 'col-lg-6 col-md-5 col-sm-5 col-xs-8 ellipsis List-staticColumnAdjacent'
},
inventory_name: {
label: 'Inventory',
sourceModel: 'inventory',
sourceField: 'name',
columnClass: 'col-lg-4 col-md-5 col-sm-3 hidden-xs elllipsis',
linkTo: "{{ '/#/inventories/' + group.inventory + '/' }}"
},
source: {
label: 'Source',
searchType: 'select',
searchOptions: [{
name: "Amazon Web Services",
value: "ec2"
}, {
name: "none",
value: ""
}, {
name: "Rackspace",
value: "rax"
},{
name: "VMware",
value: "vmware"
},{
name: "Google Compute Engine",
value: "gce"
},{
name: "Microsoft Azure",
value: "azure"
},{
name: "OpenStack",
value: "openstack"
}],
sourceModel: 'inventory_source',
sourceField: 'source',
searchOnly: true
},
has_external_source: {
label: 'Has external source?',
searchType: 'in',
searchValue: 'ec2,rax,vmware,azure,gce,openstack',
searchOnly: true,
sourceModel: 'inventory_source',
sourceField: 'source'
},
has_active_failures: {
label: 'Has failed hosts?',
searchSingleValue: true,
searchType: 'boolean',
searchValue: 'true',
searchOnly: true
},
last_update_failed: {
label: 'Update failed?',
searchType: 'select',
searchSingleValue: true,
searchValue: 'failed',
searchOnly: true,
sourceModel: 'inventory_source',
sourceField: 'status'
},
id: {
label: 'ID',
searchOnly: true
},
inventory_source: {
label: 'Source ID',
searchType: 'int',
searchOnly: true
}
},
fieldActions: {
columnClass: 'col-lg-2 col-md-2 col-sm-4 col-xs-4',
/*
sync_status: {
mode: 'all',
ngClick: "viewUpdateStatus(group.id, group.group_id)",
awToolTip: "{{ group.status_tooltip }}",
ngClass: "group.status_class",
dataPlacement: "top"
},
failed_hosts: {
mode: 'all',
awToolTip: "{{ group.hosts_status_tip }}",
dataPlacement: "top",
ngHref: "/#/inventories/{{ group.inventory }}/",
iconClass: "{{ 'fa icon-failures-' + group.hosts_status_class }}"
},
*/
group_update: {
//label: 'Sync',
mode: 'all',
ngClick: 'updateGroup(group.id)',
awToolTip: "{{ group.launch_tooltip }}",
ngShow: "(group.status !== 'running' && group.status !== 'pending' && group.status !== 'updating')",
ngClass: "group.launch_class",
dataPlacement: "top"
},
cancel: {
//label: 'Cancel',
mode: 'all',
ngClick: "cancelUpdate(group.id)",
awToolTip: "Cancel sync process",
'class': 'red-txt',
ngShow: "(group.status == 'running' || group.status == 'pending' || group.status == 'updating')",
dataPlacement: "top"
},
edit: {
label: 'Edit',
mode: 'all',
ngClick: "editGroup(group.id, group.inventory)",
awToolTip: 'Edit group',
dataPlacement: "top"
}
},
actions: {
}
});

View File

@ -47,10 +47,12 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
.factory('BuildUrl', [
function () {
return function (obj) {
return function (obj, inventory) {
var url = '/#/';
switch (obj.base) {
case 'group':
url += 'inventories/' + inventory.id + '/manage?group=' + obj.id;
break;
case 'host':
url += 'home/' + obj.base + 's/?id=' + obj.id;
break;
@ -175,7 +177,7 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
// user to a unknown location.
obj1_obj.name = $filter('sanitize')(obj1_obj.name);
obj1_obj.name = $sce.getTrustedHtml(obj1_obj.name);
descr += obj1 + " <a href=\"" + BuildUrl(obj1_obj) + "\" >" + obj1_obj.name + '</a>';
descr += obj1 + " <a href=\"" + BuildUrl(obj1_obj, obj2_obj) + "\" >" + obj1_obj.name + '</a>';
descr_nolink += obj1 + ' ' + obj1_obj.name;
} else if (obj1) {
name = '';