AC-373 Inventory page layout changes. Removed tabs and menu to make better use of limited page real estate

This commit is contained in:
chouseknecht 2013-08-27 13:46:34 -04:00
parent 0129036b40
commit fe03a789b6
21 changed files with 995 additions and 821 deletions

View File

@ -29,6 +29,8 @@ angular.module('ansible', [
'InventoriesListDefinition',
'InventoryFormDefinition',
'InventoryHelper',
'InventoryHostsFormDefinition',
'InventoryGroupsFormDefinition',
'AWFilters',
'HostFormDefinition',
'HostListDefinition',
@ -115,6 +117,12 @@ angular.module('ansible', [
when('/inventories/:id',
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: InventoriesEdit }).
when('/inventories/:inventory_id/hosts',
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: InventoryHosts }).
when('/inventories/:inventory_id/groups',
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: InventoryGroups }).
when('/organizations', { templateUrl: urlPrefix + 'partials/organizations.html',
controller: OrganizationsList }).

View File

@ -0,0 +1,194 @@
/************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Groups.js
*
* Controller functions for the Groups model.
*
*/
function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryGroupsForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInit, Prompt,
OrganizationList, TreeInit, GetBasePath, GroupsList, GroupsAdd, GroupsEdit, LoadInventory,
GroupsDelete, HostsList, HostsAdd, HostsEdit, HostsDelete, RefreshGroupName, ParseTypeChange,
HostsReload, EditInventory, RefreshTree, LoadSearchTree, EditHostGroups)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var generator = GenerateForm;
var form = InventoryGroupsForm;
var defaultUrl=GetBasePath('inventory');
var scope = generator.inject(form, { mode: 'edit', related: true, buildTree: true });
var base = $location.path().replace(/^\//,'').split('/')[0];
var id = $routeParams.inventory_id;
scope['inventory_id'] = id;
// Retrieve each related sets and any lookups
if (scope.inventoryLoadedRemove) {
scope.inventoryLoadedRemove();
}
scope.inventoryLoadedRemove = scope.$on('inventoryLoaded', function() {
LoadBreadCrumbs({ path: '/inventories/' + id, title: scope.inventory_name });
TreeInit(scope.TreeParams);
if (!scope.$$phase) {
scope.$digest();
}
});
LoadInventory({ scope: scope, doPostSteps: true });
scope.treeController = function($node) {
var nodeType = $($node).attr('type');
if (nodeType == 'inventory') {
return {
editInventory: {
label: 'Inventory Properties',
action: function(obj) {
scope.group_id = null;
if (!scope.$$phase) {
scope.$digest();
}
EditInventory({ scope: scope, "inventory_id": id });
},
separator_after: true
},
addGroup: {
label: 'Create New Group',
action: function(obj) {
scope.group_id = null;
if (!scope.$$phase) {
scope.$digest();
}
GroupsAdd({ "inventory_id": id, group_id: null });
}
}
}
}
else {
return {
edit: {
label: 'Group Properties',
action: function(obj) {
scope.group_id = $(obj).attr('group_id');
if (!scope.$$phase) {
scope.$digest();
}
GroupsEdit({ "inventory_id": id, group_id: $(obj).attr('group_id') });
},
separator_after: true
},
addGroup: {
label: 'Add Existing Group',
action: function(obj) {
scope.group_id = $(obj).attr('group_id');
if (!scope.$$phase) {
scope.$digest();
}
GroupsList({ "inventory_id": id, group_id: $(obj).attr('group_id') });
}
},
createGroup: {
label: 'Create New Group',
action: function(obj) {
scope.group_id = $(obj).attr('group_id');
if (!scope.$$phase) {
scope.$digest();
}
GroupsAdd({ "inventory_id": id, group_id: $(obj).attr('group_id') });
}
},
"delete": {
label: 'Delete Group',
action: function(obj) {
scope.group_id = $(obj).attr('group_id');
if (!scope.$$phase) {
scope.$digest();
}
GroupsDelete({ scope: scope, "inventory_id": id, group_id: $(obj).attr('group_id') });
}
}
}
}
}
scope.$on('NodeSelect', function(e, n) {
// Respond to user clicking on a tree node
var node = $('li[id="' + n.attr.id + '"]');
var type = node.attr('type');
var url;
scope['selectedNode'] = node;
scope['selectedNodeName'] = node.attr('name');
$('#tree-view').jstree('open_node',node);
if (type == 'group') {
url = node.attr('all');
scope.groupAddHide = false;
scope.groupCreateHide = false;
scope.groupEditHide = false;
scope.inventoryEditHide = true;
scope.groupDeleteHide = false;
scope.createButtonShow = true;
scope.group_id = node.attr('group_id');
//scope.groupName = n.data;
//scope.groupTitle = '<h4>' + n.data + '</h4>';
//scope.groupTitle += (node.attr('description')) ? '<p>' + node.attr('description') + '</p>' : '';
}
else if (type == 'inventory') {
url = node.attr('hosts');
scope.groupAddHide = true;
scope.groupCreateHide = false;
scope.groupEditHide =true;
scope.inventoryEditHide=false;
scope.groupDeleteHide = true;
scope.createButtonShow = false;
//scope.groupName = 'All Hosts';
//scope.groupTitle = '<h4>All Hosts</h4>';
scope.group_id = null;
}
if (!scope.$$phase) {
scope.$digest();
}
});
scope.addGroup = function() {
GroupsList({ "inventory_id": id, group_id: scope.group_id });
}
scope.createGroup = function() {
GroupsAdd({ "inventory_id": id, group_id: scope.group_id });
}
scope.editGroup = function() {
GroupsEdit({ "inventory_id": id, group_id: scope.group_id });
}
scope.editInventory = function() {
EditInventory({ scope: scope, inventory_id: id });
}
scope.deleteGroup = function() {
GroupsDelete({ scope: scope, "inventory_id": id, group_id: scope.group_id });
}
}
InventoryGroups.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryGroupsForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'LookUpInit', 'Prompt',
'OrganizationList', 'TreeInit', 'GetBasePath', 'GroupsList', 'GroupsAdd', 'GroupsEdit', 'LoadInventory',
'GroupsDelete', 'HostsList', 'HostsAdd', 'HostsEdit', 'HostsDelete', 'RefreshGroupName',
'ParseTypeChange', 'HostsReload', 'EditInventory', 'RefreshTree', 'LoadSearchTree', 'EditHostGroups'
];

View File

@ -0,0 +1,124 @@
/************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* Hosts.js
*
* Controller functions for the Hosts model.
*
*/
'use strict';
function InventoryHosts ($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryHostsForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInit, Prompt,
GetBasePath, HostsList, HostsAdd, HostsEdit, HostsDelete,
HostsReload, LoadSearchTree, EditHostGroups)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var generator = GenerateForm;
var form = InventoryHostsForm;
var defaultUrl=GetBasePath('inventory');
var scope = generator.inject(form, {mode: 'edit', related: true, buildTree: true});
var base = $location.path().replace(/^\//,'').split('/')[0];
var id = $routeParams.inventory_id;
scope['inventory_id'] = id;
scope['hostAddHide'] = true;
scope['hostCreateHide'] = true;
scope['hosts'] = null;
if (scope.loadBreadCrumbsRemove) {
scope.loadBreadCrumbsRemove();
}
scope.loadBreadCrumbsRemove = scope.$on('hostTabInit', function(e, inventory_name) {
LoadBreadCrumbs({ path: '/inventories/' + id, title: inventory_name });
});
LoadSearchTree({ scope: scope, inventory_id: scope['inventory_id'] });
// Add the selected flag to the hosts set.
if (scope.relatedHostsRemove) {
scope.relatedHostsRemove();
}
scope.relatedHostsRemove = scope.$on('relatedhosts', function() {
scope.toggleAllFlag = false;
for (var i=0; i < scope.hosts.length; i++) {
scope.hosts[i].selected = 0;
}
});
scope.filterHosts = function() {
HostsReload({ scope: scope, inventory_id: scope['inventory_id'], group_id: scope['group_id'] });
}
scope.addHost = function() {
HostsList({ scope: scope, "inventory_id": id, group_id: scope.group_id });
}
scope.createHost = function() {
HostsAdd({ scope: scope, "inventory_id": id, group_id: scope.group_id });
}
scope.editHost = function(host_id, host_name) {
HostsEdit({ scope: scope, "inventory_id": id, group_id: scope.group_id, host_id: host_id, host_name: host_name });
}
scope.editHostGroups = function(host_id) {
EditHostGroups({ inventory_id: id, host_id: host_id });
}
scope.deleteHost = function(host_id, host_name) {
HostsDelete({ scope: scope, "inventory_id": id, group_id: scope.group_id, host_id: host_id, host_name: host_name,
request: 'delete' });
}
scope.viewJobs = function(last_job) {
$location.url('/jobs/?id__int=' + last_job );
}
scope.viewLastEvents = function(host_id, last_job, host_name, last_job_name) {
// Choose View-> Latest job events
LoadBreadCrumbs({ path: '/jobs/' + last_job, title: last_job_name });
$location.url('/jobs/' + last_job + '/job_events/?host=' + escape(host_name));
}
scope.viewLastSummary = function(host_id, last_job, host_name, last_job_name) {
// Choose View-> Latest job events
LoadBreadCrumbs({ path: '/jobs/' + last_job, title: last_job_name });
$location.url('/jobs/' + last_job + '/job_host_summaries/?host=' + escape(host_name));
}
// Respond to the scope.$emit from awTree directive
if (scope.refreshHostRemove) {
scope.refreshHostRemove();
}
scope.refreshHostRemove = scope.$on('refreshHost', function(e, group, title) {
scope.groupTitle = title;
scope.group_id = group;
if (scope.group_id == null) {
scope.hostAddHide = true;
scope.hostCreateHide = true;
scope.hostDeleteHide = true;
}
else {
scope.hostAddHide = false;
scope.hostCreateHide = false;
scope.hostDeleteHide = false;
}
scope['hostDeleteDisabled'] = true;
scope['hostDeleteDisabledClass'] = 'disabled';
HostsReload({ scope: scope, inventory_id: scope['inventory_id'], group_id: group });
});
}
InventoryHosts.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryHostsForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'LookUpInit', 'Prompt',
'GetBasePath', 'HostsList', 'HostsAdd', 'HostsEdit', 'HostsDelete',
'HostsReload', 'LoadSearchTree', 'EditHostGroups'
];

