Inventory refactor from 1.4.11

Include commits from release_1.4.11 branch up to but not including 809c99d05c4bd14dac7ef2f19767e4d196cdd1bb
This commit is contained in:
Chris Houseknecht 2014-06-02 15:31:30 -04:00
parent b58f65ca26
commit 527e7c6943
15 changed files with 1275 additions and 511 deletions

View File

@ -14,7 +14,7 @@ function Home($scope, $compile, $routeParams, $rootScope, $location, Wait, Objec
ClearScope, Stream, Rest, GetBasePath, ProcessErrors, Button) {
ClearScope('home');
var buttons, html, e, waitCount, loadedCount;
// Add buttons to the top of the Home page. We're using lib/ansible/generator_helpers.js-> Buttons()
@ -31,19 +31,19 @@ function Home($scope, $compile, $routeParams, $rootScope, $location, Wait, Objec
mode: 'all'
}
};
html = Button({
btn: buttons.refresh,
action: 'refresh',
toolbar: true
});
html += Button({
btn: buttons.stream,
action: 'stream',
toolbar: true
});
e = angular.element(document.getElementById('home-list-actions'));
e.html(html);
$compile(e)($scope);
@ -137,7 +137,7 @@ function HomeGroups($scope, $filter, $compile, $location, $routeParams, LogViewe
opt, PreviousSearchParams;
generator.inject(list, { mode: 'edit', scope: scope });
function ellipsis(a) {
if (a.length > 20) {
return a.substr(0,20) + '...';
@ -299,7 +299,7 @@ function HomeGroups($scope, $filter, $compile, $location, $routeParams, LogViewe
};
scope.editGroup = function (group_id, inventory_id) {
PreviousSearchParams = Store('CurrentSearchParams');
PreviousSearchParams = Store('group_current_search_params');
GroupsEdit({
scope: scope,
group_id: group_id,
@ -335,7 +335,7 @@ function HomeGroups($scope, $filter, $compile, $location, $routeParams, LogViewe
var group = Find({ list: scope.home_groups, key: 'id', val: id });
if (group) {
if (Empty(group.source)) {
// if no source, do nothing.
// 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');
@ -410,7 +410,7 @@ function HomeGroups($scope, $filter, $compile, $location, $routeParams, LogViewe
}
scope.removeGroupSummaryReady = scope.$on('GroupSummaryReady', function(e, event, inventory, data) {
var html, title;
Wait('stop');
// Build the html for our popover

View File

@ -471,238 +471,259 @@ InventoriesAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log
function InventoriesEdit($scope, $location, $routeParams, $compile, $log, $rootScope, GenerateList, ClearScope, InventoryGroups, InventoryHosts, BuildTree, Wait,
GetSyncStatusMsg, InjectHosts, HostsReload, GroupsEdit, GroupsDelete, Breadcrumbs, LoadBreadCrumbs, Empty, Rest, ProcessErrors,
InventoryUpdate, Alert, ToggleChildren, ViewUpdateStatus, GroupsCancelUpdate, Find, EditInventoryProperties, HostsEdit,
HostsDelete, ToggleHostEnabled, CopyMoveGroup, CopyMoveHost, Stream, GetBasePath, ShowJobSummary, ApplyEllipsis, WatchInventoryWindowResize,
HelpDialog, InventoryGroupsHelp, Store, ViewJob, SetContainerHeights) {
function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateList, ClearScope, Empty, Wait, Rest, Alert, LoadBreadCrumbs, GetBasePath, ProcessErrors,
Breadcrumbs, InventoryGroups, InjectHosts, Find, HostsReload, SearchInit, PaginateInit, GetSyncStatusMsg, GetHostsStatusMsg, GroupsEdit, InventoryUpdate,
GroupsCancelUpdate, ViewUpdateStatus, GroupsDelete, Store, HostsEdit, HostsDelete, EditInventoryProperties, ToggleHostEnabled, Stream, ShowJobSummary,
InventoryGroupsHelp, HelpDialog, ViewJob, WatchInventoryWindowResize, SetContainerHeights, GetHostContainerRows, GetGroupContainerRows, GetGroupContainerHeight,
GroupsCopy, HostsCopy)
{
var PreviousSearchParams,
url,
hostScope = $scope.$new();
ClearScope();
var generator = GenerateList,
list = InventoryGroups;
$scope.group_breadcrumbs = [{
name: 'All',
id: 0,
description: '',
show: true,
ngicon: null,
has_children: false,
related: {},
active_class: 'active',
show_failures: false
}];
$scope.inventory_id = $routeParams.inventory_id;
$scope.refreshHostsOnGroupRefresh = false;
$scope.selected_group_id = null;
LoadBreadCrumbs({
path: $location.path(),
title: '{{ inventory_name }}'
});
Wait('start');
// Handle inventory sync status changes
if ($rootScope.removeJobStatusChange) {
$rootScope.removeJobStatusChange();
if ($scope.removeHostReloadComplete) {
$scope.removeHostReloadComplete();
}
$rootScope.removeJobStatusChange = $rootScope.$on('JobStatusChange', function(e, data) {
var group, stat;
Wait('stop');
$log.debug(data);
if ($scope.groups) {
// Assuming we have a list of groups available
group = Find({ list: $scope.groups, key: 'group_id', val: data.group_id });
if (group) {
// And we found the affected group
$log.debug('Received event for group: ' + group.name);
if (data.status === 'failed' || data.status === 'successful') {
$log.debug('Update completed. Refreshing the tree.');
$scope.refreshGroups(group.id, group.group_id);
}
else {
$log.debug('Status 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.removeHostReloadComplete = $scope.$on('HostReloadComplete', function() {
if ($scope.initial_height) {
$('#hosts-container .well').height($scope.initial_height + 49);
$scope.initial_height = null;
}
});
// After the tree data loads for the first time, generate the groups and hosts lists
if ($scope.removeGroupTreeLoaded) {
$scope.removeGroupTreeLoaded();
if ($scope.removeInventoryLoaded) {
$scope.removeInventoryLoaded();
}
$scope.removeGroupTreeLoaded = $scope.$on('GroupTreeLoaded', function (event, inventory_name, groups) {
// Add breadcrumbs
var e, html, inventoryAutoHelp;
$scope.removeInventoryLoaded = $scope.$on('InventoryLoaded', function() {
var e, rows;
LoadBreadCrumbs({
path: $location.path(),
title: '{{ inventory.name }}'
});
// Build page breadcrumbs
e = angular.element(document.getElementById('breadcrumbs'));
e.html(Breadcrumbs({ list: list, mode: 'edit' }));
e.html(Breadcrumbs({ list: InventoryGroups, mode: 'edit' }));
$compile(e)($scope);
// Add groups view
generator.inject(list, {
GenerateList.inject(InventoryGroups, {
mode: 'edit',
id: 'groups-container',
id: 'group-list-container',
breadCrumbs: false,
searchSize: 'col-lg-5 col-md-5 col-sm-5',
skipTableHead: true
searchSize: 'col-lg-6 col-md-6 col-sm-6',
scope: $scope
});
// Keep the table header fixed while allowing the table body to scroll and still use <table> element
html = "<table class=\"table table-condensed\" id=\"groups-table-header\">" + generator.buildHeader() + "</table>\n";
$(html).insertBefore('#groups-container .list-table-container');
/*SetContainerHeights({
group_scope: $scope,
host_scope: hostScope,
reloadHosts: false
});*/
$scope.groups = groups;
$scope.inventory_name = inventory_name;
// Default the selected group to the first node
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;
$scope.selected_group_id = null;
if ($(window).width() > 1210) {
$scope.initial_height = GetGroupContainerHeight() - 20;
$('#groups-container .list-table-container').height($scope.initial_height);
rows = GetGroupContainerRows();
//$('#hosts-container .well').height( height );
}
// Resize the containers based on viewport width/height
SetContainerHeights({ scope: $scope, reloadHosts: false });
else {
rows = 20;
}
hostScope.host_page_size = rows;
$scope.group_page_size = rows;
// 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
group_scope: $scope,
host_scope: hostScope,
inventory_id: $scope.inventory.id,
tree_id: null,
group_id: null,
pageSize: rows
});
// As the window shrinks and expands, apply ellipsis
setTimeout(function () {
// Hack to keep group name from slipping to a new line
$('#groups_table .name-column').each(function () {
var td_width, level_width, level_padding, level, pct;
td_width = $(this).width();
level_width = $(this).find('.level').width();
level_padding = parseInt($(this).find('.level').css('padding-left').replace(/px/, ''));
level = level_width + level_padding;
pct = (100 - Math.ceil((level / td_width) * 100)) + '%';
$(this).find('.group-name').css({
width: pct
SearchInit({ scope: $scope, set: 'groups', list: InventoryGroups, url: $scope.inventory.related.root_groups });
PaginateInit({ scope: $scope, list: InventoryGroups , url: $scope.inventory.related.root_groups, pageSize: rows });
$scope.search(InventoryGroups.iterator, null, true);
});
if ($scope.removePostRefresh) {
$scope.removePostRefresh();
}
$scope.removePostRefresh = $scope.$on('PostRefresh', function(e, set) {
if (set === 'groups') {
$scope.groups.forEach( function(group, idx) {
var stat, hosts_status;
stat = GetSyncStatusMsg({
status: group.summary_fields.inventory_source.status,
has_inventory_sources: group.has_inventory_sources,
source: ( (group.summary_fields.inventory_source) ? group.summary_fields.inventory_source.source : null )
}); // from helpers/Groups.js
$scope.groups[idx].status_class = stat['class'];
$scope.groups[idx].status_tooltip = stat.tooltip;
$scope.groups[idx].launch_tooltip = stat.launch_tip;
$scope.groups[idx].launch_class = stat.launch_class;
hosts_status = GetHostsStatusMsg({
active_failures: group.hosts_with_active_failures,
total_hosts: group.total_hosts,
inventory_id: $scope.inventory.id,
group_id: group.id
}); // from helpers/Groups.js
$scope.groups[idx].hosts_status_tip = hosts_status.tooltip;
$scope.groups[idx].show_failures = hosts_status.failures;
$scope.groups[idx].hosts_status_class = hosts_status['class'];
$scope.groups[idx].source = (group.summary_fields.inventory_source) ? group.summary_fields.inventory_source.source : null;
$scope.groups[idx].status = (group.summary_fields.inventory_source) ? group.summary_fields.inventory_source.status : null;
});
if ($scope.refreshHostsOnGroupRefresh) {
$scope.refreshHostsOnGroupRefresh = false;
HostsReload({
scope: hostScope,
group_id: $scope.selected_group_id,
inventory_id: $scope.inventory.id,
pageSize: hostScope.host_page_size
});
});
ApplyEllipsis('#groups_table .group-name a');
ApplyEllipsis('#hosts_table .host-name a');
}, 2500); //give the window time to display
WatchInventoryWindowResize({ scope: $scope });
inventoryAutoHelp = Store('inventoryAutoHelp');
if (inventoryAutoHelp !== 'off' && $scope.autoShowGroupHelp) {
$scope.showGroupHelp({
autoShow: true
});
}
});
// Called after tree data is reloaded on refresh button click.
if ($scope.removeGroupTreeRefreshed) {
$scope.removeGroupTreeRefreshed();
}
$scope.removeGroupTreeRefreshed = $scope.$on('GroupTreeRefreshed', function () {
// Reapply ellipsis to groups
setTimeout(function () {
ApplyEllipsis('#groups_table .group-name a');
}, 2500);
// Reselect the preveiously selected group node, causing host view to refresh.
$scope.showHosts($scope.selected_tree_id, $scope.selected_group_id, false);
});
// Group was deleted. Now we need to refresh the group view.
if ($scope.removeGroupDeleteCompleted) {
$scope.removeGroupDeleteCompleted();
}
$scope.removeGroupDeleteCompleted = $scope.$on('GroupDeleteCompleted', function () {
$scope.selected_tree_id = 1;
$scope.selected_group_id = null;
BuildTree({
scope: $scope,
inventory_id: $scope.inventory_id,
refresh: true
});
});
// Respond to a group drag-n-drop
if ($scope.removeCopMoveGroup) {
$scope.removeCopyMoveGroup();
}
$scope.removeCopyMoveGroup = $scope.$on('CopyMoveGroup', function (e, inbound_tree_id, target_tree_id) {
CopyMoveGroup({
scope: $scope,
target_tree_id: target_tree_id,
inbound_tree_id: inbound_tree_id
});
});
// Respond to a host drag-n-drop
if ($scope.removeCopMoveHost) {
$scope.removeCopyMoveHost();
}
$scope.removeCopyMoveHost = $scope.$on('CopyMoveHost', function (e, target_tree_id, host_id) {
CopyMoveHost({
scope: $scope,
target_tree_id: target_tree_id,
host_id: host_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 = '';
}
}
if (Empty($scope.inventory_id)) {
$scope.inventory_id = $scope.groups[0].inentory_id;
else {
Wait('stop');
}
HostsReload({
scope: $scope,
group_id: group_id,
tree_id: tree_id,
inventory_id: $scope.inventory_id
WatchInventoryWindowResize({
group_scope: $scope,
host_scope: hostScope
});
} else {
Wait('stop');
}
});
// Load Inventory
url = GetBasePath('inventory') + $routeParams.inventory_id + '/';
Rest.setUrl(url);
Rest.get()
.success(function (data) {
$scope.inventory = data;
$scope.$emit('InventoryLoaded');
})
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve inventory: ' + $routeParams.inventory_id +
' GET returned status: ' + status });
});
// Load group on selection
function loadGroups(url) {
SearchInit({ scope: $scope, set: 'groups', list: InventoryGroups, url: url });
PaginateInit({ scope: $scope, list: InventoryGroups , url: url, pageSize: $scope.group_page_size });
$scope.search(InventoryGroups.iterator, null, true, false, true);
}
function setActiveGroupBreadcrumb() {
$scope.group_breadcrumbs.forEach(function(crumb, idx) {
$scope.group_breadcrumbs[idx].active_class = '';
});
$scope.group_breadcrumbs[$scope.group_breadcrumbs.length - 1].active_class = 'active';
$scope.refreshHostsOnGroupRefresh = true;
$scope.selected_group_id = ($scope.group_breadcrumbs[$scope.group_breadcrumbs.length - 1].id === 0) ? null : $scope.group_breadcrumbs[$scope.group_breadcrumbs.length - 1].id;
}
$scope.refreshHosts = function() {
HostsReload({
scope: hostScope,
group_id: $scope.selected_group_id,
inventory_id: $scope.inventory.id,
pageSize: hostScope.host_page_size
});
};
$scope.refreshGroups = function() {
$scope.refreshHostsOnGroupRefresh = true;
$scope.search(InventoryGroups.iterator, null, true, false, true);
};
$scope.restoreSearch = function() {
// Restore search params and related stuff, plus refresh
// groups and hosts lists
SearchInit({
scope: $scope,
set: PreviousSearchParams.set,
list: PreviousSearchParams.list,
url: PreviousSearchParams.defaultUrl,
iterator: PreviousSearchParams.iterator,
sort_order: PreviousSearchParams.sort_order,
setWidgets: false
});
$scope.refreshHostsOnGroupRefresh = true;
$scope.search(InventoryGroups.iterator, null, true, false, true);
};
$scope.groupSelect = function(id) {
var group = Find({ list: $scope.groups, key: 'id', val: id });
$scope.group_breadcrumbs.push(group);
setActiveGroupBreadcrumb();
loadGroups(group.related.children, group.id);
};
$scope.breadcrumbGroupSelect = function(id) {
var i, url;
$scope.group_breadcrumbs.every(function(crumb, idx) {
if (crumb.id === id) {
i = idx;
return false;
}
return true;
});
$scope.group_breadcrumbs = $scope.group_breadcrumbs.slice(0,i + 1);
if (id > 0) {
url = $scope.group_breadcrumbs[$scope.group_breadcrumbs.length - 1].related.children;
}
else {
url = $scope.inventory.related.root_groups;
}
setActiveGroupBreadcrumb();
loadGroups(url);
};
$scope.createGroup = function () {
PreviousSearchParams = Store('group_current_search_params');
GroupsEdit({
scope: $scope,
inventory_id: $scope.inventory_id,
inventory_id: $scope.inventory.id,
group_id: $scope.selected_group_id,
mode: 'add'
});
};
$scope.editGroup = function (group_id, tree_id) {
$scope.editGroup = function (id) {
PreviousSearchParams = Store('group_current_search_params');
GroupsEdit({
scope: $scope,
inventory_id: $scope.inventory_id,
group_id: group_id,
tree_id: tree_id,
groups_reload: true,
inventory_id: $scope.inventory.id,
group_id: id,
mode: 'edit'
});
};
@ -715,7 +736,7 @@ function InventoriesEdit($scope, $location, $routeParams, $compile, $log, $rootS
// 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');
group.name + '</em> Click the <i class="fa fa-refresh"></i> button to monitor the status.', 'alert-info');
} else {
Wait('start');
Rest.setUrl(group.related.inventory_source);
@ -726,109 +747,164 @@ function InventoriesEdit($scope, $location, $routeParams, $compile, $log, $rootS
url: data.related.update,
group_name: data.summary_fields.group.name,
group_source: data.source,
tree_id: group.id,
group_id: group.group_id
group_id: group.id,
});
})
.error(function (data, status) {
Wait('stop');
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve inventory source: ' +
group.related.inventory_source + ' POST returned status: ' + status });
group.related.inventory_source + ' GET returned status: ' + status });
});
}
}
};
$scope.cancelUpdate = function (tree_id) {
GroupsCancelUpdate({ scope: $scope, id: tree_id });
$scope.cancelUpdate = function (id) {
GroupsCancelUpdate({ scope: $scope, id: id });
};
$scope.toggle = function (tree_id) {
// Expand/collapse nodes
ToggleChildren({ scope: $scope, list: list, id: tree_id });
};
$scope.refreshGroups = function (tree_id, group_id) {
// Refresh the tree data when refresh button cicked
if (tree_id) {
$scope.selected_tree_id = tree_id;
$scope.selected_group_id = group_id;
}
BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: true });
};
$scope.viewUpdateStatus = function (tree_id, group_id) {
$scope.viewUpdateStatus = function (id) {
ViewUpdateStatus({
scope: $scope,
tree_id: tree_id,
group_id: group_id
group_id: id
});
};
$scope.deleteGroup = function (tree_id, group_id) {
$scope.copyGroup = function(id) {
PreviousSearchParams = Store('group_current_search_params');
GroupsCopy({
scope: $scope,
group_id: id
});
};
$scope.deleteGroup = function (id) {
GroupsDelete({
scope: $scope,
tree_id: tree_id,
group_id: group_id,
inventory_id: $scope.inventory_id
group_id: id,
inventory_id: $scope.inventory.id
});
};
$scope.createHost = function () {
HostsEdit({ scope: $scope, mode: 'add', host_id: null, selected_group_id: $scope.selected_tree_id, inventory_id: $scope.inventory_id });
};
$scope.editInventoryProperties = function () {
EditInventoryProperties({ scope: $scope, inventory_id: $scope.inventory_id });
EditInventoryProperties({ scope: $scope, inventory_id: $scope.inventory.id });
};
$scope.editHost = function (host_id) {
HostsEdit({ scope: $scope, mode: 'edit', host_id: host_id, inventory_id: $scope.inventory_id });
hostScope.createHost = function () {
HostsEdit({
host_scope: hostScope,
group_scope: $scope,
mode: 'add',
host_id: null,
selected_group_id: $scope.selected_group_id,
inventory_id: $scope.inventory.id
});
};
$scope.deleteHost = function (host_id, host_name) {
HostsDelete({ scope: $scope, host_id: host_id, host_name: host_name });
hostScope.editHost = function (host_id) {
HostsEdit({
host_scope: hostScope,
group_scope: $scope,
mode: 'edit',
host_id: host_id,
inventory_id: $scope.inventory.id
});
};
$scope.toggleHostEnabled = function (host_id, external_source) {
ToggleHostEnabled({ scope: $scope, host_id: host_id, external_source: external_source });
hostScope.deleteHost = function (host_id, host_name) {
HostsDelete({
parent_scope: $scope,
host_scope: hostScope,
host_id: host_id,
host_name: host_name
});
};
hostScope.copyHost = function(id) {
PreviousSearchParams = Store('group_current_search_params');
HostsCopy({
group_scope: $scope,
host_scope: hostScope,
host_id: id
});
};
/*hostScope.restoreSearch = function() {
SearchInit({
scope: hostScope,
set: PreviousSearchParams.set,
list: PreviousSearchParams.list,
url: PreviousSearchParams.defaultUrl,
iterator: PreviousSearchParams.iterator,
sort_order: PreviousSearchParams.sort_order,
setWidgets: false
});
hostScope.search('host');
};*/
hostScope.toggleHostEnabled = function (host_id, external_source) {
ToggleHostEnabled({
parent_scope: $scope,
host_scope: hostScope,
host_id: host_id,
external_source: external_source
});
};
$scope.showGroupActivity = function () {
var url, title, group;
if ($scope.selected_group_id) {
group = Find({
list: $scope.groups,
key: 'id',
val: $scope.selected_tree_id
$scope.group_breadcrumbs.every(function(crumb) {
if (crumb.id === $scope.selected_group_id) {
group = crumb;
return false;
}
return true;
});
url = GetBasePath('activity_stream') + '?group__id=' + $scope.selected_group_id;
title = 'Showing all activities for group ' + group.name;
} else {
title = 'Showing all activities for all ' + $scope.inventory_name + ' groups';
url = GetBasePath('activity_stream') + '?group__inventory__id=' + $scope.inventory_id;
title = 'Showing all activities for all ' + $scope.inventory.name + ' groups';
url = GetBasePath('activity_stream') + '?group__inventory__id=' + $scope.inventory.id;
}
Stream({
scope: $scope,
inventory_name: $scope.inventory_name,
inventory_name: $scope.inventory.name,
url: url,
title: title
title: title,
search_iterator: 'group',
onClose: 'GroupStreamClosed'
});
};
$scope.showHostActivity = function () {
if ($scope.removeGroupStreamClosed) {
$scope.removeGroupStreamClosed();
}
$scope.removeGroupStreamClosed = $scope.$on('GroupStreamClosed', function() {
$scope.refreshGroups();
});
hostScope.showHostActivity = function () {
var url, title;
title = 'Showing all activities for all ' + $scope.inventory_name + ' hosts';
url = GetBasePath('activity_stream') + '?host__inventory__id=' + $scope.inventory_id;
title = 'Showing all activities for all ' + $scope.inventory.name + ' hosts';
url = GetBasePath('activity_stream') + '?host__inventory__id=' + $scope.inventory.id;
Stream({
scope: $scope,
inventory_name: $scope.inventory_name,
scope: hostScope,
inventory_name: $scope.inventory.name,
url: url,
title: title
title: title,
search_iterator: 'host',
onClose: 'HostStreamClosed'
});
};
$scope.showJobSummary = function (job_id) {
if (hostScope.removeHostStreamClosed) {
hostScope.removeHostStreamClosed();
}
hostScope.removeHostStreamClosed = hostScope.$on('HostStreamClosed', function() {
$scope.refreshGroups();
});
hostScope.showJobSummary = function (job_id) {
ShowJobSummary({
job_id: job_id
});
@ -848,19 +924,31 @@ function InventoriesEdit($scope, $location, $routeParams, $compile, $log, $rootS
ViewJob({ scope: $scope, id: id });
};
//Load tree data for the first time
BuildTree({
scope: $scope,
inventory_id: $scope.inventory_id,
refresh: false
$scope.showHosts = function (group_id, show_failures) {
// Clicked on group
if (group_id !== null) {
Wait('start');
hostScope.show_failures = show_failures;
$scope.groupSelect(group_id);
hostScope.hosts = [];
$scope.show_failures = show_failures; // turn on failed hosts filter in hosts view
} else {
Wait('stop');
}
};
if ($scope.removeGroupDeleteCompleted) {
$scope.removeGroupDeleteCompleted();
}
$scope.removeGroupDeleteCompleted = $scope.$on('GroupDeleteCompleted', function() {
$scope.refreshGroups();
});
}
InventoriesEdit.$inject = ['$scope', '$location', '$routeParams', '$compile', '$log', '$rootScope', 'GenerateList', 'ClearScope', 'InventoryGroups', 'InventoryHosts',
'BuildTree', 'Wait', 'GetSyncStatusMsg', 'InjectHosts', 'HostsReload', 'GroupsEdit', 'GroupsDelete', 'Breadcrumbs',
'LoadBreadCrumbs', 'Empty', 'Rest', 'ProcessErrors', 'InventoryUpdate', 'Alert', 'ToggleChildren', 'ViewUpdateStatus', 'GroupsCancelUpdate',
'Find', 'EditInventoryProperties', 'HostsEdit', 'HostsDelete', 'ToggleHostEnabled', 'CopyMoveGroup', 'CopyMoveHost',
'Stream', 'GetBasePath', 'ShowJobSummary', 'ApplyEllipsis', 'WatchInventoryWindowResize', 'HelpDialog', 'InventoryGroupsHelp', 'Store',
'ViewJob', 'SetContainerHeights'
];
InventoriesEdit.$inject = ['$scope', '$location', '$routeParams', '$compile', 'GenerateList', 'ClearScope', 'Empty', 'Wait', 'Rest', 'Alert', 'LoadBreadCrumbs',
'GetBasePath', 'ProcessErrors', 'Breadcrumbs', 'InventoryGroups', 'InjectHosts', 'Find', 'HostsReload', 'SearchInit', 'PaginateInit', 'GetSyncStatusMsg',
'GetHostsStatusMsg', 'GroupsEdit', 'InventoryUpdate', 'GroupsCancelUpdate', 'ViewUpdateStatus', 'GroupsDelete', 'Store', 'HostsEdit', 'HostsDelete',
'EditInventoryProperties', 'ToggleHostEnabled', 'Stream', 'ShowJobSummary', 'InventoryGroupsHelp', 'HelpDialog', 'ViewJob', 'WatchInventoryWindowResize',
'SetContainerHeights', 'GetHostContainerRows', 'GetGroupContainerRows', 'GetGroupContainerHeight', 'GroupsCopy', 'HostsCopy'
];

View File

@ -319,8 +319,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
// Cancel the update process
if (Empty(group)) {
group = Find({ list: scope.groups, key: 'id', val: id });
scope.selected_tree_id = group.id;
scope.selected_group_id = group.group_id;
scope.selected_group_id = group.id;
}
if (group && (group.status === 'running' || group.status === 'pending')) {
@ -615,26 +614,23 @@ function($compile, SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize, Sched
.factory('GroupsEdit', ['$rootScope', '$location', '$log', '$routeParams', '$compile', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'SetNodeName', 'ParseTypeChange', 'GetSourceTypeOptions', 'InventoryUpdate',
'LookUpInit', 'Empty', 'Wait', 'GetChoices', 'UpdateGroup', 'SourceChange', 'Find',
'ParseVariableString', 'ToJSON', 'GroupsScheduleListInit', 'SourceForm', 'SetSchedulesInnerDialogSize', 'BuildTree',
'LookUpInit', 'Empty', 'Wait', 'GetChoices', 'UpdateGroup', 'SourceChange', 'Find', 'WatchInventoryWindowResize',
'ParseVariableString', 'ToJSON', 'GroupsScheduleListInit', 'SourceForm', 'SetSchedulesInnerDialogSize',
function ($rootScope, $location, $log, $routeParams, $compile, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, SetNodeName, ParseTypeChange, GetSourceTypeOptions, InventoryUpdate, LookUpInit, Empty, Wait,
GetChoices, UpdateGroup, SourceChange, Find, ParseVariableString, ToJSON, GroupsScheduleListInit,
SourceForm, SetSchedulesInnerDialogSize, BuildTree) {
GetChoices, UpdateGroup, SourceChange, Find, WatchInventoryWindowResize, ParseVariableString, ToJSON, GroupsScheduleListInit,
SourceForm, SetSchedulesInnerDialogSize) {
return function (params) {
var parent_scope = params.scope,
group_id = params.group_id,
tree_id = params.tree_id,
mode = params.mode, // 'add' or 'edit'
inventory_id = params.inventory_id,
groups_reload = params.groups_reload,
generator = GenerateForm,
group_created = false,
defaultUrl,
master = {},
choicesReady,
base = $location.path().replace(/^\//, '').split('/')[0],
modal_scope = parent_scope.$new(),
properties_scope = parent_scope.$new(),
sources_scope = parent_scope.$new(),
@ -730,7 +726,7 @@ function($compile, SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize, Sched
height: y,
autoOpen: false,
minWidth: 440,
title: 'Edit Group',
title: (mode === 'edit') ? 'Edit Group' : 'Add Group',
closeOnEscape: false,
create: function () {
$('.ui-dialog[aria-describedby="group-modal-dialog"]').find('.ui-dialog-titlebar button').empty().attr({'class': 'close'}).text('x');
@ -1038,14 +1034,8 @@ function($compile, SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize, Sched
}
parent_scope.removeAddTreeRefreshed = parent_scope.$on('GroupTreeRefreshed', function() {
// Clean up
// Change the selected group
if (groups_reload && parent_scope.selected_tree_id !== tree_id) {
parent_scope.showHosts(tree_id, group_id, false);
} else {
Wait('stop');
}
//WatchInventoryWindowResize();
parent_scope.removeAddTreeRefreshed();
Wait('stop');
WatchInventoryWindowResize();
if (modal_scope.searchCleanUp) {
modal_scope.searchCleanup();
}
@ -1062,42 +1052,7 @@ function($compile, SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize, Sched
}
modal_scope.removeSaveComplete = modal_scope.$on('SaveComplete', function (e, error) {
if (!error) {
// Update the parent view with any changes
if (groups_reload) {
$log.debug('calling UpdateGroup group_id: ' + group_id + ' name: ' + properties_scope.name + ' description: ' + properties_scope.description +
'has_inventory_sources: ' + ((sources_scope.source && sources_scope.source.value) ? 'true' : 'false') + ' source: ' + sources_scope.source.value );
UpdateGroup({
scope: parent_scope,
group_id: group_id,
properties: {
name: properties_scope.name,
description: properties_scope.description,
has_inventory_sources: (sources_scope.source && sources_scope.source.value) ? true : false,
source: (sources_scope.source && sources_scope.source.value) ? sources_scope.source.value : ''
}
});
parent_scope.$emit('GroupTreeRefreshed');
} else if (base === 'inventories') {
if (mode === 'add') {
BuildTree({
scope: parent_scope,
inventory_id: inventory_id,
refresh: true,
new_group_id: group_id
});
}
else {
parent_scope.$emit('GroupTreeRefreshed');
}
} else if (base === 'home') {
parent_scope.restoreSearch();
try {
$('#group-modal-dialog').dialog('close');
}
catch(err) {
// ignore
}
}
modal_scope.cancelModal();
}
});
@ -1167,20 +1122,21 @@ function($compile, SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize, Sched
// Cancel
modal_scope.cancelModal = function () {
Wait('stop');
try {
$('#group-modal-dialog').dialog('close');
}
catch(e) {
//ignore
}
//if (modal_scope.searchCleanup) {
// modal_scope.searchCleanup();
//}
//if (base === 'inventories') {
// WatchInventoryWindowResize();
//}
if (modal_scope.searchCleanup) {
modal_scope.searchCleanup();
}
if (parent_scope.restoreSearch) {
parent_scope.restoreSearch();
}
else {
Wait('stop');
}
};
// Save
@ -1463,11 +1419,328 @@ function($compile, SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize, Sched
scope.$emit('DisassociateGroup');
}
};
};
}
])
.factory('GetRootGroups', ['Rest', 'ProcessErrors', 'GetBasePath', function(Rest, ProcessErrors, GetBasePath) {
return function(params) {
var scope = params.scope,
inventory_id = params.inventory_id,
//group_id = params.group_id,
callback = params.callback,
url;
url = GetBasePath('inventory') + inventory_id + '/root_groups/';
Rest.setUrl(url);
Rest.get()
.success(function(data) {
scope.$emit(callback, data.results);
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. GET returned: ' + status });
});
};
}])
.factory('GroupsCopy', ['$compile', 'Rest', 'ProcessErrors', 'CreateDialog', 'GetBasePath', 'Wait', 'GenerateList', 'GroupList', 'SearchInit',
'PaginateInit', 'GetRootGroups',
function($compile, Rest, ProcessErrors, CreateDialog, GetBasePath, Wait, GenerateList, GroupList, SearchInit, PaginateInit, GetRootGroups) {
return function(params) {
var group_id = params.group_id,
parent_scope = params.scope,
scope = parent_scope.$new(),
parent_group = parent_scope.selected_group_id,
buttonSet, url, group;
buttonSet = [{
label: "Cancel",
onClick: function() {
scope.cancel();
},
icon: "fa-times",
"class": "btn btn-default",
"id": "group-copy-cancel-button"
},{
label: "OK",
onClick: function() {
scope.performCopy();
},
icon: "fa-check",
"class": "btn btn-primary",
"id": "group-copy-ok-button"
}];
if (scope.removeGroupsCopyPostRefresh) {
scope.removeGroupsCopyPostRefresh();
}
scope.removeGroupCopyPostRefresh = scope.$on('PostRefresh', function() {
scope.copy_groups.forEach(function(row, i) {
scope.copy_groups[i].checked = '0';
});
Wait('stop');
$('#group-copy-dialog').dialog('open');
$('#group-copy-ok-button').attr('disabled','disabled');
// prevent backspace from navigation when not in input or textarea field
$(document).on("keydown", function (e) {
if (e.which === 8 && !$(e.target).is('input[type="text"], textarea')) {
e.preventDefault();
}
});
});
if (scope.removeCopyDialogReady) {
scope.removeCopyDialogReady();
}
scope.removeCopyDialogReady = scope.$on('CopyDialogReady', function() {
var url = GetBasePath('inventory') + parent_scope.inventory.id + '/groups/';
url += (parent_group) ? '?not__id__in=' + group_id + ',' + parent_group : '?not__id=' + group_id;
GenerateList.inject(GroupList, {
mode: 'lookup',
id: 'copy-select-container',
scope: scope
//,
//instructions: instructions
});
SearchInit({
scope: scope,
set: GroupList.name,
list: GroupList,
url: url
});
PaginateInit({
scope: scope,
list: GroupList,
url: url,
mode: 'lookup'
});
scope.search(GroupList.iterator);
});
if (scope.removeShowDialog) {
scope.removeShowDialog();
}
scope.removeShowDialog = scope.$on('ShowDialog', function() {
var d;
scope.name = group.name;
scope.copy_choice = "copy";
d = angular.element(document.getElementById('group-copy-dialog'));
$compile(d)(scope);
CreateDialog({
id: 'group-copy-dialog',
scope: scope,
buttons: buttonSet,
width: 650,
height: 650,
minWidth: 600,
title: 'Copy or Move Group',
callback: 'CopyDialogReady',
onClose: function() {
scope.cancel();
}
});
});
if (scope.removeRootGroupsReady) {
scope.removeRootGroupsReady();
}
scope.removeRootGroupsReady = scope.$on('RootGroupsReady', function(e, root_groups) {
scope.offer_root_group = true;
scope.use_root_group = false;
root_groups.every(function(row) {
if (row.id === group_id) {
scope.offer_root_group = false;
return false;
}
return true;
});
url = GetBasePath('groups') + group_id + '/';
Rest.setUrl(url);
Rest.get()
.success(function(data) {
group = data;
scope.$emit('ShowDialog');
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. GET returned: ' + status });
});
});
Wait('start');
GetRootGroups({
scope: scope,
group_id: group_id,
inventory_id: parent_scope.inventory.id,
callback: 'RootGroupsReady'
});
scope.cancel = function() {
$(document).off("keydown");
try {
$('#group-copy-dialog').dialog('close');
}
catch(e) {
// ignore
}
scope.searchCleanup();
parent_scope.restoreSearch();
scope.$destroy();
};
scope['toggle_' + GroupList.iterator] = function (id) {
var count = 0,
list = GroupList;
scope[list.name].forEach( function(row, i) {
if (row.id === id) {
if (row.checked === '0') {
scope[list.name][i].checked = '1';
scope[list.name][i].success_class = 'success';
}
else {
scope[list.name][i].checked = '0';
scope[list.name][i].success_class = '';
}
} else {
scope[list.name][i].checked = '0';
scope[list.name][i].success_class = '';
}
});
// Check if any rows are checked
scope[list.name].forEach(function(row) {
if (row.checked === '1') {
count++;
}
});
if (count === 0) {
$('#group-copy-ok-button').attr('disabled','disabled');
}
else {
$('#group-copy-ok-button').removeAttr('disabled');
}
};
scope.toggleUseRootGroup = function() {
var list = GroupList;
//console.log("scope.use_root_group: " + scope.use_root_group);
if (scope.use_root_group) {
$('#group-copy-ok-button').removeAttr('disabled');
}
else {
// check for group selection
$('#group-copy-ok-button').attr('disabled','disabled');
scope[list.name].every(function(row) {
if (row.checked === '1') {
$('#group-copy-ok-button').removeAttr('disabled');
return false;
}
return true;
});
}
};
scope.performCopy = function() {
var list = GroupList,
target,
url;
Wait('start');
if (scope.use_root_group) {
target = null;
}
else {
scope[list.name].every(function(row) {
if (row.checked === '1') {
target = row;
return false;
}
return true;
});
}
if (scope.copy_choice === 'move') {
// Respond to move
// disassociate the group from the original parent
if (scope.removeGroupRemove) {
scope.removeGroupRemove();
}
scope.removeGroupRemove = scope.$on('RemoveGroup', function () {
if (parent_group > 0) {
// Only remove a group from a parent when the parent is a group and not the inventory root
url = GetBasePath('groups') + parent_group + '/children/';
Rest.setUrl(url);
Rest.post({ id: group.id, disassociate: 1 })
.success(function () {
scope.cancel();
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to remove ' + group.name + ' from group ' + parent_group + '. POST returned: ' + status });
});
} else {
scope.cancel();
}
});
// add the new group to the target
url = (target) ?
GetBasePath('groups') + target.id + '/children/' :
GetBasePath('inventory') + parent_scope.inventory.id + '/groups/';
group = {
id: group.id,
name: group.name,
description: group.description,
inventory: parent_scope.inventory.id
};
Rest.setUrl(url);
Rest.post(group)
.success(function () {
scope.$emit('RemoveGroup');
})
.error(function (data, status) {
var target_name = (target) ? target.name : 'inventory';
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to add ' + group.name + ' to ' + target_name + '. POST returned: ' + status });
});
}
else {
// Respond to copy by adding the new group to the target
url = (target) ?
GetBasePath('groups') + target.id + '/children/' :
GetBasePath('inventory') + parent_scope.inventory.id + '/groups/';
group = {
id: group.id,
name: group.name,
description: group.description,
inventory: parent_scope.inventory.id
};
Rest.setUrl(url);
Rest.post(group)
.success(function () {
scope.cancel();
})
.error(function (data, status) {
var target_name = (target) ? target.name : 'inventory';
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to add ' + group.name + ' to ' + target_name + '. POST returned: ' + status
});
});
}
};
};
}])
.factory('ShowUpdateStatus', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'InventoryStatusForm', 'Wait',
function ($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath,

View File

@ -14,7 +14,8 @@
angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'HostListDefinition',
'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'AuthService', 'HostsHelper',
'InventoryHelper', 'RelatedSearchHelper', 'InventoryFormDefinition', 'SelectionHelper',
'HostGroupsFormDefinition', 'VariablesHelper', 'ModalDialog', 'LogViewerHelper'
'HostGroupsFormDefinition', 'VariablesHelper', 'ModalDialog', 'LogViewerHelper',
'GroupListDefinition'
])
.factory('SetEnabledMsg', [ function() {
@ -167,18 +168,21 @@ function($routeParams, Empty, InventoryHosts, GetBasePath, SearchInit, PaginateI
return function(params) {
var scope = params.scope,
parent_scope = params.parent_scope,
group_id = params.group_id,
inventory_id = params.inventory_id,
list = InventoryHosts,
pageSize = (params.pageSize) ? params.pageSize : 20,
url = ( !Empty(group_id) ) ? GetBasePath('groups') + group_id + '/all_hosts/' :
GetBasePath('inventory') + inventory_id + '/hosts/';
scope.search_place_holder='Search ' + scope.selected_group_name;
//if (scope.removePostRefresh) {
// scope.removePostRefresh();
//}
scope.removePostRefresh = scope.$on('PostRefresh', function(e, set) {
if (scope.removeHostsReloadPostRefresh) {
scope.removeHostsReloadPostRefresh();
}
scope.removeHostsReloadPostRefresh = scope.$on('PostRefresh', function(e, set) {
if (set === 'hosts') {
for (var i=0; i < scope.hosts.length; i++) {
//Set tooltip for host enabled flag
@ -187,7 +191,9 @@ function($routeParams, Empty, InventoryHosts, GetBasePath, SearchInit, PaginateI
SetStatus({ scope: scope });
setTimeout(function() { ApplyEllipsis('#hosts_table .host-name a'); }, 2500);
Wait('stop');
scope.$emit('HostReloadComplete');
if (parent_scope) {
parent_scope.$emit('HostReloadComplete');
}
}
});
@ -195,7 +201,7 @@ function($routeParams, Empty, InventoryHosts, GetBasePath, SearchInit, PaginateI
SetContainerHeights({ scope: scope, reloadHosts: false });
SearchInit({ scope: scope, set: 'hosts', list: list, url: url });
PaginateInit({ scope: scope, list: list, url: url });
PaginateInit({ scope: scope, list: list, url: url, pageSize: pageSize });
if ($routeParams.host_name) {
scope[list.iterator + 'InputDisable'] = false;
@ -220,16 +226,18 @@ function($routeParams, Empty, InventoryHosts, GetBasePath, SearchInit, PaginateI
function(GenerateList, InventoryHosts, HostsReload) {
return function(params) {
var scope = params.scope,
var group_scope = params.group_scope,
host_scope = params.host_scope,
inventory_id = params.inventory_id,
group_id = params.group_id,
pageSize = params.pageSize,
generator = GenerateList;
// Inject the list html
generator.inject(InventoryHosts, { scope: scope, mode: 'edit', id: 'hosts-container', breadCrumbs: false, searchSize: 'col-lg-6 col-md-6 col-sm-6' });
generator.inject(InventoryHosts, { scope: host_scope, mode: 'edit', id: 'hosts-container', breadCrumbs: false, searchSize: 'col-lg-6 col-md-6 col-sm-6' });
// Load data
HostsReload({ scope: scope, group_id: group_id, inventory_id: inventory_id });
HostsReload({ scope: host_scope, group_id: group_id, inventory_id: inventory_id, parent_scope: group_scope, cpageSize: pageSize });
};
}])
@ -336,8 +344,7 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostList, Gener
.factory('HostsCreate', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait',
'ToJSON',
'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'ToJSON',
function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, HostsReload, ParseTypeChange, Wait, ToJSON) {
return function(params) {
@ -437,13 +444,13 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
.factory('HostsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'Find', 'SetStatus', 'ApplyEllipsis',
'ToJSON', 'ParseVariableString', 'CreateDialog', 'TextareaResize', 'Empty',
'ToJSON', 'ParseVariableString', 'CreateDialog', 'TextareaResize',
function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, HostsReload, ParseTypeChange, Wait, Find, SetStatus, ApplyEllipsis, ToJSON,
ParseVariableString, CreateDialog, TextareaResize, Empty) {
ParseVariableString, CreateDialog, TextareaResize) {
return function(params) {
var parent_scope = params.scope,
var parent_scope = params.parent_scope,
host_id = params.host_id,
inventory_id = params.inventory_id,
mode = params.mode, // 'add' or 'edit'
@ -451,10 +458,10 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
generator = GenerateForm,
form = HostForm,
defaultUrl,
scope = parent_scope.$new(),
scope = params.host_scope,
master = {},
relatedSets = {},
group, buttons;
buttons, url;
generator.inject(HostForm, { mode: 'edit', id: 'host-modal-dialog', breadCrumbs: false, related: false, scope: scope });
generator.reset();
@ -581,24 +588,26 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
scope.$emit('hostLoaded');
})
.error( function(data, status) {
ProcessErrors(scope, data, status, form,
ProcessErrors(parent_scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve host: ' + host_id + '. GET returned status: ' + status });
});
}
else {
// Add mode
group = Find({ list: scope.groups, key: 'id', val: selected_group_id });
if (!Empty(group)) {
scope.has_inventory_sources = group.has_inventory_sources;
scope.enabled = true;
scope.variables = '---';
defaultUrl = GetBasePath('groups') + group.group_id + '/hosts/';
scope.$emit('hostVariablesLoaded');
}
else {
ProcessErrors(scope, null, status, null, { hdr: 'Error',
msg: 'Group lookup failed. Selected group id: ' + selected_group_id });
}
url = GetBasePath('groups') + selected_group_id + '/';
Rest.setUrl(url);
Rest.get()
.success( function(data) {
scope.has_inventory_sources = data.has_inventory_sources;
scope.enabled = true;
scope.variables = '---';
defaultUrl = data.related.hosts;
scope.$emit('hostVariablesLoaded');
})
.error( function(data, status) {
ProcessErrors(parent_scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve group: ' + selected_group_id + '. GET returned status: ' + status });
});
}
if (scope.removeSaveCompleted) {
@ -608,12 +617,12 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
var host, old_name;
if (mode === 'edit') {
// Update the name on the list
host = Find({ list: parent_scope.hosts, key: 'id', val: host_id });
host = Find({ list: scope.hosts, key: 'id', val: host_id });
old_name = host.name;
host.name = scope.name;
host.enabled = (scope.enabled) ? true : false;
host.enabled_flag = host.enabled;
SetStatus({ scope: parent_scope, host: host });
SetStatus({ scope: scope, host: host });
// Update any titles attributes created by ApplyEllipsis
if (old_name) {
setTimeout(function() {
@ -630,12 +639,7 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
}
else {
$('#host-modal-dialog').dialog('close');
HostsReload({
scope: parent_scope,
group_id: parent_scope.selected_group_id,
tree_id: parent_scope.selected_tree_id,
inventory_id: parent_scope.inventory_id
});
parent_scope.refreshHosts();
}
// Restore ellipsis response to window resize
@ -691,48 +695,38 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
};
scope.cancelModal = function() {
$('#host-modal-dialog').dialog('close');
try {
$('#host-modal-dialog').dialog('close');
}
catch(err) {
// ignore
}
parent_scope.refreshHosts();
};
};
}])
.factory('HostsDelete', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'Prompt', 'ProcessErrors', 'GetBasePath',
'HostsReload', 'Wait', 'Find', 'Empty',
function($rootScope, $location, $log, $routeParams, Rest, Alert, Prompt, ProcessErrors, GetBasePath, HostsReload, Wait, Find, Empty) {
.factory('HostsDelete', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'Wait',
function($rootScope, $location, $log, $routeParams, Rest, Alert, Prompt, ProcessErrors, GetBasePath, HostsReload, Wait) {
return function(params) {
// Remove the selected host from the current group by disassociating
var action_to_take, body,
scope = params.scope,
scope = params.parent_scope,
host_id = params.host_id,
host_name = params.host_name,
group,
url_list = [];
function getChildren(tree_id) {
var parent, found, j;
for (j = 0; j < scope.groups.length; j++) {
if (scope.groups[j].id === tree_id || scope.groups[j].parent === parent) {
found = true;
url_list.push(GetBasePath('groups') + scope.groups[j].group_id + '/hosts/');
parent = scope.groups[j].id;
}
else {
if (found) {
break;
}
}
}
}
if (!Empty(scope.selected_group_id)) {
group = Find({ list: scope.groups, key: 'id', val: scope.selected_tree_id });
getChildren(group.id);
if (scope.selected_group_id) {
//group = Find({ list: parent_scope.groups, key: 'id', val: parent_scope.selected_group_id });
//getChildren(group.id);
url_list.push(GetBasePath('groups') + scope.selected_group_id + '/hosts/');
}
else {
url_list.push(GetBasePath('inventory') + scope.inventory_id + '/hosts/');
url_list.push(GetBasePath('inventory') + scope.inventory.id + '/hosts/');
}
if (scope.removeHostsReload) {
@ -740,7 +734,7 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, Prompt, Process
}
scope.removeHostsReload = scope.$on('hostsReload', function() {
$('#prompt-modal').modal('hide');
scope.showHosts(scope.selected_tree_id, scope.selected_group_id, false);
scope.refreshHosts();
});
$('#prompt-modal').on('hidden.bs.modal', function(){ Wait('stop'); });
@ -782,6 +776,243 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, Prompt, Process
};
}])
.factory('HostsCopy', ['$compile', 'Rest', 'ProcessErrors', 'CreateDialog', 'GetBasePath', 'Wait', 'GenerateList', 'GroupList', 'SearchInit',
'PaginateInit',
function($compile, Rest, ProcessErrors, CreateDialog, GetBasePath, Wait, GenerateList, GroupList, SearchInit, PaginateInit) {
return function(params) {
var host_id = params.host_id,
group_scope = params.group_scope,
parent_scope = params.host_scope,
parent_group = group_scope.selected_group_id,
scope = parent_scope.$new(),
buttonSet, url, host;
buttonSet = [{
label: "Cancel",
onClick: function() {
scope.cancel();
},
icon: "fa-times",
"class": "btn btn-default",
"id": "host-copy-cancel-button"
},{
label: "OK",
onClick: function() {
scope.performCopy();
},
icon: "fa-check",
"class": "btn btn-primary",
"id": "host-copy-ok-button"
}];
if (scope.removeHostCopyPostRefresh) {
scope.removeHostCopyPostRefresh();
}
scope.removeHostCopyPostRefresh = scope.$on('PostRefresh', function() {
scope.copy_groups.forEach(function(row, i) {
scope.copy_groups[i].checked = '0';
});
Wait('stop');
$('#host-copy-dialog').dialog('open');
$('#host-copy-ok-button').attr('disabled','disabled');
// prevent backspace from navigation when not in input or textarea field
$(document).on("keydown", function (e) {
if (e.which === 8 && !$(e.target).is('input[type="text"], textarea')) {
e.preventDefault();
}
});
});
if (scope.removeHostCopyDialogReady) {
scope.removeHostCopyDialogReady();
}
scope.removeCopyDialogReady = scope.$on('HostCopyDialogReady', function() {
var url = GetBasePath('inventory') + group_scope.inventory.id + '/groups/';
GenerateList.inject(GroupList, {
mode: 'lookup',
id: 'copy-host-select-container',
scope: scope
//,
//instructions: instructions
});
SearchInit({
scope: scope,
set: GroupList.name,
list: GroupList,
url: url
});
PaginateInit({
scope: scope,
list: GroupList,
url: url,
mode: 'lookup'
});
scope.search(GroupList.iterator, null, true, false);
});
if (scope.removeShowDialog) {
scope.removeShowDialog();
}
scope.removeShowDialog = scope.$on('ShowDialog', function() {
var d;
scope.name = host.name;
scope.copy_choice = "copy";
d = angular.element(document.getElementById('host-copy-dialog'));
$compile(d)(scope);
CreateDialog({
id: 'host-copy-dialog',
scope: scope,
buttons: buttonSet,
width: 650,
height: 650,
minWidth: 600,
title: 'Copy or Move Host',
callback: 'HostCopyDialogReady',
onClose: function() {
scope.cancel();
}
});
});
Wait('start');
url = GetBasePath('hosts') + host_id + '/';
Rest.setUrl(url);
Rest.get()
.success(function(data) {
host = data;
scope.$emit('ShowDialog');
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. GET returned: ' + status });
});
scope.cancel = function() {
$(document).off("keydown");
try {
$('#host-copy-dialog').dialog('close');
}
catch(e) {
// ignore
}
scope.searchCleanup();
group_scope.restoreSearch(); // Restore all parent search stuff and refresh hosts and groups lists
scope.$destroy();
};
scope['toggle_' + GroupList.iterator] = function (id) {
var count = 0,
list = GroupList;
scope[list.name].forEach( function(row, i) {
if (row.id === id) {
if (row.checked === '0') {
scope[list.name][i].checked = '1';
scope[list.name][i].success_class = 'success';
}
else {
scope[list.name][i].checked = '0';
scope[list.name][i].success_class = '';
}
} else {
scope[list.name][i].checked = '0';
scope[list.name][i].success_class = '';
}
});
// Check if any rows are checked
scope[list.name].forEach(function(row) {
if (row.checked === '1') {
count++;
}
});
if (count === 0) {
$('#host-copy-ok-button').attr('disabled','disabled');
}
else {
$('#host-copy-ok-button').removeAttr('disabled');
}
};
scope.performCopy = function() {
var list = GroupList,
target,
url;
Wait('start');
if (scope.use_root_group) {
target = null;
}
else {
scope[list.name].every(function(row) {
if (row.checked === '1') {
target = row;
return false;
}
return true;
});
}
if (scope.copy_choice === 'move') {
// Respond to move
// disassociate the host from the original parent
if (scope.removeHostRemove) {
scope.removeHostRemove();
}
scope.removeHostRemove = scope.$on('RemoveHost', function () {
if (parent_group > 0) {
// Only remove a host from a parent when the parent is a group and not the inventory root
url = GetBasePath('groups') + parent_group + '/hosts/';
Rest.setUrl(url);
Rest.post({ id: host.id, disassociate: 1 })
.success(function () {
scope.cancel();
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to remove ' + host.name + ' from group ' + parent_group + '. POST returned: ' + status });
});
} else {
scope.cancel();
}
});
// add the new host to the target
url = GetBasePath('groups') + target.id + '/hosts/';
Rest.setUrl(url);
Rest.post(host)
.success(function () {
scope.$emit('RemoveHost');
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to add ' + host.name + ' to ' + target.name + '. POST returned: ' + status });
});
}
else {
// Respond to copy by adding the new host to the target
url = GetBasePath('groups') + target.id + '/hosts/';
Rest.setUrl(url);
Rest.post(host)
.success(function () {
scope.cancel();
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to add ' + host.name + ' to ' + target.name + '. POST returned: ' + status
});
});
}
};
};
}])
.factory('EditHostGroups', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm', 'Prompt',
'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait',
function($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath, HostsReload,

View File

@ -279,7 +279,6 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
url += connect + scope[iterator + 'ExtraParms'];
}
url = url.replace(/\&\&/g, '&');
if (calcOnly) {
scope.$emit('searchParamsReady', url);
}

View File

@ -142,6 +142,7 @@ angular.module('InventoryGroupsDefinition', [])
mode: 'all',
ngClick: "copyGroup(group.id)",
awToolTip: 'Copy or move group',
ngShow: "group.id > 0",
dataPlacement: "top"
},
"delete": {

View File

@ -76,6 +76,12 @@ angular.module('InventoryHostsDefinition', [])
awToolTip: 'Edit host',
dataPlacement: 'top'
},
copy: {
mode: 'all',
ngClick: "copyHost(host.id)",
awToolTip: 'Copy or move host to another group',
dataPlacement: "top"
},
"delete": {
//label: 'Delete',
ngClick: "deleteHost(host.id, host.name)",
@ -89,7 +95,7 @@ angular.module('InventoryHostsDefinition', [])
create: {
mode: 'all',
ngClick: "createHost()",
ngHide: 'selected_tree_id == 1', //disable when 'All Hosts' selected
ngHide: '!selected_group_id', //disable when 'All Hosts' selected
awToolTip: "Create a new host"
},
stream: {

View File

@ -92,7 +92,7 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
.factory('StreamBreadCrumbs', ['$rootScope', '$location',
function ($rootScope, $location) {
return function () {
// Load the breadcrumbs array. We have to do things a bit different than Utilities.LoadBreadcrumbs.
// Load the breadcrumbs array. We have to do things a bit different than Utilities.LoadBreadcrumbs.
// Rather than botch that all up, we'll do our own thing here.
$rootScope.breadcrumbs = [];
var path, title, i, j, paths = $location.path().split('/');
@ -188,7 +188,7 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
// labels
obj1 = activity.object1;
obj2 = activity.object2;
// objects
obj1_obj = (activity.summary_fields[obj1]) ? activity.summary_fields[obj1][0] : null;
if (obj1 === obj2) {
@ -279,7 +279,7 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
n, rows, scope;
if (activity) {
// Setup changes field
// Setup changes field
activity.changes_stringified = JSON.stringify(activity.changes, null, '\t');
n = activity.changes_stringified.match(/\n/g);
rows = (n) ? n.length : 1;
@ -300,7 +300,7 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
$('#form-modal').on('show.bs.modal', function () {
$('#form-modal-body').css({
width: 'auto', //probably not needed
height: 'auto', //probably not needed
height: 'auto', //probably not needed
'max-height': '100%'
});
});
@ -349,7 +349,7 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
if (paths.length > 1 && /^\d+/.test(paths[paths.length - 1])) {
type = paths[paths.length - 2];
type = (type === 'inventories') ? 'inventory' : type.replace(/s$/, '');
//defaultUrl += '?object1=' + type + '&object1__id=' +
//defaultUrl += '?object1=' + type + '&object1__id=' +
defaultUrl += '?' + type + '__id=' + paths[paths.length - 1];
} else if (paths.length > 1) {
type = paths[paths.length - 1];
@ -368,7 +368,7 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
// Fix inventory name. The way we're doing breadcrumbs doesn't support bind variables.
if (inventory_name) {
itm = Find({ list: $rootScope.breadcrumbs, key: 'title', val: '{{ inventory_name }}' });
itm = Find({ list: $rootScope.breadcrumbs, key: 'title', val: '{{ inventory.name }}' });
if (itm) {
itm.title = inventory_name;
}
@ -424,7 +424,7 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
scope.activities.forEach(function(activity, i) {
var row = scope.activities[i],
type, url;
if (scope.activities[i].summary_fields.actor) {
scope.activities[i].user = "<a href=\"/#/users/" + scope.activities[i].summary_fields.actor.id + "\">" +
scope.activities[i].summary_fields.actor.username + "</a>";
@ -436,7 +436,7 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
deleted = /^\_delete/;
obj1 = scope.activities[i].object1;
obj2 = scope.activities[i].object2;
if ((obj1 === "schedule" || obj2 === "schedule") && activity.summary_fields.schedule) {
if (activity.summary_fields.inventory_source) {
type = 'inventory_source';

View File

@ -36,6 +36,7 @@
@import "log-viewer.less";
@import "job-details.less";
@import "jobs.less";
@import "inventory-edit.less";
html, body { height: 100%; }
@ -1823,7 +1824,7 @@ tr td button i {
}
#hosts-container.col-lg-6 {
margin-toop: 15px;
margin-top: 15px;
padding-left: 15px;
padding-right: 15px;
}

View File

@ -0,0 +1,123 @@
/*********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* inventory-edit.less
*
* custom animation mixins for ansible-ui
*
*/
#inventory_edit {
#breadcrumbs .nav-path {
margin-bottom: 8px;
}
}
.group-breadcrumbs {
list-style: none;
overflow: hidden;
padding: 0;
margin: 0 0 8px 0;
}
.group-breadcrumbs li {
float: left;
height: 26px;
margin-top: 3px;
margin-bottom: 3px;
}
.group-breadcrumbs li a {
color: @white;
font-weight: normal;
text-decoration: none;
padding: 3px 8px 3px 20px;
background: @blue-dark; /* fallback color */
position: relative;
left: 0;
top: 0;
display: block;
float: left;
}
.group-breadcrumbs li.active a {
background: @grey;
color: @black;
font-weight: normal;
}
.group-breadcrumbs li a:after {
content: " ";
display: block;
width: 0;
height: 0;
border-top: 13px dashed transparent; /* Go big on the size, and let overflow hide */
border-bottom: 13px dashed transparent;
border-left: 11px solid @blue-dark;
position: absolute;
top: 50%;
margin-top: -13px;
left: 100%;
z-index: 2;
}
.group-breadcrumbs li.active a:after {
border-left: 13px solid @grey;
}
.group-breadcrumbs li a:before {
content: " ";
display: block;
width: 0;
height: 0;
border-top: 13px dashed transparent;
border-bottom: 13px dashed transparent;
border-left: 11px solid @white;
position: absolute;
top: 50%;
margin-top: -13px;
margin-left: 1px;
left: 100%;
z-index: 1;
}
.group-breadcrumbs li.active a:before {
border-left: 11px solid @white;
}
#group-copy-dialog,
#host-copy-dialog {
.highlight {
font-size: 16px;
font-weight: bold;
color: red;
padding-right: 5px;
}
.title {
font-weight: bold;
margin-bottom: 15px;
}
.well {
padding-left: 8px;
padding-right: 8px;
padding-top: 8px;
padding-bottom: 8px;
}
.page-row ul li a {
font-size: 12px;
}
.page-row .col-lg-8 {
width: 100%;
}
.page-row .col-md-8 {
width: 100%;
}
}
#copy-group-radio-container .form-group {
margin-left: 20px;
margin-bottom: 10px;
}
#copy-group-target-container .form-group {
margin-top: 10px;
margin-left: 20px;
margin-bottom: 15px;
}
#group-list-container {
.list-actions {
margin-bottom: 0;
}
}

View File

@ -7,7 +7,7 @@
* Build data for the tree selector table used on inventory detail page.
*
*/
'use strict';
angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'PromptDialog'])
@ -101,14 +101,14 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
}
function buildGroups(tree_data, parent, level) {
var children, stat, hosts_status, group,
sorted = SortNodes(tree_data),
expand, show;
sorted.forEach( function(row, i) {
id++;
stat = GetSyncStatusMsg({
status: sorted[i].summary_fields.inventory_source.status,
has_inventory_sources: sorted[i].has_inventory_sources,
@ -131,7 +131,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
show = getShowState(sorted[i].id);
if (show === null) {
// this is a node we haven't seen before, so check the parent expand/collapse state
// If parent is not expanded, then child should be hidden.
// If parent is not expanded, then child should be hidden.
show = true;
if (parent > 0) {
groups.every(function(g) {
@ -249,7 +249,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
])
// Update a group with a set of properties
// Update a group with a set of properties
.factory('UpdateGroup', ['ApplyEllipsis', 'GetSyncStatusMsg', 'Empty',
function (ApplyEllipsis, GetSyncStatusMsg, Empty) {
return function (params) {
@ -258,9 +258,9 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
group_id = params.group_id,
properties = params.properties,
i, p, grp, old_name, stat;
for (i = 0; i < scope.groups.length; i++) {
if (scope.groups[i].group_id === group_id) {
if (scope.groups[i].id === group_id) {
grp = scope.groups[i];
for (p in properties) {
if (p === 'name') {
@ -291,12 +291,12 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
scope.groups[i][p] = properties[p];
}
}
if (scope.groups[i].id === scope.selected_tree_id) {
/*if (scope.groups[i].id === scope.selected_tree_id) {
//Make sure potential group name change gets reflected throughout the page
scope.selected_group_name = scope.groups[i].name;
scope.search_place_holder = 'Search ' + scope.groups[i].name;
scope.hostSearchPlaceholder = 'Search ' + scope.groups[i].name;
}
}*/
}
// Update any titles attributes created by ApplyEllipsis
@ -406,7 +406,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
show: true
});
// Respond to move
// Respond to move
scope.moveGroup = function () {
var url, group, parent;
$('#copy-prompt-modal').modal('hide');

View File

@ -19,7 +19,7 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
.factory('ClearScope', [
function () {
return function () {
$('#form-modal .modal-body').empty();
$('#form-modal2 .modal-body').empty();
@ -59,7 +59,7 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
.factory('ToggleClass', function () {
return function (selector, cssClass) {
// Toggles the existance of a css class on a given element
// Toggles the existance of a css class on a given element
if ($(selector) && $(selector).hasClass(cssClass)) {
$(selector).removeClass(cssClass);
} else if ($(selector)) {
@ -69,7 +69,7 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
})
/*
/*
* Pass in the header and message you want displayed on TB modal dialog found in index.html.
* Assumes an #id of 'alert-modal'. Pass in an optional TB alert class (i.e. alert-danger, alert-success,
* alert-info...). Pass an optional function(){}, if you want a specific action to occur when user
@ -91,7 +91,7 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
backdrop: 'static'
});
scope.disableButtons2 = (disableButtons) ? true : false;
$('#alert-modal2').on('hidden.bs.modal', function () {
if (action) {
action();
@ -238,7 +238,7 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
return (a === 'ies') ? 'y' : '';
}
//Keep a list of path/title mappings. When we see /organizations/XX in the path, for example,
//Keep a list of path/title mappings. When we see /organizations/XX in the path, for example,
//we'll know the actual organization name it maps to.
if (!Empty(crumb)) {
found = false;
@ -288,7 +288,7 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
} else {
//if (/_/.test(paths[i])) {
// replace '_' with space and uppercase each word
//}
//title = paths[i].charAt(0).toUpperCase() + paths[i].slice(1);
title = paths[i].replace(/(?:^|_)\S/g, toUppercase).replace(/_/g, ' ');
@ -313,7 +313,7 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
.factory('HelpDialog', ['$rootScope', '$location', 'Store',
function ($rootScope, $location, Store) {
return function (params) {
var defn = params.defn,
current_step = params.step,
autoShow = params.autoShow || false;
@ -463,9 +463,9 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
])
/*
/*
* Split the current path by '/' and use the array elements from 0 up to and
* including idx as the new path. If no idx value supplied, use 0 to length - 1.
* including idx as the new path. If no idx value supplied, use 0 to length - 1.
*
*/
.factory('ReturnToCaller', ['$location', 'Empty',
@ -496,9 +496,9 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
}
])
/*
* Display a spinning icon in the center of the screen to freeze the
* UI while waiting on async things to complete (i.e. API calls).
/*
* Display a spinning icon in the center of the screen to freeze the
* UI while waiting on async things to complete (i.e. API calls).
* Wait('start' | 'stop');
*
*/
@ -575,16 +575,16 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
}
])
/*
/*
* Make an Options call to the API and retrieve dropdown options
*
* GetChoices({
* scope: Parent $scope
* url: API resource to access
* url: API resource to access
* field: API element in the response object that contains the option list.
* variable: Scope variable that will receive the list.
* callback: Optional. Will issue scope.$emit(callback) on completion.
* choice_name: Optional. Used when list is found in a variable other than 'choices'.
* choice_name: Optional. Used when list is found in a variable other than 'choices'.
* })
*/
.factory('GetChoices', ['Rest', 'ProcessErrors',
@ -655,8 +655,8 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
}
])
/*
* DeugForm({ form: <form object>, scope: <current scope object> });
/*
* DebugForm({ form: <form object>, scope: <current scope object> });
*
* Use to log the $pristine and $valid properties of each form element. Helpful when form
* buttons fail to enable/disable properly.
@ -721,7 +721,7 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
.factory('ApplyEllipsis', [
function () {
return function (selector) {
// Add a hidden element to the DOM. We'll use this to calc the px length of
// Add a hidden element to the DOM. We'll use this to calc the px length of
// our target text.
var tmp = $('#string-test');
if (!tmp.length) {

View File

@ -3,7 +3,7 @@
*
* FormGenerator
*
* Pass in a form definition and get back an html template. Use the.inject() method
* Pass in a form definition and get back an html template. Use the.inject() method
* to add the template to the DOM and compile.
*
*/
@ -123,7 +123,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator
try {
$('#help-modal').empty().dialog('destroy');
} catch (e) {
//ignore any errors should the dialog not be initialized
//ignore any errors should the dialog not be initialized
}
if (options.modal) {
@ -134,7 +134,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator
if (options.modal_title_id) {
this.scope[options.modal_title_id] = (options.mode === 'add') ? form.addTitle : form.editTitle;
} else {
this.scope.formModalHeader = (options.mode === 'add') ? form.addTitle : form.editTitle; //Default title for default modal
this.scope.formModalHeader = (options.mode === 'add') ? form.addTitle : form.editTitle; //Default title for default modal
}
}
if (options.modal_selector) {
@ -189,8 +189,11 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator
}
});
}
if (!this.scope.$$phase) {
this.scope.$digest();
setTimeout(function() {
this.scope.$digest();
}, 100);
}
return this.scope;
@ -201,7 +204,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator
// Get HTML without actually injecting into DOM. Caller is responsible for any injection.
// Example:
// html = GenerateForm.buildHTML(JobVarsPromptForm, { mode: 'edit', modal: true, scope: scope });
this.mode = options.mode;
this.modal = (options.modal) ? true : false;
this.setForm(form);
@ -351,7 +354,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator
active: active,
activate: function () {
// Maintain in local storage of list of all accordions by page, recording
// the active panel for each. If user navigates away and comes back,
// the active panel for each. If user navigates away and comes back,
// we can activate the last panely viewed.
$('.jqui-accordion').each(function () {
var active = $(this).accordion('option', 'active'),
@ -542,7 +545,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator
return html;
}
if (field.type === 'alertblock') {
html += "<div class=\"row\">\n";
html += "<div class=\"";
@ -1030,7 +1033,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator
},
getActions: function (options) {
// Use to add things like Activity Stream to a detail page
// Use to add things like Activity Stream to a detail page
var html = "<div class=\"list-actions\">\n", action;
for (action in this.form.actions) {
if (this.form.actions[action].mode === 'all' || this.form.actions[action].mode === options.mode) {
@ -1102,8 +1105,8 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator
build: function (options) {
//
// Generate HTML. Do NOT call this function directly. Called by inject(). Returns an HTML
// string to be injected into the current view.
// Generate HTML. Do NOT call this function directly. Called by inject(). Returns an HTML
// string to be injected into the current view.
//
var btn, button, fld, field, html = '', i, section, group,
tab, sectionShow, offset, width;
@ -1115,7 +1118,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator
html += this.breadCrumbs(options);
}
}
if (this.form.collapse && this.form.collapseMode === options.mode) {
html += "<div id=\"" + this.form.name + "-collapse-0\" ";
html += (this.form.collapseOpen) ? "data-open=\"true\" " : "";
@ -1337,7 +1340,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator
if (this.form.collapse && this.form.collapseMode === options.mode) {
html += "</div>\n";
}
if ((!this.modal) && options.related && this.form.related) {
html += this.buildCollections(options);
}
@ -1357,7 +1360,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator
if (!options.collapseAlreadyStarted) {
html = "<div id=\"" + this.form.name + "-collapse-1\" class=\"jqui-accordion\">\n";
}
for (itm in form.related) {
collection = form.related[itm];
html += "<h3 class=\"" + itm + "_collapse\">" + (collection.title || collection.editTitle) + "</h3>\n";
@ -1370,7 +1373,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator
}
html += "</div>\n"; // accordion inner
}
if (!options.collapseAlreadyStarted) {
html += "</div>\n"; // accordion body
}
@ -1386,7 +1389,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator
itm = params.related,
collection = form.related[itm],
act, action, fld, cnt, base, fAction;
if (collection.instructions) {
html += "<div class=\"alert alert-info alert-block\">\n";
html += "<button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>\n";

View File

@ -181,45 +181,41 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
if (options.showSearch=== undefined || options.showSearch === true) {
html += "<div class=\"row\">\n";
if (list.name !== 'groups') {
if (options.searchSize) {
html += SearchWidget({
iterator: list.iterator,
template: list,
mini: true,
size: options.searchSize,
searchWidgets: list.searchWidgets
});
} else if (options.mode === 'summary') {
html += SearchWidget({
iterator: list.iterator,
template: list,
mini: true,
size: 'col-lg-6'
});
} else if (options.mode === 'lookup' || options.id !== undefined) {
html += SearchWidget({
iterator: list.iterator,
template: list,
mini: true,
size: 'col-lg-8'
});
} else {
html += SearchWidget({
iterator: list.iterator,
template: list,
mini: true
});
}
if (options.searchSize) {
html += SearchWidget({
iterator: list.iterator,
template: list,
mini: true,
size: options.searchSize,
searchWidgets: list.searchWidgets
});
} else if (options.mode === 'summary') {
html += SearchWidget({
iterator: list.iterator,
template: list,
mini: true,
size: 'col-lg-6'
});
} else if (options.mode === 'lookup' || options.id !== undefined) {
html += SearchWidget({
iterator: list.iterator,
template: list,
mini: true,
size: 'col-lg-8'
});
} else {
html += SearchWidget({
iterator: list.iterator,
template: list,
mini: true
});
}
if (options.mode !== 'lookup') {
//actions
base = $location.path().replace(/^\//, '').split('/')[0];
html += "<div class=\"";
if (list.name === 'groups') {
html += "col-lg-12";
} else if (options.searchSize && !options.listSize) {
if (options.searchSize && !options.listSize) {
// User supplied searchSize, calc the remaining
size = parseInt(options.searchSize.replace(/([A-Z]|[a-z]|\-)/g, ''));
size = (list.searchWidgets) ? list.searchWidgets * size : size;
@ -416,18 +412,16 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
html += "</div>\n"; //well
}
if (list.name !== 'groups') {
if (options.mode === 'lookup' || (options.id && options.id === "form-modal-body")) {
html += PaginateWidget({
set: list.name,
iterator: list.iterator
});
} else {
html += PaginateWidget({
set: list.name,
iterator: list.iterator
});
}
if (options.mode === 'lookup' || (options.id && options.id === "form-modal-body")) {
html += PaginateWidget({
set: list.name,
iterator: list.iterator
});
} else {
html += PaginateWidget({
set: list.name,
iterator: list.iterator
});
}
return html;

View File

@ -3,23 +3,68 @@
<div class="row">
<div class="col-lg-12" id="breadcrumbs"></div>
</div>
<!-- <div class="row">
<div id="hosts-title" class="col-lg-offset-6 col-lg-6">{{ selected_group_name }}</div>
</div> -->
<ul class="group-breadcrumbs">
<li ng-repeat="group_breadcrumb in group_breadcrumbs" ng-class="group_breadcrumb.active_class"><a href="" ng-click="breadcrumbGroupSelect(group_breadcrumb.id)">{{ group_breadcrumb.name }}</a></li>
</ul>
<div class="row">
<div id="groups-container" class="col-lg-6"></div>
<div id="groups-container" class="col-lg-6">
<div id="group-list-container"></div>
</div>
<div id="hosts-container" class="col-lg-6"></div>
</div>
<div id="inventory-modal-container"></div>
<div id="group-copy-dialog" style="display: none;">
<div id="copy-group-radio-container" class="well">
<div class="title"><span class="highlight">1.</span> Copy or move <span ng-bind="name"></span>?</div>
<div class="form-group">
<label class="radio-inline">
<input type="radio" ng-model="copy_choice" value="copy"> Copy
</label>
<label class="radio-inline">
<input type="radio" ng-model="copy_choice" value="move"> Move
</label>
</div>
</div>
<div id="copy-group-target-container" class="well">
<div class="title" ng-show="offer_root_group"><span class="highlight">2.</span> Select a target group below, OR choose the inventory root:
<div class="form-group">
<label><input type="checkbox" ng-model="use_root_group" ng-change="toggleUseRootGroup()"> Use the inventory root</label>
</div>
</div>
<div class="title" ng-show="!offer_root_group"><span class="highlight">2.</span> Select a target group:</div>
<div id="copy-select-container" ng-show="!use_root_group"></div>
</div>
</div>
<div id="host-copy-dialog" style="display: none;">
<div id="copy-group-radio-container" class="well">
<div class="title"><span class="highlight">1.</span> Copy or move <span ng-bind="name"></span>?</div>
<div class="form-group">
<label class="radio-inline">
<input type="radio" ng-model="copy_choice" value="copy"> Copy
</label>
<label class="radio-inline">
<input type="radio" ng-model="copy_choice" value="move"> Move
</label>
</div>
</div>
<div id="copy-group-target-container" class="well">
<div class="title"><span class="highlight">2.</span> Select a target group:</div>
<div id="copy-host-select-container"></div>
</div>
</div>
<div id="group-modal-dialog" style="display: none;">
<ul id="group_tabs" class="nav nav-tabs">
<li class="active"><a id="properties_link" ng-click="toggleTab($event, 'properties_link', 'group_tabs')"
<li class="active"><a id="properties_link" ng-click="toggleTab($event, 'properties_link', 'group_tabs')"
href="#properties-tab" data-toggle="tab">Properties</a></li>
<li ng-show="showSourceTab"><a id="source_link" ng-click="toggleTab($event, 'source_link', 'group_tabs')"
href="#sources-tab" data-toggle="tab">Source</a></li>
<li ng-show="showSchedulesTab"><a id="schedules_link" ng-click="toggleTab($event, 'schedules_link', 'group_tabs')"
<li ng-show="showSchedulesTab"><a id="schedules_link" ng-click="toggleTab($event, 'schedules_link', 'group_tabs')"
href="#schedules-tab" data-toggle="tab">Schedule</a></li>
</ul>
<div class="tab-content">
@ -45,11 +90,11 @@
</div>
</div>
</div>
</div>
</div>
</div>
<div id="host-modal-dialog" style="display: none;" class="dialog-content"></div>
<div id="group-delete-dialog" style="display: none;" class="dialog-content">
<div ng-show="groupsCount > 0 || hostsCount > 0">
<div class="alert alert-info">
@ -59,55 +104,55 @@
<span ng-show="groupsCopunt > 0 && hostsCount == 0"> This group contains {{ groupsCount }} groups. </span>
Delete or promote the group's children?</p>
<div style="width: 50%; margin: 15px auto;">
<div class="radio" ng-show="groupsCount > 0 && hostsCount > 0">
<label>
<input type="radio" ng-model="deleteOption" name="delete_option1" value="preserve-all"> Promote groups and hosts
<input type="radio" ng-model="deleteOption" name="delete_option1" value="preserve-all"> Promote groups and hosts
</label>
</div>
<div class="radio" ng-show="groupsCount > 0 && hostsCount > 0">
<label>
<input type="radio" ng-model="deleteOption" name="delete_option1" value="delete-all"> Delete groups and hosts
<input type="radio" ng-model="deleteOption" name="delete_option1" value="delete-all"> Delete groups and hosts
</label>
</div>
<div class="radio" ng-show="groupsCount > 0 && hostsCount == 0">
<label>
<input type="radio" ng-model="deleteOption" name="delete_option2" value="preserve-all"> Promote groups
<input type="radio" ng-model="deleteOption" name="delete_option2" value="preserve-all"> Promote groups
</label>
</div>
<div class="radio" ng-show="groupsCount > 0 && hostsCount == 0">
<label>
<input type="radio" ng-model="deleteOption" name="delete_option2" value="delete-all"> Delete groups
<input type="radio" ng-model="deleteOption" name="delete_option2" value="delete-all"> Delete groups
</label>
</div>
<div class="radio" ng-show="groupsCount == 0 && hostsCount > 0">
<label>
<input type="radio" ng-model="deleteOption" name="delete_option3" value="preserve-all"> Promote hosts
<input type="radio" ng-model="deleteOption" name="delete_option3" value="preserve-all"> Promote hosts
</label>
</div>
<div class="radio" ng-show="groupsCount == 0 && hostsCount > 0">
<label>
<input type="radio" ng-model="deleteOption" name="delete_option3" value="delete-all"> Delete hosts
<input type="radio" ng-model="deleteOption" name="delete_option3" value="delete-all"> Delete hosts
</label>
</div>
</div>
</div>
<div class="help-container" style="text-align:right;">
<a href="" id="awp-promote" href="" aw-pop-over="{{ helpText }}" aw-tool-tip="Click for help" aw-pop-over-watch="helpText" data-placement="top" data-container="body" data-title="Help" class="help-link"><i class="fa fa-question-circle"></i> click for help</a>
</div>
</div>
<div ng-show="groupsCount == 0 && hostsCount == 0">
<div class="alert alert-info">Delete group <em>{{ group_name }}</em>?</div>
</div>
<div class="alert alert-info">Delete group <em>{{ group_name }}</em>?</div>
</div>
</div>
<div ng-include="'/static/partials/logviewer.html'"></div>
</div>
</div>