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

@@ -299,7 +299,7 @@ function HomeGroups($scope, $filter, $compile, $location, $routeParams, LogViewe
}; };
scope.editGroup = function (group_id, inventory_id) { scope.editGroup = function (group_id, inventory_id) {
PreviousSearchParams = Store('CurrentSearchParams'); PreviousSearchParams = Store('group_current_search_params');
GroupsEdit({ GroupsEdit({
scope: scope, scope: scope,
group_id: group_id, group_id: group_id,

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, function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateList, ClearScope, Empty, Wait, Rest, Alert, LoadBreadCrumbs, GetBasePath, ProcessErrors,
GetSyncStatusMsg, InjectHosts, HostsReload, GroupsEdit, GroupsDelete, Breadcrumbs, LoadBreadCrumbs, Empty, Rest, ProcessErrors, Breadcrumbs, InventoryGroups, InjectHosts, Find, HostsReload, SearchInit, PaginateInit, GetSyncStatusMsg, GetHostsStatusMsg, GroupsEdit, InventoryUpdate,
InventoryUpdate, Alert, ToggleChildren, ViewUpdateStatus, GroupsCancelUpdate, Find, EditInventoryProperties, HostsEdit, GroupsCancelUpdate, ViewUpdateStatus, GroupsDelete, Store, HostsEdit, HostsDelete, EditInventoryProperties, ToggleHostEnabled, Stream, ShowJobSummary,
HostsDelete, ToggleHostEnabled, CopyMoveGroup, CopyMoveHost, Stream, GetBasePath, ShowJobSummary, ApplyEllipsis, WatchInventoryWindowResize, InventoryGroupsHelp, HelpDialog, ViewJob, WatchInventoryWindowResize, SetContainerHeights, GetHostContainerRows, GetGroupContainerRows, GetGroupContainerHeight,
HelpDialog, InventoryGroupsHelp, Store, ViewJob, SetContainerHeights) { GroupsCopy, HostsCopy)
{
var PreviousSearchParams,
url,
hostScope = $scope.$new();
ClearScope(); ClearScope();
var generator = GenerateList, $scope.group_breadcrumbs = [{
list = InventoryGroups; 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({ Wait('start');
path: $location.path(),
title: '{{ inventory_name }}'
});
// Handle inventory sync status changes
if ($rootScope.removeJobStatusChange) { if ($scope.removeHostReloadComplete) {
$rootScope.removeJobStatusChange(); $scope.removeHostReloadComplete();
} }
$rootScope.removeJobStatusChange = $rootScope.$on('JobStatusChange', function(e, data) { $scope.removeHostReloadComplete = $scope.$on('HostReloadComplete', function() {
var group, stat; if ($scope.initial_height) {
Wait('stop'); $('#hosts-container .well').height($scope.initial_height + 49);
$log.debug(data); $scope.initial_height = null;
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;
}
}
} }
}); });
// After the tree data loads for the first time, generate the groups and hosts lists if ($scope.removeInventoryLoaded) {
if ($scope.removeGroupTreeLoaded) { $scope.removeInventoryLoaded();
$scope.removeGroupTreeLoaded();
} }
$scope.removeGroupTreeLoaded = $scope.$on('GroupTreeLoaded', function (event, inventory_name, groups) { $scope.removeInventoryLoaded = $scope.$on('InventoryLoaded', function() {
// Add breadcrumbs var e, rows;
var e, html, inventoryAutoHelp;
LoadBreadCrumbs({
path: $location.path(),
title: '{{ inventory.name }}'
});
// Build page breadcrumbs
e = angular.element(document.getElementById('breadcrumbs')); e = angular.element(document.getElementById('breadcrumbs'));
e.html(Breadcrumbs({ list: list, mode: 'edit' })); e.html(Breadcrumbs({ list: InventoryGroups, mode: 'edit' }));
$compile(e)($scope); $compile(e)($scope);
// Add groups view // Add groups view
generator.inject(list, { GenerateList.inject(InventoryGroups, {
mode: 'edit', mode: 'edit',
id: 'groups-container', id: 'group-list-container',
breadCrumbs: false, breadCrumbs: false,
searchSize: 'col-lg-5 col-md-5 col-sm-5', searchSize: 'col-lg-6 col-md-6 col-sm-6',
skipTableHead: true scope: $scope
}); });
// Keep the table header fixed while allowing the table body to scroll and still use <table> element /*SetContainerHeights({
html = "<table class=\"table table-condensed\" id=\"groups-table-header\">" + generator.buildHeader() + "</table>\n"; group_scope: $scope,
$(html).insertBefore('#groups-container .list-table-container'); host_scope: hostScope,
reloadHosts: false
});*/
$scope.groups = groups; if ($(window).width() > 1210) {
$scope.inventory_name = inventory_name; $scope.initial_height = GetGroupContainerHeight() - 20;
$('#groups-container .list-table-container').height($scope.initial_height);
// Default the selected group to the first node rows = GetGroupContainerRows();
if ($scope.groups.length > 0) { //$('#hosts-container .well').height( height );
$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;
} }
else {
// Resize the containers based on viewport width/height rows = 20;
SetContainerHeights({ scope: $scope, reloadHosts: false }); }
hostScope.host_page_size = rows;
$scope.group_page_size = rows;
// Add hosts view // Add hosts view
$scope.show_failures = false; $scope.show_failures = false;
InjectHosts({ InjectHosts({
scope: $scope, group_scope: $scope,
inventory_id: $scope.inventory_id, host_scope: hostScope,
tree_id: $scope.selected_tree_id, inventory_id: $scope.inventory.id,
group_id: $scope.selected_group_id tree_id: null,
group_id: null,
pageSize: rows
}); });
// As the window shrinks and expands, apply ellipsis SearchInit({ scope: $scope, set: 'groups', list: InventoryGroups, url: $scope.inventory.related.root_groups });
setTimeout(function () { PaginateInit({ scope: $scope, list: InventoryGroups , url: $scope.inventory.related.root_groups, pageSize: rows });
// Hack to keep group name from slipping to a new line $scope.search(InventoryGroups.iterator, null, true);
$('#groups_table .name-column').each(function () { });
var td_width, level_width, level_padding, level, pct;
td_width = $(this).width(); if ($scope.removePostRefresh) {
level_width = $(this).find('.level').width(); $scope.removePostRefresh();
level_padding = parseInt($(this).find('.level').css('padding-left').replace(/px/, '')); }
level = level_width + level_padding; $scope.removePostRefresh = $scope.$on('PostRefresh', function(e, set) {
pct = (100 - Math.ceil((level / td_width) * 100)) + '%'; if (set === 'groups') {
$(this).find('.group-name').css({ $scope.groups.forEach( function(group, idx) {
width: pct 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)) { else {
$scope.inventory_id = $scope.groups[0].inentory_id; Wait('stop');
} }
HostsReload({
scope: $scope, WatchInventoryWindowResize({
group_id: group_id, group_scope: $scope,
tree_id: tree_id, host_scope: hostScope
inventory_id: $scope.inventory_id
}); });
} 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 () { $scope.createGroup = function () {
PreviousSearchParams = Store('group_current_search_params');
GroupsEdit({ GroupsEdit({
scope: $scope, scope: $scope,
inventory_id: $scope.inventory_id, inventory_id: $scope.inventory.id,
group_id: $scope.selected_group_id, group_id: $scope.selected_group_id,
mode: 'add' mode: 'add'
}); });
}; };
$scope.editGroup = function (group_id, tree_id) { $scope.editGroup = function (id) {
PreviousSearchParams = Store('group_current_search_params');
GroupsEdit({ GroupsEdit({
scope: $scope, scope: $scope,
inventory_id: $scope.inventory_id, inventory_id: $scope.inventory.id,
group_id: group_id, group_id: id,
tree_id: tree_id,
groups_reload: true,
mode: 'edit' mode: 'edit'
}); });
}; };
@@ -715,7 +736,7 @@ function InventoriesEdit($scope, $location, $routeParams, $compile, $log, $rootS
// if no source, do nothing. // if no source, do nothing.
} else if (group.status === 'updating') { } else if (group.status === 'updating') {
Alert('Update in Progress', 'The inventory update process is currently running for group <em>' + 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 { } else {
Wait('start'); Wait('start');
Rest.setUrl(group.related.inventory_source); Rest.setUrl(group.related.inventory_source);
@@ -726,109 +747,164 @@ function InventoriesEdit($scope, $location, $routeParams, $compile, $log, $rootS
url: data.related.update, url: data.related.update,
group_name: data.summary_fields.group.name, group_name: data.summary_fields.group.name,
group_source: data.source, group_source: data.source,
tree_id: group.id, group_id: group.id,
group_id: group.group_id
}); });
}) })
.error(function (data, status) { .error(function (data, status) {
Wait('stop');
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve inventory source: ' + 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) { $scope.cancelUpdate = function (id) {
GroupsCancelUpdate({ scope: $scope, id: tree_id }); GroupsCancelUpdate({ scope: $scope, id: id });
}; };
$scope.toggle = function (tree_id) { $scope.viewUpdateStatus = function (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) {
ViewUpdateStatus({ ViewUpdateStatus({
scope: $scope, scope: $scope,
tree_id: tree_id, group_id: id
group_id: group_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({ GroupsDelete({
scope: $scope, scope: $scope,
tree_id: tree_id, group_id: id,
group_id: group_id, inventory_id: $scope.inventory.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 () { $scope.editInventoryProperties = function () {
EditInventoryProperties({ scope: $scope, inventory_id: $scope.inventory_id }); EditInventoryProperties({ scope: $scope, inventory_id: $scope.inventory.id });
}; };
$scope.editHost = function (host_id) { hostScope.createHost = function () {
HostsEdit({ scope: $scope, mode: 'edit', host_id: host_id, inventory_id: $scope.inventory_id }); 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) { hostScope.editHost = function (host_id) {
HostsDelete({ scope: $scope, host_id: host_id, host_name: host_name }); 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) { hostScope.deleteHost = function (host_id, host_name) {
ToggleHostEnabled({ scope: $scope, host_id: host_id, external_source: external_source }); 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 () { $scope.showGroupActivity = function () {
var url, title, group; var url, title, group;
if ($scope.selected_group_id) { if ($scope.selected_group_id) {
group = Find({ $scope.group_breadcrumbs.every(function(crumb) {
list: $scope.groups, if (crumb.id === $scope.selected_group_id) {
key: 'id', group = crumb;
val: $scope.selected_tree_id return false;
}
return true;
}); });
url = GetBasePath('activity_stream') + '?group__id=' + $scope.selected_group_id; url = GetBasePath('activity_stream') + '?group__id=' + $scope.selected_group_id;
title = 'Showing all activities for group ' + group.name; title = 'Showing all activities for group ' + group.name;
} else { } else {
title = 'Showing all activities for all ' + $scope.inventory_name + ' groups'; title = 'Showing all activities for all ' + $scope.inventory.name + ' groups';
url = GetBasePath('activity_stream') + '?group__inventory__id=' + $scope.inventory_id; url = GetBasePath('activity_stream') + '?group__inventory__id=' + $scope.inventory.id;
} }
Stream({ Stream({
scope: $scope, scope: $scope,
inventory_name: $scope.inventory_name, inventory_name: $scope.inventory.name,
url: url, 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; var url, title;
title = 'Showing all activities for all ' + $scope.inventory_name + ' hosts'; title = 'Showing all activities for all ' + $scope.inventory.name + ' hosts';
url = GetBasePath('activity_stream') + '?host__inventory__id=' + $scope.inventory_id; url = GetBasePath('activity_stream') + '?host__inventory__id=' + $scope.inventory.id;
Stream({ Stream({
scope: $scope, scope: hostScope,
inventory_name: $scope.inventory_name, inventory_name: $scope.inventory.name,
url: url, 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({ ShowJobSummary({
job_id: job_id job_id: job_id
}); });
@@ -848,19 +924,31 @@ function InventoriesEdit($scope, $location, $routeParams, $compile, $log, $rootS
ViewJob({ scope: $scope, id: id }); ViewJob({ scope: $scope, id: id });
}; };
//Load tree data for the first time $scope.showHosts = function (group_id, show_failures) {
BuildTree({ // Clicked on group
scope: $scope, if (group_id !== null) {
inventory_id: $scope.inventory_id, Wait('start');
refresh: false 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', InventoriesEdit.$inject = ['$scope', '$location', '$routeParams', '$compile', 'GenerateList', 'ClearScope', 'Empty', 'Wait', 'Rest', 'Alert', 'LoadBreadCrumbs',
'BuildTree', 'Wait', 'GetSyncStatusMsg', 'InjectHosts', 'HostsReload', 'GroupsEdit', 'GroupsDelete', 'Breadcrumbs', 'GetBasePath', 'ProcessErrors', 'Breadcrumbs', 'InventoryGroups', 'InjectHosts', 'Find', 'HostsReload', 'SearchInit', 'PaginateInit', 'GetSyncStatusMsg',
'LoadBreadCrumbs', 'Empty', 'Rest', 'ProcessErrors', 'InventoryUpdate', 'Alert', 'ToggleChildren', 'ViewUpdateStatus', 'GroupsCancelUpdate', 'GetHostsStatusMsg', 'GroupsEdit', 'InventoryUpdate', 'GroupsCancelUpdate', 'ViewUpdateStatus', 'GroupsDelete', 'Store', 'HostsEdit', 'HostsDelete',
'Find', 'EditInventoryProperties', 'HostsEdit', 'HostsDelete', 'ToggleHostEnabled', 'CopyMoveGroup', 'CopyMoveHost', 'EditInventoryProperties', 'ToggleHostEnabled', 'Stream', 'ShowJobSummary', 'InventoryGroupsHelp', 'HelpDialog', 'ViewJob', 'WatchInventoryWindowResize',
'Stream', 'GetBasePath', 'ShowJobSummary', 'ApplyEllipsis', 'WatchInventoryWindowResize', 'HelpDialog', 'InventoryGroupsHelp', 'Store', 'SetContainerHeights', 'GetHostContainerRows', 'GetGroupContainerRows', 'GetGroupContainerHeight', 'GroupsCopy', 'HostsCopy'
'ViewJob', 'SetContainerHeights' ];
];

View File

@@ -319,8 +319,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
// Cancel the update process // Cancel the update process
if (Empty(group)) { if (Empty(group)) {
group = Find({ list: scope.groups, key: 'id', val: id }); group = Find({ list: scope.groups, key: 'id', val: id });
scope.selected_tree_id = group.id; scope.selected_group_id = group.id;
scope.selected_group_id = group.group_id;
} }
if (group && (group.status === 'running' || group.status === 'pending')) { 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', .factory('GroupsEdit', ['$rootScope', '$location', '$log', '$routeParams', '$compile', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'SetNodeName', 'ParseTypeChange', 'GetSourceTypeOptions', 'InventoryUpdate', 'Prompt', 'ProcessErrors', 'GetBasePath', 'SetNodeName', 'ParseTypeChange', 'GetSourceTypeOptions', 'InventoryUpdate',
'LookUpInit', 'Empty', 'Wait', 'GetChoices', 'UpdateGroup', 'SourceChange', 'Find', 'LookUpInit', 'Empty', 'Wait', 'GetChoices', 'UpdateGroup', 'SourceChange', 'Find', 'WatchInventoryWindowResize',
'ParseVariableString', 'ToJSON', 'GroupsScheduleListInit', 'SourceForm', 'SetSchedulesInnerDialogSize', 'BuildTree', 'ParseVariableString', 'ToJSON', 'GroupsScheduleListInit', 'SourceForm', 'SetSchedulesInnerDialogSize',
function ($rootScope, $location, $log, $routeParams, $compile, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors, function ($rootScope, $location, $log, $routeParams, $compile, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, SetNodeName, ParseTypeChange, GetSourceTypeOptions, InventoryUpdate, LookUpInit, Empty, Wait, GetBasePath, SetNodeName, ParseTypeChange, GetSourceTypeOptions, InventoryUpdate, LookUpInit, Empty, Wait,
GetChoices, UpdateGroup, SourceChange, Find, ParseVariableString, ToJSON, GroupsScheduleListInit, GetChoices, UpdateGroup, SourceChange, Find, WatchInventoryWindowResize, ParseVariableString, ToJSON, GroupsScheduleListInit,
SourceForm, SetSchedulesInnerDialogSize, BuildTree) { SourceForm, SetSchedulesInnerDialogSize) {
return function (params) { return function (params) {
var parent_scope = params.scope, var parent_scope = params.scope,
group_id = params.group_id, group_id = params.group_id,
tree_id = params.tree_id,
mode = params.mode, // 'add' or 'edit' mode = params.mode, // 'add' or 'edit'
inventory_id = params.inventory_id, inventory_id = params.inventory_id,
groups_reload = params.groups_reload,
generator = GenerateForm, generator = GenerateForm,
group_created = false, group_created = false,
defaultUrl, defaultUrl,
master = {}, master = {},
choicesReady, choicesReady,
base = $location.path().replace(/^\//, '').split('/')[0],
modal_scope = parent_scope.$new(), modal_scope = parent_scope.$new(),
properties_scope = parent_scope.$new(), properties_scope = parent_scope.$new(),
sources_scope = parent_scope.$new(), sources_scope = parent_scope.$new(),
@@ -730,7 +726,7 @@ function($compile, SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize, Sched
height: y, height: y,
autoOpen: false, autoOpen: false,
minWidth: 440, minWidth: 440,
title: 'Edit Group', title: (mode === 'edit') ? 'Edit Group' : 'Add Group',
closeOnEscape: false, closeOnEscape: false,
create: function () { create: function () {
$('.ui-dialog[aria-describedby="group-modal-dialog"]').find('.ui-dialog-titlebar button').empty().attr({'class': 'close'}).text('x'); $('.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() { parent_scope.removeAddTreeRefreshed = parent_scope.$on('GroupTreeRefreshed', function() {
// Clean up // Clean up
// Change the selected group Wait('stop');
if (groups_reload && parent_scope.selected_tree_id !== tree_id) { WatchInventoryWindowResize();
parent_scope.showHosts(tree_id, group_id, false);
} else {
Wait('stop');
}
//WatchInventoryWindowResize();
parent_scope.removeAddTreeRefreshed();
if (modal_scope.searchCleanUp) { if (modal_scope.searchCleanUp) {
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) { modal_scope.removeSaveComplete = modal_scope.$on('SaveComplete', function (e, error) {
if (!error) { if (!error) {
// Update the parent view with any changes modal_scope.cancelModal();
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
}
}
} }
}); });
@@ -1167,20 +1122,21 @@ function($compile, SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize, Sched
// Cancel // Cancel
modal_scope.cancelModal = function () { modal_scope.cancelModal = function () {
Wait('stop');
try { try {
$('#group-modal-dialog').dialog('close'); $('#group-modal-dialog').dialog('close');
} }
catch(e) { catch(e) {
//ignore //ignore
} }
if (modal_scope.searchCleanup) {
//if (modal_scope.searchCleanup) { modal_scope.searchCleanup();
// modal_scope.searchCleanup(); }
//} if (parent_scope.restoreSearch) {
//if (base === 'inventories') { parent_scope.restoreSearch();
// WatchInventoryWindowResize(); }
//} else {
Wait('stop');
}
}; };
// Save // Save
@@ -1463,11 +1419,328 @@ function($compile, SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize, Sched
scope.$emit('DisassociateGroup'); 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', .factory('ShowUpdateStatus', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'InventoryStatusForm', 'Wait', 'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'InventoryStatusForm', 'Wait',
function ($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath, function ($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath,

View File

@@ -14,7 +14,8 @@
angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'HostListDefinition', angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'HostListDefinition',
'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'AuthService', 'HostsHelper', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'AuthService', 'HostsHelper',
'InventoryHelper', 'RelatedSearchHelper', 'InventoryFormDefinition', 'SelectionHelper', 'InventoryHelper', 'RelatedSearchHelper', 'InventoryFormDefinition', 'SelectionHelper',
'HostGroupsFormDefinition', 'VariablesHelper', 'ModalDialog', 'LogViewerHelper' 'HostGroupsFormDefinition', 'VariablesHelper', 'ModalDialog', 'LogViewerHelper',
'GroupListDefinition'
]) ])
.factory('SetEnabledMsg', [ function() { .factory('SetEnabledMsg', [ function() {
@@ -167,18 +168,21 @@ function($routeParams, Empty, InventoryHosts, GetBasePath, SearchInit, PaginateI
return function(params) { return function(params) {
var scope = params.scope, var scope = params.scope,
parent_scope = params.parent_scope,
group_id = params.group_id, group_id = params.group_id,
inventory_id = params.inventory_id, inventory_id = params.inventory_id,
list = InventoryHosts, list = InventoryHosts,
pageSize = (params.pageSize) ? params.pageSize : 20,
url = ( !Empty(group_id) ) ? GetBasePath('groups') + group_id + '/all_hosts/' : url = ( !Empty(group_id) ) ? GetBasePath('groups') + group_id + '/all_hosts/' :
GetBasePath('inventory') + inventory_id + '/hosts/'; GetBasePath('inventory') + inventory_id + '/hosts/';
scope.search_place_holder='Search ' + scope.selected_group_name; scope.search_place_holder='Search ' + scope.selected_group_name;
//if (scope.removePostRefresh) { if (scope.removeHostsReloadPostRefresh) {
// scope.removePostRefresh(); scope.removeHostsReloadPostRefresh();
//} }
scope.removePostRefresh = scope.$on('PostRefresh', function(e, set) { scope.removeHostsReloadPostRefresh = scope.$on('PostRefresh', function(e, set) {
if (set === 'hosts') { if (set === 'hosts') {
for (var i=0; i < scope.hosts.length; i++) { for (var i=0; i < scope.hosts.length; i++) {
//Set tooltip for host enabled flag //Set tooltip for host enabled flag
@@ -187,7 +191,9 @@ function($routeParams, Empty, InventoryHosts, GetBasePath, SearchInit, PaginateI
SetStatus({ scope: scope }); SetStatus({ scope: scope });
setTimeout(function() { ApplyEllipsis('#hosts_table .host-name a'); }, 2500); setTimeout(function() { ApplyEllipsis('#hosts_table .host-name a'); }, 2500);
Wait('stop'); 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 }); SetContainerHeights({ scope: scope, reloadHosts: false });
SearchInit({ scope: scope, set: 'hosts', list: list, url: url }); 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) { if ($routeParams.host_name) {
scope[list.iterator + 'InputDisable'] = false; scope[list.iterator + 'InputDisable'] = false;
@@ -220,16 +226,18 @@ function($routeParams, Empty, InventoryHosts, GetBasePath, SearchInit, PaginateI
function(GenerateList, InventoryHosts, HostsReload) { function(GenerateList, InventoryHosts, HostsReload) {
return function(params) { return function(params) {
var scope = params.scope, var group_scope = params.group_scope,
host_scope = params.host_scope,
inventory_id = params.inventory_id, inventory_id = params.inventory_id,
group_id = params.group_id, group_id = params.group_id,
pageSize = params.pageSize,
generator = GenerateList; generator = GenerateList;
// Inject the list html // 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 // 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', .factory('HostsCreate', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'ToJSON',
'ToJSON',
function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, GenerateForm, Prompt, ProcessErrors, function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, HostsReload, ParseTypeChange, Wait, ToJSON) { GetBasePath, HostsReload, ParseTypeChange, Wait, ToJSON) {
return function(params) { 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', .factory('HostsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'Find', 'SetStatus', 'ApplyEllipsis', '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, function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, HostsReload, ParseTypeChange, Wait, Find, SetStatus, ApplyEllipsis, ToJSON, GetBasePath, HostsReload, ParseTypeChange, Wait, Find, SetStatus, ApplyEllipsis, ToJSON,
ParseVariableString, CreateDialog, TextareaResize, Empty) { ParseVariableString, CreateDialog, TextareaResize) {
return function(params) { return function(params) {
var parent_scope = params.scope, var parent_scope = params.parent_scope,
host_id = params.host_id, host_id = params.host_id,
inventory_id = params.inventory_id, inventory_id = params.inventory_id,
mode = params.mode, // 'add' or 'edit' mode = params.mode, // 'add' or 'edit'
@@ -451,10 +458,10 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
generator = GenerateForm, generator = GenerateForm,
form = HostForm, form = HostForm,
defaultUrl, defaultUrl,
scope = parent_scope.$new(), scope = params.host_scope,
master = {}, master = {},
relatedSets = {}, relatedSets = {},
group, buttons; buttons, url;
generator.inject(HostForm, { mode: 'edit', id: 'host-modal-dialog', breadCrumbs: false, related: false, scope: scope }); generator.inject(HostForm, { mode: 'edit', id: 'host-modal-dialog', breadCrumbs: false, related: false, scope: scope });
generator.reset(); generator.reset();
@@ -581,24 +588,26 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
scope.$emit('hostLoaded'); scope.$emit('hostLoaded');
}) })
.error( function(data, status) { .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 }); { hdr: 'Error!', msg: 'Failed to retrieve host: ' + host_id + '. GET returned status: ' + status });
}); });
} }
else { else {
// Add mode // Add mode
group = Find({ list: scope.groups, key: 'id', val: selected_group_id }); url = GetBasePath('groups') + selected_group_id + '/';
if (!Empty(group)) { Rest.setUrl(url);
scope.has_inventory_sources = group.has_inventory_sources; Rest.get()
scope.enabled = true; .success( function(data) {
scope.variables = '---'; scope.has_inventory_sources = data.has_inventory_sources;
defaultUrl = GetBasePath('groups') + group.group_id + '/hosts/'; scope.enabled = true;
scope.$emit('hostVariablesLoaded'); scope.variables = '---';
} defaultUrl = data.related.hosts;
else { scope.$emit('hostVariablesLoaded');
ProcessErrors(scope, null, status, null, { hdr: 'Error', })
msg: 'Group lookup failed. Selected group id: ' + selected_group_id }); .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) { if (scope.removeSaveCompleted) {
@@ -608,12 +617,12 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
var host, old_name; var host, old_name;
if (mode === 'edit') { if (mode === 'edit') {
// Update the name on the list // 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; old_name = host.name;
host.name = scope.name; host.name = scope.name;
host.enabled = (scope.enabled) ? true : false; host.enabled = (scope.enabled) ? true : false;
host.enabled_flag = host.enabled; host.enabled_flag = host.enabled;
SetStatus({ scope: parent_scope, host: host }); SetStatus({ scope: scope, host: host });
// Update any titles attributes created by ApplyEllipsis // Update any titles attributes created by ApplyEllipsis
if (old_name) { if (old_name) {
setTimeout(function() { setTimeout(function() {
@@ -630,12 +639,7 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
} }
else { else {
$('#host-modal-dialog').dialog('close'); $('#host-modal-dialog').dialog('close');
HostsReload({ parent_scope.refreshHosts();
scope: parent_scope,
group_id: parent_scope.selected_group_id,
tree_id: parent_scope.selected_tree_id,
inventory_id: parent_scope.inventory_id
});
} }
// Restore ellipsis response to window resize // Restore ellipsis response to window resize
@@ -691,48 +695,38 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
}; };
scope.cancelModal = function() { 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', .factory('HostsDelete', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'Wait',
'HostsReload', 'Wait', 'Find', 'Empty', function($rootScope, $location, $log, $routeParams, Rest, Alert, Prompt, ProcessErrors, GetBasePath, HostsReload, Wait) {
function($rootScope, $location, $log, $routeParams, Rest, Alert, Prompt, ProcessErrors, GetBasePath, HostsReload, Wait, Find, Empty) {
return function(params) { return function(params) {
// Remove the selected host from the current group by disassociating // Remove the selected host from the current group by disassociating
var action_to_take, body, var action_to_take, body,
scope = params.scope, scope = params.parent_scope,
host_id = params.host_id, host_id = params.host_id,
host_name = params.host_name, host_name = params.host_name,
group, group,
url_list = []; url_list = [];
function getChildren(tree_id) { if (scope.selected_group_id) {
var parent, found, j; //group = Find({ list: parent_scope.groups, key: 'id', val: parent_scope.selected_group_id });
for (j = 0; j < scope.groups.length; j++) { //getChildren(group.id);
if (scope.groups[j].id === tree_id || scope.groups[j].parent === parent) { url_list.push(GetBasePath('groups') + scope.selected_group_id + '/hosts/');
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);
} }
else { else {
url_list.push(GetBasePath('inventory') + scope.inventory_id + '/hosts/'); url_list.push(GetBasePath('inventory') + scope.inventory.id + '/hosts/');
} }
if (scope.removeHostsReload) { if (scope.removeHostsReload) {
@@ -740,7 +734,7 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, Prompt, Process
} }
scope.removeHostsReload = scope.$on('hostsReload', function() { scope.removeHostsReload = scope.$on('hostsReload', function() {
$('#prompt-modal').modal('hide'); $('#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'); }); $('#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', .factory('EditHostGroups', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm', 'Prompt',
'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait',
function($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath, HostsReload, 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 += connect + scope[iterator + 'ExtraParms'];
} }
url = url.replace(/\&\&/g, '&'); url = url.replace(/\&\&/g, '&');
if (calcOnly) { if (calcOnly) {
scope.$emit('searchParamsReady', url); scope.$emit('searchParamsReady', url);
} }

View File

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

View File

@@ -76,6 +76,12 @@ angular.module('InventoryHostsDefinition', [])
awToolTip: 'Edit host', awToolTip: 'Edit host',
dataPlacement: 'top' dataPlacement: 'top'
}, },
copy: {
mode: 'all',
ngClick: "copyHost(host.id)",
awToolTip: 'Copy or move host to another group',
dataPlacement: "top"
},
"delete": { "delete": {
//label: 'Delete', //label: 'Delete',
ngClick: "deleteHost(host.id, host.name)", ngClick: "deleteHost(host.id, host.name)",
@@ -89,7 +95,7 @@ angular.module('InventoryHostsDefinition', [])
create: { create: {
mode: 'all', mode: 'all',
ngClick: "createHost()", 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" awToolTip: "Create a new host"
}, },
stream: { stream: {

View File

@@ -368,7 +368,7 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
// Fix inventory name. The way we're doing breadcrumbs doesn't support bind variables. // Fix inventory name. The way we're doing breadcrumbs doesn't support bind variables.
if (inventory_name) { 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) { if (itm) {
itm.title = inventory_name; itm.title = inventory_name;
} }

View File

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

@@ -260,7 +260,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
i, p, grp, old_name, stat; i, p, grp, old_name, stat;
for (i = 0; i < scope.groups.length; i++) { 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]; grp = scope.groups[i];
for (p in properties) { for (p in properties) {
if (p === 'name') { if (p === 'name') {
@@ -291,12 +291,12 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
scope.groups[i][p] = properties[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 //Make sure potential group name change gets reflected throughout the page
scope.selected_group_name = scope.groups[i].name; scope.selected_group_name = scope.groups[i].name;
scope.search_place_holder = 'Search ' + scope.groups[i].name; scope.search_place_holder = 'Search ' + scope.groups[i].name;
scope.hostSearchPlaceholder = 'Search ' + scope.groups[i].name; scope.hostSearchPlaceholder = 'Search ' + scope.groups[i].name;
} }*/
} }
// Update any titles attributes created by ApplyEllipsis // Update any titles attributes created by ApplyEllipsis

View File

@@ -656,7 +656,7 @@ 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 * Use to log the $pristine and $valid properties of each form element. Helpful when form
* buttons fail to enable/disable properly. * buttons fail to enable/disable properly.

View File

@@ -189,8 +189,11 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'Utilities', 'ListGenerator
} }
}); });
} }
if (!this.scope.$$phase) { if (!this.scope.$$phase) {
this.scope.$digest(); setTimeout(function() {
this.scope.$digest();
}, 100);
} }
return this.scope; return this.scope;

View File

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

View File

@@ -3,16 +3,61 @@
<div class="row"> <div class="row">
<div class="col-lg-12" id="breadcrumbs"></div> <div class="col-lg-12" id="breadcrumbs"></div>
</div> </div>
<!-- <div class="row">
<div id="hosts-title" class="col-lg-offset-6 col-lg-6">{{ selected_group_name }}</div> <ul class="group-breadcrumbs">
</div> --> <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 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 id="hosts-container" class="col-lg-6"></div>
</div> </div>
<div id="inventory-modal-container"></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;"> <div id="group-modal-dialog" style="display: none;">
<ul id="group_tabs" class="nav nav-tabs"> <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')"