View File

@ -81,6 +81,14 @@ function InventoriesList ($scope, $rootScope, $location, $log, $routeParams, Res
scope.viewFailedJobs = function(id) {
$location.url('/jobs/?inventory__int=' + id + '&status=failed&order_by=status');
}
scope.editHosts = function(id) {
$location.url('/inventories/' + id + '/hosts');
}
scope.editGroups = function(id) {
$location.url('/inventories/' + id + '/groups');
}
}
InventoriesList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'InventoryList', 'GenerateList',
@ -191,12 +199,10 @@ InventoriesAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$lo
'OrganizationList', 'SearchInit', 'PaginateInit', 'LookUpInit', 'GetBasePath', 'ParseTypeChange'];
function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm,
function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInit, Prompt,
OrganizationList, TreeInit, GetBasePath, GroupsList, GroupsAdd, GroupsEdit, LoadInventory,
GroupsDelete, HostsList, HostsAdd, HostsEdit, HostsDelete, RefreshGroupName, ParseTypeChange,
HostsReload, EditInventory, RefreshTree, LoadSearchTree, EditHostGroups)
RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInit, Prompt, OrganizationList,
GetBasePath, LoadInventory, ParseTypeChange, EditInventory, SaveInventory, PostLoadInventory)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
@ -204,79 +210,25 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
var generator = GenerateForm;
var form = InventoryForm;
var defaultUrl=GetBasePath('inventory');
var scope = generator.inject(form, {mode: 'edit', related: true, buildTree: true});
var scope = generator.inject(form, { mode: 'edit', related: true });
var base = $location.path().replace(/^\//,'').split('/')[0];
var id = $routeParams.id;
ParseTypeChange(scope,'inventory_variables', 'inventoryParseType');
$('#inventory-tabs a:first').tab('show'); //activate the hosts tab
scope['inventoryParseType'] = 'yaml';
scope['inventory_id'] = id;
scope['inventoryFailureFilter'] = false;
scope['hostDeleteDisabled'] = true;
scope['hostDeleteDisabledClass'] = 'disabled';
ParseTypeChange(scope,'inventory_variables', 'inventoryParseType');
// Retrieve each related sets and any lookups
if (scope.inventoryLoadedRemove) {
scope.inventoryLoadedRemove();
}
scope.inventoryLoadedRemove = scope.$on('inventoryLoaded', function() {
LoadSearchTree({ scope: scope, inventory_id: scope['inventory_id'] });
TreeInit(scope.TreeParams);
Rest.setUrl(scope.inventoryGroupsUrl);
Rest.get()
.success(function(data, status, headers, config) {
if (data.results.length == 0) {
// No groups exist yet, activate the groups tab
scope.showGroupHelp = true;
$('#inventory-tabs a[href="#inventory-groups"]').tab('show')
}
else {
scope.showGroupHelp = false;
$('#inventory-tabs a[href="#inventory-hosts"]').tab('show')
}
})
.error(function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get inventory groups. GET returned status: ' + status });
});
if (!scope.$$phase) {
scope.$digest();
}
LoadBreadCrumbs({ path: '/inventories/' + id, title: scope.inventory_name });
PostLoadInventory({ scope: scope });
});
// Add the selected flag to the hosts set.
if (scope.relatedHostsRemove) {
scope.relatedHostsRemove();
}
scope.relatedHostsRemove = scope.$on('relatedhosts', function() {
scope.toggleAllFlag = false;
for (var i=0; i < scope.hosts.length; i++) {
scope.hosts[i].selected = 0;
}
});
LoadInventory({ scope: scope, doPostSteps: true });
$('#inventory-tabs a[href="#inventory-hosts"]').on('show.bs.tab', function() {
scope['hosts'] = null;
LoadSearchTree({ scope: scope, inventory_id: scope['inventory_id'] });
if (!scope.$$phase) {
scope.$digest();
}
});
scope.filterInventory = function() {
$rootScope.hostFailureFilter = scope.hostFailureFilter;
LoadSearchTree({ scope: scope, inventory_id: scope['inventory_id'] });
//HostsReload({ scope: scope, inventory_id: scope['inventory_id'], group_id: scope['group_id'] });
}
scope.filterHosts = function() {
HostsReload({ scope: scope, inventory_id: scope['inventory_id'], group_id: scope['group_id'] });
}
LoadInventory({ scope: scope, doPostSteps: false });
// Cancel
scope.formReset = function() {
@ -297,10 +249,16 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
$rootScope.flashMessage = null;
$location.path('/' + base + '/' + $routeParams.id + '/' + set + '/' + id);
};
scope.editInventory = function() {
EditInventory({ scope: scope, 'inventory_id': scope['inventory_id'] });
};
if (scope.removeInventorySaved) {
scope.removeInventorySaved();
}
scope.removeInventorySaved = scope.$on('inventorySaved', function() {
$location.path('/inventories');
});
scope.formSave = function() {
SaveInventory({ scope: scope });
}
// Related set: Delete button
scope['delete'] = function(set, itm_id, name, title) {
@ -327,229 +285,12 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
});
};
scope.treeController = function($node) {
var nodeType = $($node).attr('type');
if (nodeType == 'inventory') {
return {
editInventory: {
label: 'Inventory Properties',
action: function(obj) {
scope.group_id = null;
if (!scope.$$phase) {
scope.$digest();
}
EditInventory({ scope: scope, "inventory_id": id });
},
separator_after: true
},
addGroup: {
label: 'Create New Group',
action: function(obj) {
scope.group_id = null;
if (!scope.$$phase) {
scope.$digest();
}
GroupsAdd({ "inventory_id": id, group_id: null });
}
}
}
}
else {
return {
edit: {
label: 'Group Properties',
action: function(obj) {
scope.group_id = $(obj).attr('group_id');
if (!scope.$$phase) {
scope.$digest();
}
GroupsEdit({ "inventory_id": id, group_id: $(obj).attr('group_id') });
},
separator_after: true
},
addGroup: {
label: 'Add Existing Group',
action: function(obj) {
scope.group_id = $(obj).attr('group_id');
if (!scope.$$phase) {
scope.$digest();
}
GroupsList({ "inventory_id": id, group_id: $(obj).attr('group_id') });
}
},
createGroup: {
label: 'Create New Group',
action: function(obj) {
scope.group_id = $(obj).attr('group_id');
if (!scope.$$phase) {
scope.$digest();
}
GroupsAdd({ "inventory_id": id, group_id: $(obj).attr('group_id') });
}
},
"delete": {
label: 'Delete Group',
action: function(obj) {
scope.group_id = $(obj).attr('group_id');
if (!scope.$$phase) {
scope.$digest();
}
GroupsDelete({ scope: scope, "inventory_id": id, group_id: $(obj).attr('group_id') });
}
}
}
}
}
scope.$on('NodeSelect', function(e, n) {
// Respond to user clicking on a tree node
var node = $('li[id="' + n.attr.id + '"]');
var type = node.attr('type');
var url;
scope['selectedNode'] = node;
scope['selectedNodeName'] = node.attr('name');
$('#tree-view').jstree('open_node',node);
if (type == 'group') {
url = node.attr('all');
scope.groupAddHide = false;
scope.groupCreateHide = false;
scope.groupEditHide = false;
scope.inventoryEditHide = true;
scope.groupDeleteHide = false;
scope.createButtonShow = true;
scope.group_id = node.attr('group_id');
//scope.groupName = n.data;
//scope.groupTitle = '<h4>' + n.data + '</h4>';
//scope.groupTitle += (node.attr('description')) ? '<p>' + node.attr('description') + '</p>' : '';
}
else if (type == 'inventory') {
url = node.attr('hosts');
scope.groupAddHide = true;
scope.groupCreateHide = false;
scope.groupEditHide =true;
scope.inventoryEditHide=false;
scope.groupDeleteHide = true;
scope.createButtonShow = false;
//scope.groupName = 'All Hosts';
//scope.groupTitle = '<h4>All Hosts</h4>';
scope.group_id = null;
}
if (!scope.$$phase) {
scope.$digest();
}
});
scope.addGroup = function() {
GroupsList({ "inventory_id": id, group_id: scope.group_id });
}
scope.createGroup = function() {
GroupsAdd({ "inventory_id": id, group_id: scope.group_id });
}
scope.editGroup = function() {
GroupsEdit({ "inventory_id": id, group_id: scope.group_id });
}
scope.deleteGroup = function() {
GroupsDelete({ scope: scope, "inventory_id": id, group_id: scope.group_id });
}
scope.addHost = function() {
HostsList({ scope: scope, "inventory_id": id, group_id: scope.group_id });
}
scope.createHost = function() {
HostsAdd({ scope: scope, "inventory_id": id, group_id: scope.group_id });
}
scope.editHost = function(host_id, host_name) {
HostsEdit({ scope: scope, "inventory_id": id, group_id: scope.group_id, host_id: host_id, host_name: host_name });
}
scope.editHostGroups = function(host_id) {
EditHostGroups({ inventory_id: id, host_id: host_id });
}
scope.deleteHost = function(host_id, host_name) {
HostsDelete({ scope: scope, "inventory_id": id, group_id: scope.group_id, host_id: host_id, host_name: host_name,
request: 'delete' });
}
scope.viewJobs = function(last_job) {
$location.url('/jobs/?id__int=' + last_job );
}
scope.viewLastEvents = function(host_id, last_job, host_name, last_job_name) {
// Choose View-> Latest job events
LoadBreadCrumbs({ path: '/jobs/' + last_job, title: last_job_name });
$location.url('/jobs/' + last_job + '/job_events/?host=' + escape(host_name));
}
scope.viewLastSummary = function(host_id, last_job, host_name, last_job_name) {
// Choose View-> Latest job events
LoadBreadCrumbs({ path: '/jobs/' + last_job, title: last_job_name });
$location.url('/jobs/' + last_job + '/job_host_summaries/?host=' + escape(host_name));
}
scope.toggleAllHosts = function() {
scope.hostDeleteDisabled = (scope.toggleAllFlag) ? false : true;
scope.hostDeleteDisabledClass = (scope.hostDeleteDisabled) ? "disabled" : "";
for (var i=0; i < scope.hosts.length; i++) {
scope.hosts[i].selected = scope.toggleAllFlag;
}
}
scope.toggleOneHost = function() {
var result = true;
for (var i=0; i < scope.hosts.length; i++) {
if (scope.hosts[i].selected) {
result = false;
break;
}
}
scope.hostDeleteDisabled = result;
scope.hostDeleteDisabledClass = (scope.hostDeleteDisabled) ? "disabled" : "";
}
// Respond to the scope.$emit from awTree directive
scope.$on('refreshHost', function(e, group, title) {
scope.groupTitle = title;
scope.group_id = group;
if (scope.group_id == null) {
scope.hostAddHide = true;
scope.hostCreateHide = true;
scope.hostDeleteHide = true;
}
else {
scope.hostAddHide = false;
scope.hostCreateHide = false;
scope.hostDeleteHide = false;
}
scope['hostDeleteDisabled'] = true;
scope['hostDeleteDisabledClass'] = 'disabled';
HostsReload({ scope: scope, inventory_id: scope['inventory_id'], group_id: group });
});
}
InventoriesEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'LookUpInit', 'Prompt',
'OrganizationList', 'TreeInit', 'GetBasePath', 'GroupsList', 'GroupsAdd', 'GroupsEdit', 'LoadInventory',
'GroupsDelete', 'HostsList', 'HostsAdd', 'HostsEdit', 'HostsDelete', 'RefreshGroupName',
'ParseTypeChange', 'HostsReload', 'EditInventory', 'RefreshTree', 'LoadSearchTree', 'EditHostGroups'
'OrganizationList', 'GetBasePath', 'LoadInventory', 'ParseTypeChange', 'EditInventory',
'SaveInventory', 'PostLoadInventory'
];

View File

@ -15,9 +15,6 @@ angular.module('InventoryFormDefinition', [])
name: 'inventory',
parseTypeName: 'inventoryParseType',
well: true,
/*,
formLabelSize: 'col-lg-3',
formFieldSize: 'col-lg-9',*/
fields: {
inventory_name: {
@ -63,7 +60,7 @@ angular.module('InventoryFormDefinition', [])
'<p>View YAML examples at <a href="http://www.ansibleworks.com/docs/YAMLSyntax.html" target="_blank">ansibleworks.com</a></p>',
dataTitle: 'Inventory Variables',
dataPlacement: 'bottom',
dataContainer: '#form-modal .modal-content'
dataContainer: '#inventory'
}
},
@ -86,56 +83,6 @@ angular.module('InventoryFormDefinition', [])
related: {
groups: {
type: 'tree',
open: true,
actions: {
}
},
hosts: {
type: 'treeview',
title: "groupTitle",
iterator: 'host',
actions: {
},
fields: {
name: {
key: true,
label: 'Host Name',
ngClick: "editHost(\{\{ host.id \}\}, '\{\{ host.name \}\}')",
badgeShow: "\{\{ host.has_active_failures \}\}",
badgeIcon: 'icon-exclamation-sign',
badgeToolTip: 'Most recent job failed',
badgePlacement: 'bottom',
columnClass: 'col-lg-3'
},
groups: {
label: 'Groups',
searchable: false,
sourceModel: 'groups',
sourceField: 'name',
nosort: true
},
dropdown: {
type: 'DropDown',
label: 'View',
"class": "btn-sm",
ngDisabled: 'host.last_job == null',
options: [
{ ngClick: 'viewJobs(\{\{ host.last_job \}\})', label: 'Latest job' },
{ ngClick: "viewLastEvents(\{\{ host.id \}\}, '\{\{ host.last_job \}\}', '\{\{ host.name \}\}', " +
"'\{\{ host.summary_fields.last_job.name \}\}')", label: 'Latest job events' },
{ ngClick: "viewLastSummary(\{\{ host.id \}\}, '\{\{ host.last_job \}\}', '\{\{ host.name \}\}', " +
"'\{\{ host.summary_fields.last_job.name \}\}')", label: 'Latest host summary' }
]
}
},
fieldActions: {
}
}
}
}); //InventoryForm

View File

@ -0,0 +1,27 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* InventoryGroups.js
* Form definition for Groups model
*
*
*/
angular.module('InventoryGroupsFormDefinition', [])
.value(
'InventoryGroupsForm', {
type: 'groupsview',
title: "groupTitle",
editTitle: 'Groups',
iterator: 'group',
fields: {
},
actions: {
},
fieldActions: {
}
}); //InventoryGroupsForm

View File

@ -0,0 +1,82 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* InventoryHosts.js
* Form definition for Hosts model
*
*
*/
angular.module('InventoryHostsFormDefinition', [])
.value(
'InventoryHostsForm', {
type: 'hostsview',
title: "groupTitle",
editTitle: 'Hosts',
iterator: 'host',
fields: {
name: {
key: true,
label: 'Host Name',
ngClick: "editHost(\{\{ host.id \}\}, '\{\{ host.name \}\}')",
badgeIcon: "\{\{ 'icon-failures-' + host.has_active_failures \}\}",
badgePlacement: 'left',
columnClass: 'col-lg-3'
},
groups: {
label: 'Groups',
searchable: false,
sourceModel: 'groups',
sourceField: 'name',
nosort: true
},
dropdown: {
type: 'DropDown',
searchable: false,
nosort: true,
label: 'View Jobs',
"class": "btn-sm",
//ngDisabled: 'host.last_job == null',
options: [
{ ngClick: 'viewJobs(\{\{ host.last_job \}\})', label: 'Latest job', ngShow: 'host.last_job' },
{ ngClick: "viewLastEvents(\{\{ host.id \}\}, '\{\{ host.last_job \}\}', '\{\{ host.name \}\}', " +
"'\{\{ host.summary_fields.last_job.name \}\}')", label: 'Latest job events', ngShow: 'host.last_job' },
{ ngClick: "viewLastSummary(\{\{ host.id \}\}, '\{\{ host.last_job \}\}', '\{\{ host.name \}\}', " +
"'\{\{ host.summary_fields.last_job.name \}\}')", label: 'Latest host summary', ngShow: 'host.last_job' },
{ ngClick: "", label: 'No job data available', ngShow: 'host.last_job == null' }
]
}
},
actions: {
add: {
label: 'Add Existing Host',
ngClick: "addHost()",
ngHide: "hostAddHide",
awToolTip: "Select from a list of existing hosts",
dataPlacement: 'bottom',
'class': 'btn-xs btn-primary',
icon: 'icon-check'
},
create: {
label: 'Create New Host',
ngClick: 'createHost()',
ngHide: 'hostCreateHide',
awToolTip: 'Create a new host',
dataPlacement: 'bottom',
'class': 'btn-xs btn-success',
icon: 'icon-plus'
}
},
fieldActions: {
"delete": {
ngClick: "deleteHost(\{\{ host.id \}\},'\{\{ host.name \}\}')",
icon: 'icon-trash',
"class": 'btn-sm btn-danger',
awToolTip: 'Delete host'
}
}
}); //InventoryHostsForm

View File

@ -33,7 +33,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
});
scope.formModalActionLabel = 'Select';
scope.formModalHeader = 'Add Groups';
scope.formModalHeader = 'Add Existing Groups';
scope.formModalCancelShow = true;
scope.formModalActionClass = 'btn btn-success';
@ -91,7 +91,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
var scope = generator.inject(form, {mode: 'add', modal: true, related: false});
scope.formModalActionLabel = 'Save';
scope.formModalHeader = 'Create Group';
scope.formModalHeader = 'Create New Group';
scope.formModalCancelShow = true;
scope.parseType = 'yaml';
ParseTypeChange(scope);
@ -185,7 +185,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
return function(params) {
var group_id = params.group_id;
var inventory_id = $routeParams.id;
var inventory_id = params.inventory_id;
var generator = GenerateForm;
var form = GroupForm;
var defaultUrl = GetBasePath('groups') + group_id + '/';

View File

@ -10,7 +10,8 @@
angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'HostListDefinition',
'SearchHelper', 'PaginateHelper', 'ListGenerator', 'AuthService', 'HostsHelper',
'InventoryHelper', 'RelatedSearchHelper','RelatedPaginateHelper',
'InventoryFormDefinition', 'SelectionHelper', 'HostGroupsFormDefinition'
'InventoryFormDefinition', 'SelectionHelper', 'HostGroupsFormDefinition',
'InventoryHostsFormDefinition'
])
.factory('HostsList', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostList', 'GenerateList',
@ -28,7 +29,6 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
list.iterator = 'subhost'; //Override the iterator and name so the scope of the modal dialog
list.name = 'subhosts'; //will not conflict with the parent scope
var defaultUrl = GetBasePath('inventory') + inventory_id + '/hosts/';
var view = GenerateList;
var scope = view.inject(list, {
@ -38,8 +38,10 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
selectButton: false
});
var defaultUrl = GetBasePath('inventory') + inventory_id + '/hosts/?not__groups__id=' + scope.group_id;
scope.formModalActionLabel = 'Select';
scope.formModalHeader = 'Select Hosts';
scope.formModalHeader = 'Add Existing Hosts';
scope.formModalCancelShow = true;
SelectionInit({ scope: scope, list: list, url: GetBasePath('groups') + group_id + '/hosts/' });
@ -89,7 +91,7 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
var scope = generator.inject(form, {mode: 'add', modal: true, related: false});
scope.formModalActionLabel = 'Save';
scope.formModalHeader = 'Create Host';
scope.formModalHeader = 'Create New Host';
scope.formModalCancelShow = true;
scope.parseType = 'yaml';
ParseTypeChange(scope);
@ -349,16 +351,9 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
'HostsReload',
function($rootScope, $location, $log, $routeParams, Rest, Alert, Prompt, ProcessErrors, GetBasePath, HostsReload) {
return function(params) {
// Remove the selected host from the current group by disassociating
var scope = params.scope;
if (scope.hostDeleteDisabled) {
// simulate a disabled link
return;
}
var group_id = scope.group_id;
var inventory_id = params.inventory_id;
var host_id = params.host_id;
@ -376,40 +371,18 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
});
var action_to_take = function() {
var errors = false;
var maxI;
// Find index pointing to the last selected host
for (var i=0; i < scope.hosts.length; i++) {
if (scope.hosts[i].selected) {
maxI = i;
}
}
function emit(i) {
// After we process the last selected host or after we hit a problem, refresh the host list
if (i >= maxI || errors) {
$('#prompt-modal').modal('hide');
scope.$emit('hostsReload');
}
}
Rest.setUrl(url);
for (var i=0; i < scope.hosts.length && !errors; i++) {
if (scope.hosts[i].selected) {
Rest.post({ id: scope.hosts[i].id, disassociate: 1 })
.success( function(data, status, headers, config) {
// if this is the last selected host, clean up and exit
emit(i);
})
.error( function(data, status, headers, config) {
errors = true;
emit(i);
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Attempt to delete ' + scope.hosts[i].name + ' failed. POST returned status: ' + status });
});
}
}
Rest.post({ id: host_id, disassociate: 1 })
.success( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
scope.$emit('hostsReload');
})
.error( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
scope.$emit('hostsReload');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Attempt to delete ' + host_name + ' failed. POST returned status: ' + status });
});
}
//Force binds to work (not working usual way), and launch the confirmation prompt
@ -419,13 +392,6 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
scope['promptActionBtnClass'] = 'btn-danger';
}
/*else {
scope['promptHeader'] = 'Remove Host from Group';
scope['promptBody'] = 'Are you sure you want to remove ' + host_name + ' from the group? ' +
host_name + ' will continue to be part of the inventory under All Hosts.';
scope['promptActionBtnClass'] = 'btn-success';
}*/
scope.promptAction = action_to_take;
$('#prompt-modal').modal({
@ -442,13 +408,13 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
}])
.factory('HostsReload', ['RelatedSearchInit', 'RelatedPaginateInit', 'InventoryForm', 'GetBasePath', 'Wait',
function(RelatedSearchInit, RelatedPaginateInit, InventoryForm, GetBasePath, Wait) {
.factory('HostsReload', ['SearchInit', 'PaginateInit', 'InventoryHostsForm', 'GetBasePath', 'Wait',
function(SearchInit, PaginateInit, InventoryHostsForm, GetBasePath, Wait) {
return function(params) {
// Rerfresh the Hosts view on right side of page
var group_id = params.group_id;
var scope = params.scope;
var group_id = scope.group_id;
var postAction = params.action;
scope['hosts'] = null;
@ -463,10 +429,10 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
}
// Set the groups value in each element of hosts array
if (scope.removeRelatedHosts) {
scope.removeRelatedHosts();
if (scope.removePostRefresh) {
scope.removePostRefresh();
}
scope.removeRelatedHosts = scope.$on('relatedhosts', function() {
scope.removePostRefresh = scope.$on('PostRefresh', function() {
var groups, descr, found, list;
for (var i=0; i < scope.hosts.length; i++) {
groups = scope.hosts[i].summary_fields.groups;
@ -483,10 +449,8 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
}
});
var relatedSets = { hosts: { url: url, iterator: 'host' } };
RelatedSearchInit({ scope: params.scope, form: InventoryForm, relatedSets: relatedSets });
RelatedPaginateInit({ scope: params.scope, relatedSets: relatedSets, pageSize: 40 });
SearchInit({ scope: scope, set: 'hosts', list: InventoryHostsForm, url: url });
PaginateInit({ scope: scope, list: InventoryHostsForm, url: url });
scope.search('host');
if (!params.scope.$$phase) {
@ -510,7 +474,7 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
if (scope.buildAllGroupsRemove) {
scope.buildAllGroupsRemove();
}
scope.buildAllGroupsRemove = scope.$on('buildAllGroups', function() {
scope.buildAllGroupsRemove = scope.$on('buildAllGroups', function(e, inventory_name) {
scope.inventory_groups = [];
Rest.setUrl(GetBasePath('inventory') + inventory_id + '/groups/?order_by=name');
Rest.get()
@ -518,7 +482,7 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
for (var i=0; i < data.results.length; i++) {
scope.inventory_groups.push({ name: data.results[i].name, id: data.results[i].id });
}
scope.$emit('hostTabInit');
scope.$emit('hostTabInit', inventory_name);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
@ -538,7 +502,7 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
groups: data.related.root_groups,
children: []
});
scope.$emit('buildAllGroups');
scope.$emit('buildAllGroups', data.name);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,

View File

@ -325,7 +325,7 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
scope.relatedSets = [];
scope.master = {};
Rest.setUrl(GetBasePath('inventory') + $routeParams.id + '/');
Rest.setUrl(GetBasePath('inventory') + scope['inventory_id'] + '/');
Rest.get()
.success( function(data, status, headers, config) {
LoadBreadCrumbs({ path: '/inventories/' + $routeParams.id, title: data.name });
@ -440,11 +440,119 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
}
}])
.factory('SaveInventory', ['InventoryForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList',
'GetBasePath', 'ParseTypeChange', 'LoadInventory', 'RefreshGroupName',
function(InventoryForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange,
LoadInventory, RefreshGroupName) {
return function(params) {
// Save inventory property modifications
var scope = params.scope;
var form = InventoryForm;
var defaultUrl=GetBasePath('inventory');
try {
// Make sure we have valid variable data
if (scope.inventoryParseType == 'json') {
var json_data = JSON.parse(scope.inventory_variables); //make sure JSON parses
}
else {
var json_data = jsyaml.load(scope.inventory_variables); //parse yaml
}
// Make sure our JSON is actually an object
if (typeof json_data !== 'object') {
throw "failed to return an object!";
}
var data = {}
for (var fld in form.fields) {
if (fld != 'inventory_variables') {
if (form.fields[fld].realName) {
data[form.fields[fld].realName] = scope[fld];
}
else {
data[fld] = scope[fld];
}
}
}
Rest.setUrl(defaultUrl + scope['inventory_id'] + '/');
Rest.put(data)
.success( function(data, status, headers, config) {
if (scope.inventory_variables) {
Rest.setUrl(data.related.variable_data);
Rest.put(json_data)
.success( function(data, status, headers, config) {
scope.$emit('inventorySaved');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update inventory varaibles. PUT returned status: ' + status });
});
}
else {
scope.$emit('inventorySaved');
}
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update inventory. POST returned status: ' + status });
});
}
catch(err) {
Alert("Error", "Error parsing inventory variables. Parser returned: " + err);
}
}
}])
.factory('PostLoadInventory', ['InventoryForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList', 'GetBasePath',
function(InventoryForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath) {
return function(params) {
var scope = params.scope;
LookUpInit({
scope: scope,
form: InventoryForm,
current_item: (scope.organization !== undefined) ? scope.organization : null,
list: OrganizationList,
field: 'organization'
});
if (scope.variable_url) {
Rest.setUrl(scope.variable_url);
Rest.get()
.success( function(data, status, headers, config) {
if ($.isEmptyObject(data)) {
scope.inventory_variables = "---";
}
else {
scope.inventory_variables = jsyaml.safeDump(data);
}
scope.master.inventory_variables = scope.inventory_variables;
})
.error( function(data, status, headers, config) {
scope.inventory_variables = null;
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve inventory variables. GET returned status: ' + status });
});
}
else {
scope.inventory_variables = "---";
}
if (!scope.$$phase) {
scope.$digest();
}
}
}])
.factory('EditInventory', ['InventoryForm', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList',
'GetBasePath', 'ParseTypeChange', 'LoadInventory', 'RefreshGroupName',
'GetBasePath', 'ParseTypeChange', 'LoadInventory', 'RefreshGroupName', 'SaveInventory', 'PostLoadInventory',
function(InventoryForm, GenerateForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange,
LoadInventory, RefreshGroupName) {
LoadInventory, RefreshGroupName, SaveInventory, PostLoadInventory) {
return function(params) {
var generator = GenerateForm;
@ -473,38 +581,7 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
scope.inventoryLoadedRemove();
}
scope.inventoryLoadedRemove = scope.$on('inventoryLoaded', function() {
LookUpInit({
scope: scope,
form: form,
current_item: (scope.organization !== undefined) ? scope.organization : null,
list: OrganizationList,
field: 'organization'
});
if (scope.variable_url) {
Rest.setUrl(scope.variable_url);
Rest.get()
.success( function(data, status, headers, config) {
if ($.isEmptyObject(data)) {
scope.inventory_variables = "---";
}
else {
scope.inventory_variables = jsyaml.safeDump(data);
}
})
.error( function(data, status, headers, config) {
scope.inventory_variables = null;
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve inventory variables. GET returned status: ' + status });
});
}
else {
scope.inventory_variables = "---";
}
if (!scope.$$phase) {
scope.$digest();
}
PostLoadInventory({ scope: scope });
});
LoadInventory({ scope: scope, doPostSteps: false });
@ -513,81 +590,19 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
scope.$digest();
}
function PostSave() {
$('#form-modal').modal('hide');
if (scope.removeInventorySaved) {
scope.removeInventorySaved();
}
scope.removeInventorySaved = scope.$on('inventorySaved', function() {
$('#form-modal').modal('hide');
// Make sure the inventory name appears correctly in the tree and the navbar
RefreshGroupName($('#inventory-node'), scope['inventory_name'], scope['inventory_description']);
});
// Make sure the inventory name appears correctly in the tree and the navbar
RefreshGroupName($('#inventory-node'), scope['inventory_name'], scope['inventory_description']);
// Reset the form to disable the form action buttons
//scope[form.name + '_form'].$setPristine();
// Show the flash message for 5 seconds, letting the user know the save worked
//scope['flashMessage'] = 'Your changes were successfully saved!';
//setTimeout(function() {
// scope['flashMessage'] = null;
// if (!scope.$$phase) {
// scope.$digest();
// }
// }, 5000);
}
// Save
scope.formModalAction = function() {
try {
// Make sure we have valid variable data
if (scope.inventoryParseType == 'json') {
var json_data = JSON.parse(scope.inventory_variables); //make sure JSON parses
}
else {
var json_data = jsyaml.load(scope.inventory_variables); //parse yaml
}
// Make sure our JSON is actually an object
if (typeof json_data !== 'object') {
throw "failed to return an object!";
}
var data = {}
for (var fld in form.fields) {
if (fld != 'inventory_variables') {
if (form.fields[fld].realName) {
data[form.fields[fld].realName] = scope[fld];
}
else {
data[fld] = scope[fld];
}
}
}
Rest.setUrl(defaultUrl + scope['inventory_id'] + '/');
Rest.put(data)
.success( function(data, status, headers, config) {
if (scope.inventory_variables) {
Rest.setUrl(data.related.variable_data);
Rest.put(json_data)
.success( function(data, status, headers, config) {
PostSave();
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update inventory varaibles. PUT returned status: ' + status });
});
}
else {
PostSave();
}
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update inventory. POST returned status: ' + status });
});
}
catch(err) {
Alert("Error", "Error parsing inventory variables. Parser returned: " + err);
}
};
SaveInventory({ scope: scope });
}
}
}]);

View File

@ -158,7 +158,8 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
scope[iterator + 'SearchParams'] = (sort_order) ? 'order_by=' + escape(sort_order) : "";
}
if (iterator == 'inventory' && scope.inventoryFailureFilter) {
if ( (iterator == 'inventory' && scope.inventoryFailureFilter) ||
(iterator == 'host' && scope.hostFailureFilter) ) {
scope[iterator + 'SearchParams'] += '&has_active_failures=true';
}

View File

@ -12,7 +12,7 @@ angular.module('HostListDefinition', [])
name: 'hosts',
iterator: 'host',
selectTitle: 'Select Host',
selectTitle: 'Add Existing Hosts',
editTitle: 'Hosts',
index: true,
well: true,

View File

@ -22,10 +22,8 @@ angular.module('InventoriesListDefinition', [])
name: {
key: true,
label: 'Name',
badgeShow: "\{\{ inventory.has_active_failures \}\}",
badgeIcon: 'icon-exclamation-sign',
badgeToolTip: 'Contains hosts with active job failures',
badgePlacement: 'bottom'
badgeIcon: "\{\{ 'icon-failures-' + inventory.has_active_failures \}\}",
badgePlacement: 'left'
},
description: {
label: 'Description'
@ -54,7 +52,7 @@ angular.module('InventoriesListDefinition', [])
dropdown: {
type: 'DropDown',
label: 'View',
label: 'View Jobs',
'class': 'btn-xs',
options: [
{ ngClick: 'viewJobs(\{\{ inventory.id \}\})', label: 'Jobs' },
@ -62,16 +60,30 @@ angular.module('InventoriesListDefinition', [])
]
},
hosts: {
label: 'Hosts',
ngClick: "editHosts(\{\{ inventory.id \}\})",
icon: 'icon-th-large',
"class": 'btn-xs btn-default',
awToolTip: 'Edit Hosts'
},
groups: {
label: 'Groups',
ngClick: "editGroups(\{\{ inventory.id \}\})",
icon: 'icon-group',
"class": 'btn-xs btn-default',
awToolTip: 'Edit Groups'
},
edit: {
label: 'Edit',
ngClick: "editInventory(\{\{ inventory.id \}\})",
icon: 'icon-edit',
"class": 'btn-xs btn-default',
awToolTip: 'View/Edit inventory'
awToolTip: 'Edit Inventory Properties'
},
"delete": {
label: 'Delete',
ngClick: "deleteInventory(\{\{ inventory.id \}\},'\{\{ inventory.name \}\}')",
icon: 'icon-trash',
"class": 'btn-xs btn-danger',

View File

@ -14,7 +14,6 @@
@blue-link: #0088cc;
@grey: #A9A9A9;
html {
background-color: @black;
}
@ -106,6 +105,7 @@ hr {
border-color: #ccc;
}
/* Use code-breakable in pop-over text to indent and wrap code segments */
.code-breakable {
@ -390,8 +390,20 @@ select.field-mini-height {
}
.tree-container {
padding: 0;
margin: 5px 0 15px 0;
background-color: #f5f5f5;
border: 1px solid #e3e3e3;
border-radius: 6px;
}
.tree-controls {
padding: 10px;
border-bottom: 1px solid #e3e3e3;
.title {
display: inline-block;
font-weight: bold;
margin-right: 10px;
}
}
.no-padding {
@ -436,117 +448,136 @@ select.field-mini-height {
/* Jobs pages */
.job-error,
.job-failed,
.license-expired,
.license-invalid,
.active-failures-true,
.active-failures-true a,
.active-failures-true a:active,
input[type="text"].job-failed,
input[type="text"].job-error {
color: #da4f49;
}
.job-error,
.job-failed,
.license-expired,
.license-invalid,
.icon-failures-true,
.active-failures-true a,
.active-failures-true a:active,
input[type="text"].job-failed,
input[type="text"].job-error {
color: #da4f49;
}
.active-failures-true a:hover {
color: @red;
}
.icon-failures-true a:hover {
color: @red;
}
.job-failures-true {
padding-top: 5px;
color: #da4f49;
}
.job-failures-true {
padding-top: 5px;
color: #da4f49;
}
.job-event-status,
.license-status {
padding-top: 5px;
}
.job-event-status,
.license-status {
padding-top: 5px;
}
.job-new,
input[type="text"].job-new,
.job-canceled,
input[type="text"].job-canceled {
color: #778899;
}
.job-new,
input[type="text"].job-new,
.job-canceled,
input[type="text"].job-canceled {
color: #778899;
}
.job-pending,
.job-running,
.job-success,
.job-successful,
.active-failures-false,
.license-valid,
input[type="text"].job-success,
input[type="text"].job-successful {
color: #5bb75b;
}
.job-pending,
.job-running,
.job-success,
.job-successful,
.icon-failures-false,
.license-valid,
input[type="text"].job-success,
input[type="text"].job-successful {
color: #5bb75b;
}
.field-success {
color: #5bb75b;
}
.icon-failures-true:before {
content: "\f06a";
}
.field-success input {
border-color: #5bb75b;
}
.icon-failures-false:before {
content: "\f111";
}
.field-failure {
color: @red;
}
.field-success {
color: #5bb75b;
}
.field-failure input {
border-color: @red;
}
.field-success input {
border-color: #5bb75b;
}
.job-changed,
.license-warning,
.license-demo {
color: @warning;
}
.field-failure {
color: @red;
}
.job-detail-status {
display: inline-block;
margin-top: 5px;
font-size: 15px;
font-weight: bold;
}
.field-failure input {
border-color: @red;
}
.form-items .search-widget {
margin-top: 15px;
}
.field-badge {
font-size: 12px;
}
.form-items .item-count {
display: inline-block;
margin-top: 25px;
font-size: small;
}
.job-changed,
.license-warning,
.license-demo {
color: @warning;
}
.child-event a {
color: @black;
cursor: default;
}
.job-detail-status {
display: inline-block;
margin-top: 5px;
font-size: 15px;
font-weight: bold;
}
.level-1 {
padding-left: 24px;
}
.form-items .search-widget {
margin-top: 15px;
}
.level-2 {
padding-left: 48px;
}
.form-items .item-count {
display: inline-block;
margin-top: 25px;
font-size: small;
}
.level-3 {
padding-left: 72px;
}
.child-event a {
color: @black;
cursor: default;
}
.level-3-detail {
padding-left: 72px;
}
.level-1 {
padding-left: 24px;
}
#job_events .control-group {
margin-top: 0;
margin-bottom: 10px;
}
.level-2 {
padding-left: 48px;
}
.level-3 {
padding-left: 72px;
}
.level-3-detail {
padding-left: 72px;
}
#job_events .control-group {
margin-top: 0;
margin-bottom: 10px;
}
/* End Jobs Page */
/* License Accordion */
#license-collapse .ui-accordion-content {
overflow: hidden;
}
/* Inventory Detail Groups tab */
.inventory-content {
padding: 15px;
@ -614,11 +645,6 @@ input[type="text"].job-successful {
}
.field-badge {
color: @red;
font-size: 12px;
}
/* Inventory Detail Hosts tab */
.hosts-well {
@ -661,6 +687,14 @@ input[type="text"].job-successful {
}
.search-tree {
.title {
color: @black;
font-weight: bold;
margin-bottom: 10px;
margin-top: 0;
}
ul {
list-style-type: none;
padding-left: 13px;
@ -676,19 +710,31 @@ input[type="text"].job-successful {
.active {
font-weight: bold;
color: #000;
padding: 5px;
}
.expand {
padding: 3px;
border: 1px solid rgb(245, 245, 245);
}
.expand:hover {
background-color: #ddd;
border: 1px solid #ddd;
}
.field-badge {
font-size: 10px;
line-height: normal;
vertical-align: middle;
}
}
.host-failure-filter {
padding: 10px;
}
.disabled {
color: @grey;
}
@ -744,7 +790,7 @@ tr td i {
float: none;
padding-top: 3px;
padding-left: 0;
margin-right: 10px;
margin-right: 5px;
margin-left: 0;
}

View File

@ -56,7 +56,7 @@ angular.module('AuthService', ['ngCookies'])
return ($rootScope.token) ? $rootScope.token : $cookieStore.get('token');
}
else {
return null;
$location.path('/login');
}
},

View File

@ -421,7 +421,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
elm = angular.element(e.target);
}
var sibling = angular.element(parent.children()[1]); // <a>
var sibling = angular.element(parent.children()[2]); // <a>
var state = parent.attr('data-state');
var icon = angular.element(elm.children()[0]);
@ -449,6 +449,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
}
else {
icon.removeClass('icon-caret-right').addClass('icon-caret-down');
parent.attr('data-state','open');
//activate(e);
}
});
@ -485,7 +486,6 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
else {
// close the element
parent.attr('data-state','closed');
var icon = angular.element(elm.children()[0]);
icon.removeClass('icon-caret-down').addClass('icon-caret-right');
var childlists = parent.find('ul');
if (childlists && childlists.length > 0) {
@ -525,15 +525,14 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
html += "date-state=\"closed\" ";
html += "data-hosts=\"" + data.results[i].related.all_hosts + "\" ";
html += "data-description=\"" + data.results[i].description + "\" ";
html += "data-failures=\"" +data.results[i].has_active_failures + "\" ";
html += "data-failures=\"" + data.results[i].has_active_failures + "\" ";
html += "data-groups=\"" + data.results[i].related.children + "\" ";
html += "data-name=\"" + data.results[i].name + "\" ";
html += "data-group-id=\"" + data.results[i].id + "\">";
html += "<a href=\"\" class=\"expand\"><i class=\"icon-caret-right\"></i></a> ";
html += "<a href=\"\" class=\"activate\">" + data.results[i].name + "</a> ";
html += "<a href=\"\" aw-tool-tip=\"Contains hosts with failed jobs\" ng-show=\"" +
data.results[i].has_active_failures + "\" data-placement=\"bottom\">" +
"<i class=\"field-badge icon-exclamation-sign\"></i></a></li>\n";
html += "<i class=\"field-badge icon-failures-" + data.results[i].has_active_failures + "\"></i>";
html += " <a href=\"\" class=\"activate\">" + data.results[i].name + "</a> ";
html += "</li>\n";
}
html = (html !== '') ? "<ul>" + html + "</ul>\n" : "";
var compiled = $compile(html)(scope);
@ -570,7 +569,8 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
Wait('start');
var container = angular.element(document.getElementById('search-tree-container'));
container.empty();
var html = "<ul>\n" +
var html = "<div class=\"title\">Group Selector:</div>\n" +
"<ul>\n" +
"<li id=\"search-node-1000\" data-state=\"closed\" data-hosts=\"{{ treeData[0].hosts}}\" " +
"data-hosts=\"{{ treeData[0].hosts }}\" " +
"data-description=\"{{ treeData[0].description }}\" " +
@ -578,9 +578,8 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
"data-groups=\"{{ treeData[0].groups }}\" " +
"data-name=\"{{ treeData[0].name }}\" " +
"><a href=\"\" class=\"expand\"><i class=\"icon-caret-right\"></i></a> " +
"<i class=\"field-badge \{\{ 'icon-failures-' + treeData[0].failures \}\}\"></i> " +
"<a href=\"\" class=\"activate active\">{{ treeData[0].name }}</a> " +
"<a href=\"\" aw-tool-tip=\"Contains hosts with failed jobs\" ng-show=\"\{\{ treeData[0].failures \}\}\" data-placement=\"bottom\">" +
"<i class=\"field-badge icon-exclamation-sign\"></i></a>" +
"</li>\n" +
"</ul>\n";
var compiled = $compile(html)(scope);
@ -591,7 +590,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
$('#search-node-1000 .expand').click();
$('#search-node-1000 .activate').click();
Wait('stop');
}, 1000);
}, 500);
});
}

View File

@ -72,7 +72,6 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
this.scope[set] = null;
}
if ( ((!options.modal) && options.related) || this.form.forceListeners ) {
console.log('adding listeners');
this.addListeners();
}
if (options.mode == 'add') {
@ -906,184 +905,183 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
//
var form = this.form;
var itm = "groups";
html = this.breadCrumbs(options);
html += "<div class=\"inventory-content\">\n";
html += "<ul class=\"nav nav-tabs\" id=\"inventory-tabs\">\n";
html += "<li><a href=\"#inventory-hosts\" data-toggle=\"tab\">Hosts</a></li>\n";
html += "<li><a href=\"#inventory-groups\" data-toggle=\"tab\">Groups</a></li>\n";
html += "</ul>\n";
html += "<div class=\"tab-content\">\n";
html += "<div class=\"tab-pane active\" id=\"inventory-groups\">\n";
html += "<div ng-show=\"showGroupHelp\" class=\"alert alert-dismissable alert-info\">\n";
html += "<button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">&times;</button>\n";
html += "<p><strong>Hint:</strong> Get started building your inventory by adding a group. After creating a group, " +
"use the Hosts tab to add hosts to the group."
"use the Hosts tab to add hosts to the group.</p>";
html += "</div>\n";
// build the groups tab
html += "<div class=\"navbar groups-menu\">\n";
html += "<a class=\"navbar-brand\" ng-bind-html-unsafe=\"selectedNodeName\" href=\"\"></a>\n";
html += "<ul class=\"nav navbar-nav\">\n";
html += "<li><a href=\"\" ng-click=\"editInventory()\" ng-hide=\"inventoryEditHide\" " +
"aw-tool-tip=\"Edit inventory properties\" data-placement=\"bottom\"><i class=\"icon-edit\"></i> Inventory Properties</a></li>\n";
html += "<li><a href=\"\" ng-click=\"editGroup()\" ng-hide=\"groupEditHide\" " +
"aw-tool-tip=\"Edit the selected group\" data-placement=\"bottom\"><i class=\"icon-edit\"></i> Group Properties</a></li>\n";
html += "<li><a href=\"\" ng-click=\"addGroup()\" ng-hide=\"groupAddHide\" " +
"aw-tool-tip=\"Add an existing group\" data-placement=\"bottom\"><i class=\"icon-check\"></i> Add Existing Group</a></li>\n";
html += "<li><a href=\"\" ng-click=\"createGroup()\" ng-hide=\"groupCreateHide\" " +
"aw-tool-tip=\"Create a new group\" data-placement=\"bottom\"><i class=\"icon-plus\"></i> Create New Group</a></li>\n";
html += "<li><a href=\"\" ng-click=\"deleteGroup()\" ng-hide=\"groupDeleteHide\" " +
"aw-tool-tip=\"Delete the selected group\" data-placement=\"bottom\"><i class=\"icon-trash\"></i> Delete Group</a></li>\n";
html += "<li><a class=\"status\" ng-show=\"treeLoading\" href=\"\"><i class=\"icon-spinner icon-spin icon-large\"></i> Loading...</a></li>\n";
html += "</ul>\n";
html += "</div><!-- navbar -->\n";
html += "<div id=\"tree-view\" class=\"tree-container\"></div>\n";
html += "</div><!-- inventory-groups -->\n";
var html = '';
html += this.breadCrumbs(options);
// build the hosts tab
itm = "hosts";
html += "<div class=\"tab-pane\" id=\"inventory-hosts\">\n";
html += "<div class=\"row\">\n";
html += "<div class=\"col-lg-3\" id=\"search-tree-target\">\n";
html += "<div aw-tree=\"searchTree\"></div>\n";
html += "</div>\n";
html += "<div class=\"col-lg-9\">\n";
html += "<div class=\"navbar hosts-menu\">\n";
html += "<a class=\"navbar-brand\" ng-bind-html-unsafe=\"" + form.related[itm].title + "\" href=\"\"></a>\n";
html += "<ul class=\"nav navbar-nav\">\n";
html += "<li><a href=\"\" ng-click=\"addHost()\" ng-hide=\"hostAddHide\" " +
"aw-tool-tip=\"Add an existing host\" data-placement=\"bottom\"><i class=\"icon-check\"></i> Add Existing Host</a></li>\n";
html += "<li><a href=\"\" ng-click=\"createHost()\" ng-hide=\"hostCreateHide\" " +
"aw-tool-tip=\"Create a new host\" data-placement=\"bottom\"><i class=\"icon-plus\"></i> Create New Host</a></li>\n";
html += "<li><a href=\"\" ng-click=\"deleteHost()\" ng-class=\"hostDeleteDisabledClass\" ng-disabled=\"hostDeleteDisabled\" " +
"aw-tool-tip=\"Delete selected hosts\" data-placement=\"bottom\"><i class=\"icon-trash\"></i> Delete Hosts</a></li>\n";
html += "<li><a class=\"status\" ng-show=\"treeLoading\" href=\"\"><i class=\"icon-spinner icon-spin icon-large\"></i> Loading...</a></li>\n";
html += "</ul>\n";
html += "<form class=\"navbar-form\">\n";
html += "<label class=\"checkbox-inline\"><input type=\"checkbox\" ng-model=\"hostFailureFilter\" ng-change=\"filterInventory()\" > Only show hosts with failed jobs" +
"</label>\n";
html += "</form>\n";
html += "</div><!-- navbar -->\n";
html += "<div class=\"hosts-well well\">\n";
html += SearchWidget({ iterator: form.related[itm].iterator, template: form.related[itm], mini: true, size: 'col-lg-6'});
// Add actions(s)
for (var action in form.related[itm].actions) {
html += "<button type=\"button\" class=\"btn btn-sm ";
html += (form.related[itm].actions[action]['class']) ? form.related[itm].actions[action]['class'] : "btn-success";
html += "\" ";
html += (form.related[itm]['actions'][action].id) ? this.attr(form.related[itm]['actions'][action],'id') : "";
html += this.attr(form.related[itm]['actions'][action],'ngClick');
html += (form.related[itm]['actions'][action].awToolTip) ? this.attr(form.related[itm]['actions'][action],'awToolTip') : "";
html += (form.related[itm]['actions'][action].awToolTip) ? "data-placement=\"top\" " : "";
html += (form.related[itm]['actions'][action].ngHide) ? this.attr(form.related[itm]['actions'][action],'ngHide') : "";
html += "><i class=\"" + form.related[itm]['actions'][action].icon + "\"></i>";
html += (form.related[itm]['actions'][action].label) ? " " + form.related[itm]['actions'][action].label : "";
html += "</button>\n";
if (form.type == 'groupsview') {
// build the groups page
html += "<div class=\"tree-container\">\n";
html += "<div class=\"tree-controls\">\n";
//html += "<div class=\"title\" ng-bind=\"selectedNodeName\"></div>\n";
html += "<button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"editInventory()\" ng-hide=\"inventoryEditHide\" " +
"aw-tool-tip=\"Edit inventory properties\" data-placement=\"bottom\"><i class=\"icon-edit\"></i> " +
"\{\{ selectedNodeName \}\} Properties</button>\n";
html += "<button type=\"button\" class=\"btn btn-default btn-xs\" ng-click=\"editGroup()\" ng-hide=\"groupEditHide\" " +
"aw-tool-tip=\"Edit the selected group\" data-placement=\"bottom\"><i class=\"icon-edit\"></i> " +
"\{\{ selectedNodeName \}\} Properties</button>\n";
html += "<button type=\"button\" class=\"btn btn-success btn-xs\" ng-click=\"addGroup()\" ng-hide=\"groupAddHide\" " +
"aw-tool-tip=\"Add an existing group\" data-placement=\"bottom\"><i class=\"icon-check\"></i> Add Existing Group</button>\n";
html += "<button type=\"button\" class=\"btn btn-success btn-xs\" ng-click=\"createGroup()\" ng-hide=\"groupCreateHide\" " +
"aw-tool-tip=\"Create a new group\" data-placement=\"bottom\"><i class=\"icon-plus\"></i> Create New Group</button>\n";
html += "<button type=\"button\" class=\"btn btn-danger btn-xs\" ng-click=\"deleteGroup()\" ng-hide=\"groupDeleteHide\" " +
"aw-tool-tip=\"Delete the selected group\" data-placement=\"bottom\"><i class=\"icon-trash\"></i> Delete Group</button>\n";
html += "</div><!-- tree controls -->\n";
html += "<div id=\"tree-view\"></div>\n";
html += "</div><!-- tree-container -->\n";
}
html += "</div><!-- row -->\n";
// Start the list
html += "<div class=\"list\">\n";
html += "<table class=\"" + form.related[itm].iterator + " table table-condensed table-hover\">\n";
html += "<thead>\n";
html += "<tr>\n";
html += "<th><input type=\"checkbox\" ng-model=\"toggleAllFlag\" ng-change=\"toggleAllHosts()\" aw-tool-tip=\"Select all hosts\" " +
"data-placement=\"top\"></th>\n";
for (var fld in form.related[itm].fields) {
html += "<th class=\"list-header\" id=\"" + form.related[itm].iterator + '-' + fld + "-header\" ";
html += (!form.related[itm].fields[fld].nosort) ? "ng-click=\"sort('" + form.related[itm].iterator + "', '" + fld + "')\"" : "";
html += ">" + form.related[itm]['fields'][fld].label;
if (form.related[itm].fields[fld].nosort == undefined || form.related[itm].fields[fld].nosort == false) {
html += " <i class=\"";
if (form.related[itm].fields[fld].key) {
if (form.related[itm].fields[fld].desc) {
html += "icon-sort-down";
else {
// build the hosts page
html += "<div class=\"row\">\n";
html += "<div class=\"col-lg-3\" id=\"search-tree-target\">\n";
html += "<div aw-tree=\"searchTree\"></div>\n";
html += "</div>\n";
html += "<div class=\"col-lg-9\">\n";
html += "<div class=\"hosts-well well\">\n";
html += SearchWidget({ iterator: form.iterator, template: form, mini: true, size: 'col-md-6 col-lg-6'});
html += "<div class=\"col-md-6 col-lg-6\">\n"
html += "<div class=\"pull-right\">\n";
// Add actions(s)
for (var action in form.actions) {
html += "<button type=\"button\" class=\"btn ";
html += (form.actions[action]['class']) ? form.actions[action]['class'] : "btn-success";
html += "\" ";
html += (form['actions'][action].id) ? this.attr(form['actions'][action],'id') : "";
html += this.attr(form['actions'][action],'ngClick');
html += (form['actions'][action].awToolTip) ? this.attr(form['actions'][action],'awToolTip') : "";
html += (form['actions'][action].awToolTip && form['actions'][action].dataPlacement) ?
this.attr(form['actions'][action], 'dataPlacement') : "data-placement=\"top\" ";
html += (form['actions'][action].ngHide) ? this.attr(form['actions'][action],'ngHide') : "";
html += "><i class=\"" + form['actions'][action].icon + "\"></i>";
html += (form['actions'][action].label) ? " " + form['actions'][action].label : "";
html += "</button>\n";
}
html += "</div>\n";
html += "</div>\n";
html += "</div><!-- row -->\n";
// Start the list
html += "<div class=\"list\">\n";
html += "<table class=\"" + form.iterator + " table table-condensed table-hover\">\n";
html += "<thead>\n";
html += "<tr>\n";
//html += "<th><input type=\"checkbox\" ng-model=\"toggleAllFlag\" ng-change=\"toggleAllHosts()\" aw-tool-tip=\"Select all hosts\" " +
// "data-placement=\"top\"></th>\n";
for (var fld in form.fields) {
html += "<th class=\"list-header\" id=\"" + form.iterator + '-' + fld + "-header\" ";
html += (!form.fields[fld].nosort) ? "ng-click=\"sort('" + form.iterator + "', '" + fld + "')\"" : "";
html += ">";
html += (form['fields'][fld].label && form['fields'][fld].type !== 'DropDown') ? form['fields'][fld].label : '';
if (form.fields[fld].nosort == undefined || form.fields[fld].nosort == false) {
html += " <i class=\"";
if (form.fields[fld].key) {
if (form.fields[fld].desc) {
html += "icon-sort-down";
}
else {
html += "icon-sort-up";
}
}
else {
html += "icon-sort-up";
html += "icon-sort";
}
html += "\"></i>";
}
html += "</th>\n";
}
html += "<th></th>\n";
html += "</tr>\n";
html += "</thead>";
html += "<tbody>\n";
html += "<tr ng-repeat=\"" + form.iterator + " in hosts\" >\n";
// Select checkbox
//html += "<td><input type=\"checkbox\" ng-model=\"" + form.iterator + ".selected\" ng-change=\"toggleOneHost()\" ></td>";
var cnt = 0;
var rfield;
for (var fld in form.fields) {
cnt++;
rfield = form.fields[fld];
if (fld == 'groups' ) {
// generate group form control/button widget
html += "<td>";
html += "<div class=\"input-group input-group-sm\">\n";
html += "<span class=\"input-group-btn\">\n";
html += "<button class=\"btn btn-default\" type=\"button\" ng-click=\"editHostGroups({{ host.id }})\"><i class=\"icon-list\"></i></button>\n";
html += "</span>\n";
html += "<input type=\"text\" ng-model=\"host.groups\" class=\"form-control\" disabled=\"disabled\" >\n";
html += "</div>\n";
html += "</td>\n";
}
else {
html += "icon-sort";
html += Column({ list: form, fld: fld, options: options, base: null });
}
html += "\"></i>";
}
html += "</a></th>\n";
}
}
// Row level actions
html += "<td class=\"actions\">";
for (act in form.fieldActions) {
var action = form.fieldActions[act];
html += "<button type=\"button\" class=\"btn";
html += (action['class']) ? " " + action['class'] : "";
html += "\" " + this.attr(action,'ngClick');
html += (action.awToolTip) ? this.attr(action,'awToolTip') : "";
html += (action.awToolTip) ? "data-placement=\"top\" " : "";
html += ">" + this.icon(action.icon);
html += (action.label) ? " " + action.label : "";
html += "</button> ";
}
html += "</td>";
html += "</tr>\n";
cnt++;
// Message for when a related collection is empty
html += "<tr class=\"info\" ng-show=\"" + form.iterator + "Loading == false && (hosts == null || hosts.length == 0)\">\n";
html += "<td colspan=\"" + cnt + "\"><div class=\"alert alert-info\">No records matched your search.</div></td>\n";
html += "</tr>\n";
html += "<th></th>\n";
html += "</tr>\n";
html += "</thead>";
html += "<tbody>\n";
html += "<tr ng-repeat=\"" + form.related[itm].iterator + " in " + itm + "\" >\n";
// Message for loading
html += "<tr class=\"info\" ng-show=\"HostsLoading == true\">\n";
html += "<td colspan=\"" + cnt + "\"><div class=\"alert alert-info\">Loading...</div></td>\n";
html += "</tr>\n";
// Select checkbox
html += "<td><input type=\"checkbox\" ng-model=\"" + form.related[itm].iterator + ".selected\" ng-change=\"toggleOneHost()\" ></td>";
// End List
html += "</tbody>\n";
html += "</table>\n";
html += "</div>\n"; // close list
var cnt = 1;
var rfield;
var base = (form.related[itm].base) ? form.related[itm].base : itm;
base = base.replace(/^\//,'');
for (var fld in form.related[itm].fields) {
cnt++;
rfield = form.related[itm].fields[fld];
if (fld == 'groups' ) {
// generate group form control/button widget
html += "<td>";
html += "<div class=\"input-group input-group-sm\">\n";
html += "<span class=\"input-group-btn\">\n";
html += "<button class=\"btn btn-default\" type=\"button\" ng-click=\"editHostGroups({{ host.id }})\"><i class=\"icon-list\"></i></button>\n";
html += "</span>\n";
html += "<input type=\"text\" ng-model=\"host.groups\" class=\"form-control\" disabled=\"disabled\" >\n";
html += "</div>\n";
//html += "<a href=\"\"><i class=\"icon-list\"></i></button> \{\{ host.groups \}\}</a>";
html += "</td>\n";
}
else {
html += Column({ list: form.related[itm], fld: fld, options: options, base: base });
}
}
html += "<div class=\"row host-failure-filter\">\n";
html += "<div class=\"col-lg-12\">\n";
html += "<label class=\"checkbox-inline pull-right\"><input type=\"checkbox\" ng-model=\"hostFailureFilter\" ng-change=\"filterHosts()\" > Only show hosts with failed jobs" +
"</label>\n";
html += "</div>\n";
html += "</div>\n";
html += "</tr>\n";
html += "</div>\n"; // close well
// Message for when a related collection is empty
html += "<tr class=\"info\" ng-show=\"" + form.related[itm].iterator + "Loading == false && (" + itm + " == null || " + itm + ".length == 0)\">\n";
html += "<td colspan=\"" + cnt + "\"><div class=\"alert alert-info\">No records matched your search.</div></td>\n";
html += "</tr>\n";
html += PaginateWidget({ set: 'hosts', iterator: form.iterator, mini: true });
// Message for loading
html += "<tr class=\"info\" ng-show=\"" + form.related[itm].iterator + "Loading == true\">\n";
html += "<td colspan=\"" + cnt + "\"><div class=\"alert alert-info\">Loading...</div></td>\n";
html += "</tr>\n";
html += "</div>\n";
html += "</div>\n";
// End List
html += "</tbody>\n";
html += "</table>\n";
html += "</div>\n"; // close list
html += "</div>\n"; // close well
html += PaginateWidget({ set: itm, iterator: form.related[itm].iterator, mini: true });
html += "</div>\n";
html += "</div>\n";
html += "</div><!-- inventory-hosts -->\n";
html += "</div><!-- tab-content -->\n";
html += "</div><!-- inventory-content -->\n";
return html;
//html += "</div><!-- inventory-hosts -->\n";
}
return html;
},
buildCollections: function(options) {

View File

@ -134,8 +134,36 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
}
}])
.factory('Badge', [ function() {
return function(field) {
var html = '';
.factory('Column', ['Attr', 'Icon', 'DropDown', function(Attr, Icon, DropDown) {
if (field.badgeToolTip) {
html += "<a href=\"\" aw-tool-tip=\"" + field.badgeToolTip + "\"";
html += (field.badgeTipPlacement) ? " data-placement=\"" + field.badgeTipPlacement + "\"" : "";
html += (field.badgeShow) ? " ng-show=\"" + field.badgeShow + "\"" : "";
html += ">";
}
html += "<i ";
html += (field.badgeShow) ? "ng-show=\"" + field.badgeShow + "\" " : "";
html += " class=\"field-badge " + field.badgeIcon;
html += (field.badgeClass) ? " " + field.badgeClass : "";
html += "\"></i>";
if (field.badgeToolTip) {
html += "</a>";
}
html += "\n";
return html;
}
}])
.factory('Column', ['Attr', 'Icon', 'DropDown', 'Badge', function(Attr, Icon, DropDown, Badge) {
return function(params) {
var list = params['list'];
var fld = params['fld'];
@ -159,6 +187,11 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
// Add ngShow
html += (field.ngShow) ? "<span " + Attr(field,'ngShow') + ">" : "";
// Badge
if (field.badgeIcon && field.badgePlacement && field.badgePlacement == 'left') {
html += Badge(field);
}
// Add collapse/expand icon --used on job_events page
if (list['hasChildren'] && field.hasChildren) {
@ -173,7 +206,7 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += "<a href=\"#" + field.linkTo + "\">";
}
else if (field.ngClick) {
html += "<a href=\"\"" + Attr(field, 'ngClick') + "\">";
html += "<a href=\"\"" + Attr(field, 'ngClick') + ">";
}
else if (field.link == undefined || field.link) {
html += "<a href=\"#/" + base + "/{{" + list.iterator + ".id }}\">";
@ -225,18 +258,8 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
"></div>\n" : "";
// Badge
if (field.badgeIcon) {
if (field.badgeToolTip) {
html += "<a href=\"\" aw-tool-tip=\"" + field.badgeToolTip + "\"";
html += (field.badgePlacement) ? " data-placement=\"" + field.badgePlacement + "\"" : "";
html += (field.badgeShow) ? " ng-show=\"" + field.badgeShow + "\"" : ""
html += ">";
html += " <i class=\"field-badge " + field.badgeIcon + "\"></i></a>\n";
}
else {
html += " <i class=\"field-badge " + field.badgeIcon + "\" ";
html += "ng-show=\"" + field.badgeShow + "\"></i>\n";
}
if (field.badgeIcon && field.badgePlacement && field.badgePlacement !== 'left') {
html += Badge(field);
}
}

View File

@ -193,10 +193,6 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
html += "</div>\n";
html += "</div><!-- row -->\n";
//html += "</div>\n";
// table header row
html += "<table class=\"table table-condensed"
html += (list['class']) ? " " + list['class'] : "";
@ -290,7 +286,6 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
});
}
else {
console.log('here');
html += this.button(list.fieldActions[action]);
}
}

View File

@ -9,12 +9,6 @@
padding: 15px;
}
.jstree-ansible {
background-color: #f5f5f5;
border: 1px solid #e3e3e3;
border-radius: 6px;
}
.jstree-ansible li,
.jstree-ansible ins { background-image:url("d.png"); background-repeat:no-repeat; background-color:transparent; }
.jstree-ansible li { background-position:-90px 0; background-repeat:repeat-y; }

View File

@ -41,6 +41,8 @@
<script src="{{ STATIC_URL }}js/controllers/Users.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Admins.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Inventories.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Hosts.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Groups.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Teams.js"></script>
<script src="{{ STATIC_URL }}js/controllers/Credentials.js"></script>
<script src="{{ STATIC_URL }}js/controllers/JobTemplates.js"></script>
@ -52,6 +54,8 @@
<script src="{{ STATIC_URL }}js/forms/Users.js"></script>
<script src="{{ STATIC_URL }}js/forms/Organizations.js"></script>
<script src="{{ STATIC_URL }}js/forms/Inventories.js"></script>
<script src="{{ STATIC_URL }}js/forms/InventoryHosts.js"></script>
<script src="{{ STATIC_URL }}js/forms/InventoryGroups.js"></script>
<script src="{{ STATIC_URL }}js/forms/Teams.js"></script>
<script src="{{ STATIC_URL }}js/forms/Hosts.js"></script>
<script src="{{ STATIC_URL }}js/forms/Groups.js"></script>