AC-331 Latest host tab changes. Editing the groups of a host is now possible

This commit is contained in:
chouseknecht
2013-08-20 18:22:28 -04:00
parent 36d4795c12
commit b76bf268f9
33 changed files with 5056 additions and 2033 deletions
+384
View File
@@ -0,0 +1,384 @@
.btn-default,
.btn-primary,
.btn-success,
.btn-info,
.btn-warning,
.btn-danger {
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
}
.btn-default:active,
.btn-primary:active,
.btn-success:active,
.btn-info:active,
.btn-warning:active,
.btn-danger:active,
.btn-default.active,
.btn-primary.active,
.btn-success.active,
.btn-info.active,
.btn-warning.active,
.btn-danger.active {
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}
.btn:active,
.btn.active {
background-image: none;
}
.btn-default {
text-shadow: 0 1px 0 #fff;
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#e6e6e6));
background-image: -webkit-linear-gradient(top, #ffffff, 0%, #e6e6e6, 100%);
background-image: -moz-linear-gradient(top, #ffffff 0%, #e6e6e6 100%);
background-image: linear-gradient(to bottom, #ffffff 0%, #e6e6e6 100%);
background-repeat: repeat-x;
border-color: #e0e0e0;
border-color: #ccc;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
}
.btn-default:active,
.btn-default.active {
background-color: #e6e6e6;
border-color: #e0e0e0;
}
.btn-primary {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
background-repeat: repeat-x;
border-color: #2d6ca2;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
}
.btn-primary:active,
.btn-primary.active {
background-color: #3071a9;
border-color: #2d6ca2;
}
.btn-success {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44));
background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%);
background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
background-repeat: repeat-x;
border-color: #419641;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
}
.btn-success:active,
.btn-success.active {
background-color: #449d44;
border-color: #419641;
}
.btn-warning {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f));
background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%);
background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
background-repeat: repeat-x;
border-color: #eb9316;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
}
.btn-warning:active,
.btn-warning.active {
background-color: #ec971f;
border-color: #eb9316;
}
.btn-danger {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c));
background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%);
background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
background-repeat: repeat-x;
border-color: #c12e2a;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
}
.btn-danger:active,
.btn-danger.active {
background-color: #c9302c;
border-color: #c12e2a;
}
.btn-info {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5));
background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%);
background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
background-repeat: repeat-x;
border-color: #2aabd2;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
}
.btn-info:active,
.btn-info.active {
background-color: #31b0d5;
border-color: #2aabd2;
}
.thumbnail,
.img-thumbnail {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus,
.dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus {
background-color: #357ebd;
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
}
.navbar {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#f8f8f8));
background-image: -webkit-linear-gradient(top, #ffffff, 0%, #f8f8f8, 100%);
background-image: -moz-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
background-repeat: repeat-x;
border-radius: 4px;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
}
.navbar .navbar-nav > .active > a {
background-color: #f8f8f8;
}
.navbar-brand,
.navbar-nav > li > a {
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
}
.navbar-inverse {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#3c3c3c), to(#222222));
background-image: -webkit-linear-gradient(top, #3c3c3c, 0%, #222222, 100%);
background-image: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%);
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
}
.navbar-inverse .navbar-nav > .active > a {
background-color: #222222;
}
.navbar-inverse .navbar-brand,
.navbar-inverse .navbar-nav > li > a {
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.navbar-static-top,
.navbar-fixed-top,
.navbar-fixed-bottom {
border-radius: 0;
}
.alert {
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
}
.alert-success {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#c8e5bc));
background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #c8e5bc, 100%);
background-image: -moz-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
background-repeat: repeat-x;
border-color: #b2dba1;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
}
.alert-info {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#b9def0));
background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #b9def0, 100%);
background-image: -moz-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
background-repeat: repeat-x;
border-color: #9acfea;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
}
.alert-warning {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#f8efc0));
background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #f8efc0, 100%);
background-image: -moz-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
background-repeat: repeat-x;
border-color: #f5e79e;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
}
.alert-danger {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#e7c3c3));
background-image: -webkit-linear-gradient(top, #f2dede, 0%, #e7c3c3, 100%);
background-image: -moz-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
background-repeat: repeat-x;
border-color: #dca7a7;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
}
.progress {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(#f5f5f5));
background-image: -webkit-linear-gradient(top, #ebebeb, 0%, #f5f5f5, 100%);
background-image: -moz-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
}
.progress-bar {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
}
.progress-bar-success {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44));
background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%);
background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
}
.progress-bar-info {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5));
background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%);
background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
}
.progress-bar-warning {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f));
background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%);
background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
}
.progress-bar-danger {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c));
background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%);
background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
}
.list-group {
border-radius: 4px;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
}
.list-group-item.active,
.list-group-item.active:hover,
.list-group-item.active:focus {
text-shadow: 0 -1px 0 #3071a9;
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3278b3));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #3278b3, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #3278b3 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
background-repeat: repeat-x;
border-color: #3278b3;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
}
.panel {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.panel-default > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f5f5f5), to(#e8e8e8));
background-image: -webkit-linear-gradient(top, #f5f5f5, 0%, #e8e8e8, 100%);
background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
}
.panel-primary > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
}
.panel-success > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#d0e9c6));
background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #d0e9c6, 100%);
background-image: -moz-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
}
.panel-info > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#c4e3f3));
background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #c4e3f3, 100%);
background-image: -moz-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
}
.panel-warning > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#faf2cc));
background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #faf2cc, 100%);
background-image: -moz-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
}
.panel-danger > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#ebcccc));
background-image: -webkit-linear-gradient(top, #f2dede, 0%, #ebcccc, 100%);
background-image: -moz-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
}
.well {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#e8e8e8), to(#f5f5f5));
background-image: -webkit-linear-gradient(top, #e8e8e8, 0%, #f5f5f5, 100%);
background-image: -moz-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
background-repeat: repeat-x;
border-color: #dcdcdc;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
}
File diff suppressed because one or more lines are too long
+3904 -1791
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -62,7 +62,8 @@ angular.module('ansible', [
'AccessHelper',
'SelectionHelper',
'LicenseFormDefinition',
'License'
'License',
'HostGroupsFormDefinition'
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.
+15 -4
View File
@@ -185,7 +185,7 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInit, Prompt,
OrganizationList, TreeInit, GetBasePath, GroupsList, GroupsAdd, GroupsEdit, LoadInventory,
GroupsDelete, HostsList, HostsAdd, HostsEdit, HostsDelete, RefreshGroupName, ParseTypeChange,
HostsReload, EditInventory, RefreshTree, LoadSearchTree)
HostsReload, EditInventory, RefreshTree, LoadSearchTree, EditHostGroups)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
@@ -204,6 +204,8 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
scope['inventoryParseType'] = 'yaml';
scope['inventory_id'] = id;
scope['inventoryFailureFilter'] = false;
scope['hostDeleteDisabled'] = true;
scope['hostDeleteDisabledClass'] = 'disabled';
// Retrieve each related sets and any lookups
if (scope.inventoryLoadedRemove) {
@@ -447,6 +449,10 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
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' });
@@ -472,7 +478,8 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
}
scope.toggleAllHosts = function() {
scope.hostDeleteHide = (scope.toggleAllFlag) ? false : true;
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;
}
@@ -486,9 +493,11 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
break;
}
}
scope.hostDeleteHide = result;
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;
@@ -503,6 +512,8 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
scope.hostCreateHide = false;
scope.hostDeleteHide = false;
}
scope['hostDeleteDisabled'] = true;
scope['hostDeleteDisabledClass'] = 'disabled';
HostsReload({ scope: scope, inventory_id: scope['inventory_id'], group_id: group });
});
@@ -513,6 +524,6 @@ InventoriesEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$l
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'LookUpInit', 'Prompt',
'OrganizationList', 'TreeInit', 'GetBasePath', 'GroupsList', 'GroupsAdd', 'GroupsEdit', 'LoadInventory',
'GroupsDelete', 'HostsList', 'HostsAdd', 'HostsEdit', 'HostsDelete', 'RefreshGroupName',
'ParseTypeChange', 'HostsReload', 'EditInventory', 'RefreshTree', 'LoadSearchTree'
'ParseTypeChange', 'HostsReload', 'EditInventory', 'RefreshTree', 'LoadSearchTree', 'EditHostGroups'
];
+61
View File
@@ -0,0 +1,61 @@
/*********************************************
* Copyright (c) 2013 AnsibleWorks, Inc.
*
* HostGroups.js
* Form definition for Host model
*
*
*/
angular.module('HostGroupsFormDefinition', [])
.value(
'HostGroupsForm', {
editTitle: 'Host Groups', //Legend in edit mode
name: 'host', //Form name attribute
well: false, //Wrap the form with TB well
formLabelSize: 'col-lg-3',
formFieldSize: 'col-lg-9',
fields: {
groups: {
label: 'Groups',
type: 'select',
multiple: true,
ngOptions: 'group.name for group in inventory_groups',
addRequired: true,
editRequired: true,
awPopOver: "<p>Provide a host name, ip address, or ip address:port. Examples include:</p>" +
"<blockquote>myserver.domain.com<br/>" +
"127.0.0.1<br />" +
"10.1.0.140:25<br />" +
"server.example.com:25" +
"</blockquote>",
dataTitle: 'Host Name',
dataPlacement: 'right',
dataContainer: '#form-modal .modal-content'
}
},
buttons: { //for now always generates <button> tags
save: {
label: 'Save',
icon: 'icon-ok',
"class": 'btn-success',
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
},
reset: {
ngClick: 'formReset()',
label: 'Reset',
icon: 'icon-trash',
'class': 'btn btn-default',
ngDisabled: true //Disabled when $pristine
}
},
related: { //related colletions (and maybe items?)
}
}); //UserForm
+4 -8
View File
@@ -96,14 +96,6 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
scope.parseType = 'yaml';
ParseTypeChange(scope);
//$('#form-modal').on('hidden.bs.modal', function() {
// var me = $(this);
// $('.modal-backdrop').each(function(index) {
// $(this).remove();
// });
// me.unbind('hidden.bs.modal');
// });
$('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success');
generator.reset();
@@ -116,6 +108,8 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
// Save
scope.formModalAction = function() {
try {
scope.formModalActionDisabled = true;
// Make sure we have valid variable data
if (scope.parseType == 'json') {
@@ -162,11 +156,13 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
}
})
.error( function(data, status, headers, config) {
scope.formModalActionDisabled = false;
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to add new group. POST returned status: ' + status });
});
}
catch(err) {
scope.formModalActionDisabled = false;
Alert("Error", "Error parsing group variables. Parser returned: " + err);
}
}
+365 -37
View File
@@ -10,7 +10,7 @@
angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'HostListDefinition',
'SearchHelper', 'PaginateHelper', 'ListGenerator', 'AuthService', 'HostsHelper',
'InventoryHelper', 'RelatedSearchHelper','RelatedPaginateHelper',
'InventoryFormDefinition', 'SelectionHelper'
'InventoryFormDefinition', 'SelectionHelper', 'HostGroupsFormDefinition'
])
.factory('HostsList', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostList', 'GenerateList',
@@ -98,7 +98,6 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
scope.removeHostsReload();
}
scope.removeHostsReload = scope.$on('hostsReload', function() {
console.log('here!');
HostsReload(params);
});
@@ -122,6 +121,9 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
}
try {
scope.formModalActionDisabled = true;
// Make sure we have valid variable data
if (scope.parseType == 'json') {
var json_data = JSON.parse(scope.variables); //make sure JSON parses
@@ -162,11 +164,13 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
}
})
.error( function(data, status, headers, config) {
scope.formModalActionDisabled = false;
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to add new host. POST returned status: ' + status });
});
}
catch(err) {
scope.formModalActionDisabled = false;
Alert("Error", "Error parsing host variables. Parser returned: " + err);
}
}
@@ -200,7 +204,7 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
var relatedSets = {};
scope.formModalActionLabel = 'Save';
scope.formModalHeader = 'Edit Host';
scope.formModalHeader = 'Host Properties';
scope.formModalCancelShow = true;
scope.parseType = 'yaml';
ParseTypeChange(scope);
@@ -347,8 +351,14 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
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;
@@ -432,13 +442,15 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
}])
.factory('HostsReload', ['RelatedSearchInit', 'RelatedPaginateInit', 'InventoryForm', 'GetBasePath',
function(RelatedSearchInit, RelatedPaginateInit, InventoryForm, GetBasePath) {
.factory('HostsReload', ['RelatedSearchInit', 'RelatedPaginateInit', 'InventoryForm', 'GetBasePath', 'Wait',
function(RelatedSearchInit, RelatedPaginateInit, InventoryForm, 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 postAction = params.action;
scope['hosts'] = null;
scope['toggleAllFlag'] = false;
scope['hostDeleteHide'] = true;
@@ -450,26 +462,24 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
url += '?has_active_failures=true';
}
// Set the groups value in each element of hosts array
if (scope.removeRelatedHosts) {
scope.removeRelatedHosts();
}
scope.removeRelatedHosts = scope.$on('relatedhosts', function() {
var groups, descr='';
var groups, descr, found, list;
for (var i=0; i < scope.hosts.length; i++) {
groups = scope.hosts[i].summary_fields.groups;
for (var j=0; j < groups.length; j++) {
if (groups[j].name.match(/^_deleted/)) {
descr += groups[j].name.substr(1,18) + ', ';
}
else {
descr += groups[j].name + ', ';
}
}
descr = descr.replace(/, $/,'');
if (descr.length > 50) {
descr = descr.substr(0,49) + '...';
}
scope.hosts[i].groups = descr;
groups = scope.hosts[i].summary_fields.groups;
scope.hosts[i].groups = '';
for (var k=0; k < groups.length; k++) {
if (!groups[k].name.match(/^_deleted/)) {
scope.hosts[i].groups += groups[k].name + ', '
}
}
scope.hosts[i].groups = scope.hosts[i].groups.replace(/\, $/,'');
}
if (postAction) {
postAction();
}
});
@@ -477,19 +487,6 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
RelatedSearchInit({ scope: params.scope, form: InventoryForm, relatedSets: relatedSets });
RelatedPaginateInit({ scope: params.scope, relatedSets: relatedSets, pageSize: 40 });
/*if (scope['hostFailureFilter']) {
// If the user checked 'show only hosts with failures', filter for hosts with failed jobs
scope['hostSearchFieldLabel'] = 'Failed jobs?';
scope['hostSearchField'] = 'has_active_failures';
scope['hostSelectShow'] = true;
scope.setSearchField('host','has_active_failures','Failed jobs?');
for (var i=0; i < scope['hostSearchSelectOpts'].length; i++) {
if (scope['hostSearchSelectOpts'][i].value == 1) {
scope['hostSearchSelectValue'] = scope['hostSearchSelectOpts'][i];
}
}
} */
scope.search('host');
if (!params.scope.$$phase) {
@@ -498,16 +495,38 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
}
}])
.factory('LoadSearchTree', ['Rest', 'GetBasePath', 'ProcessErrors', '$compile',
function(Rest, GetBasePath, ProcessErrors, $compile) {
return function(params) {
var scope = params.scope;
var inventory_id = params.inventory_id;
var newTree = [];
scope.searchTree = [];
// After the inventory is loaded, build an array of all unique groups found therein.
// The lis is used in the group drop-down selector widget for each host.
if (scope.buildAllGroupsRemove) {
scope.buildAllGroupsRemove();
}
scope.buildAllGroupsRemove = scope.$on('buildAllGroups', function() {
scope.inventory_groups = [];
Rest.setUrl(GetBasePath('inventory') + inventory_id + '/groups/?order_by=name');
Rest.get()
.success( function(data, status, headers, config) {
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');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get groups for inventory: ' + inventory_id + '. GET returned: ' + status });
});
});
// Load the root node
// Load the inventory root node
Rest.setUrl (GetBasePath('inventory') + inventory_id + '/');
Rest.get()
.success( function(data, status, headers, config) {
@@ -519,14 +538,323 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
groups: data.related.root_groups,
children: []
});
scope.$emit('hostTabInit');
scope.$emit('buildAllGroups');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status });
});
}
}])
.factory('EditHostGroups', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait',
function($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors,
GetBasePath, HostsReload, ParseTypeChange, Wait) {
return function(params) {
var host_id = params.host_id;
var inventory_id = params.inventory_id;
var generator = GenerateForm;
var actions = [];
var html="<div class=\"host-groups-title\"><h4>{{ host.name }}</h4></div>\n";
html += "<div class=\"row host-groups\">\n";
html += "<div class=\"col-lg-6\">\n";
html += "<label>Available Groups:</label>\n";
html += "<select multiple class=\"form-control\" name=\"available-groups\" ng-model=\"selectedGroups\" ng-change=\"leftChange()\" " +
"ng-options=\"avail_group.name for avail_group in available_groups\"></select>\n";
html += "</div>\n";
html += "<div class=\"col-lg-6\">\n";
html += "<label>Belongs to Groups:</label>\n";
html += "<select multiple class=\"form-control\" name=\"selected-groups\" ng-model=\"assignedGroups\" ng-change=\"rightChange()\" " +
"ng-options=\"host_group.name for host_group in host_groups\"></select>\n";
html += "</div>\n";
html += "</div>\n";
html += "<div class=\"row host-group-buttons\">\n";
html += "<div class=\"col-lg-12\">\n";
html += "<button type=\"button\" ng-click=\"moveLeft()\" class=\"btn btn-sm btn-primary left-button\" ng-disabled=\"leftButtonDisabled\">" +
"<i class=\"icon-arrow-left\"></i></button>\n";
html += "<button type=\"button\" ng-click=\"moveRight()\" class=\"btn btn-sm btn-primary right-button\" ng-disabled=\"rightButtonDisabled\">" +
"<i class=\"icon-arrow-right\"></i></button>\n";
html += "<p>(move selected groups)</p>\n";
html += "</div>\n";
html += "</div>\n";
var defaultUrl = GetBasePath('hosts') + host_id + '/';
var scope = generator.inject(null, { mode: 'edit', modal: true, related: false, html: html });
for (var i=0; i < scope.hosts.length; i++) {
if (scope.hosts[i].id == host_id) {
scope.host = scope.hosts[i];
}
}
scope.selectedGroups = null;
scope.assignedGroups = null;
scope.leftButtonDisabled = true;
scope.rightButtonDisabled = true;
scope.formModalActionLabel = 'Save';
scope.formModalHeader = 'Host Groups';
scope.formModalCancelShow = true;
scope.formModalActionDisabled = true;
$('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success');
if (scope.hostGroupChangeRemove) {
scope.hostGroupChangeRemove();
}
scope.hostGroupChangeRemove = scope.$on('hostGroupChange', function(e) {
actions.pop();
if (actions.length == 0) {
var postAction = function() {
setTimeout(function() { Wait('stop') }, 500);
};
HostsReload({ scope: scope, inventory_id: inventory_id, group_id: scope.group_id , action: postAction });
}
});
// Save changes
scope.formModalAction = function() {
var found;
$('#form-modal').modal('hide');
Wait('start');
// removed host from deleted groups
for (var i=0; i < scope.original_groups.length; i++) {
found = false;
for (var j=0; j < scope.host_groups.length; j++) {
if (scope.original_groups[i].id == scope.host_groups[j].id) {
found = true;
}
}
if (!found) {
// group was removed
actions.push({ group_id: scope.original_groups[i].id , action: 'delete' });
Rest.setUrl(GetBasePath('groups') + scope.original_groups[i].id + '/hosts/');
Rest.post({ id: host_id, disassociate: 1 })
.success( function(data, status, headers, config) {
scope.$emit('hostGroupChange');
})
.error( function(data, status, headers, config) {
scope.$emit('hostGroupChange');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Attempt to remove host from group ' + scope.original_groups[i].name +
' failed. POST returned status: ' + status });
});
}
}
// add host to new groups
for (var i=0; i < scope.host_groups.length; i++) {
found = false;
for (var j=0; j < scope.original_groups.length; j++) {
if (scope.original_groups[j].id == scope.host_groups[i].id) {
found = true;
}
}
if (!found) {
// group was added
actions.push({ group_id: scope.host_groups[i].id , action: 'add' });
Rest.setUrl(GetBasePath('groups') + scope.host_groups[i].id + '/hosts/');
Rest.post(scope.host)
.success( function(data, status, headers, config) {
scope.$emit('hostGroupChange');
})
.error( function(data, status, headers, config) {
scope.$emit('hostGroupChange');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Attempt to add host to group ' + scope.host_groups[i].name +
' failed. POST returned status: ' + status });
});
}
}
}
scope.leftChange = function() {
// Select/deselect on available groups list
if (scope.selectedGroups !== null && scope.selectedGroups.length > 0) {
scope.assignedGroups = null;
scope.leftButtonDisabled = true;
scope.rightButtonDisabled = false;
}
else {
scope.rightButtonDisabled = true;
}
}
scope.rightChange = function() {
// Select/deselect made on host groups list
if (scope.assignedGroups !== null && scope.assignedGroups.length > 0) {
scope.selectedGroups = null;
scope.leftButtonDisabled = false;
scope.rightButtonDisabled = true;
}
else {
scope.leftButtonDisabled = true;
}
}
scope.moveLeft = function() {
// Remove selected groups from the list of assigned groups
for (var i=0; i < scope.assignedGroups.length; i++){
for (var j=0 ; j < scope.host_groups.length; j++) {
if (scope.host_groups[j].id == scope.assignedGroups[i].id) {
scope.host_groups.splice(j,1);
break;
}
}
}
var found, placed;
for (var i=0; i < scope.assignedGroups.length; i++){
found = false;
for (var j=0; j < scope.available_groups.length && !found; j++){
if (scope.available_groups[j].id == scope.assignedGroups[i].id) {
found=true;
}
}
if (!found) {
placed = false;
for (var j=0; j < scope.available_groups.length && !placed; j++){
if (j == 0 && scope.assignedGroups[i].name.toLowerCase() < scope.available_groups[j].name.toLowerCase()) {
// prepend to the beginning of the array
placed=true;
scope.available_groups.unshift(scope.assignedGroups[i]);
}
else if (j + 1 < scope.available_groups.length) {
if (scope.assignedGroups[i].name.toLowerCase() > scope.available_groups[j].name.toLowerCase() &&
scope.assignedGroups[i].name.toLowerCase() < scope.available_groups[j + 1].name.toLowerCase() ) {
// insert into the middle of the array
placed = true;
scope.available_groups.splice(j + 1, 0, scope.assignedGroups[i]);
}
}
}
if (!placed) {
// append to the end of the array
scope.available_groups.push(scope.assignedGroups[i]);
}
}
}
scope.assignedGroups = null;
scope.leftButtonDisabled = true;
scope.rightButtonDisabled = true;
scope.formModalActionDisabled = false;
}
scope.moveRight = function() {
// Remove selected groups from list of available groups
for (var i=0; i < scope.selectedGroups.length; i++){
for (var j=0 ; j < scope.available_groups.length; j++) {
if (scope.available_groups[j].id == scope.selectedGroups[i].id) {
scope.available_groups.splice(j,1);
break;
}
}
}
var found, placed;
for (var i=0; i < scope.selectedGroups.length; i++){
found = false;
for (var j=0; j < scope.host_groups.length && !found; j++){
if (scope.host_groups[j].id == scope.selectedGroups[i].id) {
found=true;
}
}
if (!found) {
placed = false;
for (var j=0; j < scope.host_groups.length && !placed; j++){
if (j == 0 && scope.selectedGroups[i].name.toLowerCase() < scope.host_groups[j].name.toLowerCase()) {
// prepend to the beginning of the array
placed=true;
scope.host_groups.unshift(scope.selectedGroups[i]);
}
else if (j + 1 < scope.host_groups.length) {
if (scope.selectedGroups[i].name.toLowerCase() > scope.host_groups[j].name.toLowerCase() &&
scope.selectedGroups[i].name.toLowerCase() < scope.host_groups[j + 1].name.toLowerCase() ) {
// insert into the middle of the array
placed = true;
scope.host_groups.splice(j + 1, 0, scope.selectedGroups[i]);
}
}
}
if (!placed) {
// append to the end of the array
scope.host_groups.push(scope.selectedGroups[i]);
}
}
}
scope.selectedGroups = null;
scope.leftButtonDisabled = true;
scope.rightButtonDisabled = true;
scope.formModalActionDisabled = false;
}
// Load the host's current list of groups
scope.host_groups = [];
scope.original_groups = [];
scope.available_groups = [];
Rest.setUrl(scope.host.related.groups + '?order_by=name');
Rest.get()
.success( function(data, status, headers, config) {
for (var i=0; i < data.results.length; i++) {
scope.host_groups.push({
id: data.results[i].id,
name: data.results[i].name,
description: data.results[i].description
});
scope.original_groups.push({
id: data.results[i].id,
name: data.results[i].name,
description: data.results[i].description
});
}
var found;
for (var i=0; i < scope.inventory_groups.length; i++) {
found = false;
for (var j=0; j < scope.host_groups.length; j++) {
if (scope.inventory_groups[i].id == scope.host_groups[j].id) {
found = true;
}
}
if (!found) {
scope.available_groups.push(scope.inventory_groups[i]);
}
}
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get current groups for host: ' + host_id + '. GET returned: ' + status });
});
if (scope.removeHostsReload) {
scope.removeHostsReload();
}
scope.removeHostsReload = scope.$on('hostsReload', function() {
HostsReload(params);
});
// After the group record is loaded, retrieve any group variables
if (scope.hostLoadedRemove) {
scope.hostLoadedRemove();
}
scope.hostLoadedRemove = scope.$on('hostLoaded', function() {
});
if (!scope.$$phase) {
scope.$digest();
}
}
}]);
+61 -51
View File
@@ -22,6 +22,7 @@ angular.module('SelectionHelper', ['Utilities', 'RestServices'])
var returnToCaller = params.returnToCaller;
scope.selected = []; //array of selected row IDs
scope.formModalActionDisabled = true;
// toggle row selection
scope['toggle_' + list.iterator] = function(id, ischeckbox) {
@@ -59,62 +60,71 @@ angular.module('SelectionHelper', ['Utilities', 'RestServices'])
}
}
}
if (scope.selected.length > 0) {
scope.formModalActionDisabled = false;
}
else {
scope.formModalActionDisabled = true;
}
}
scope.finishSelection = function() {
Rest.setUrl(target_url);
scope.queue = [];
function finished() {
scope.selected = [];
if (returnToCaller !== undefined) {
ReturnToCaller(returnToCaller);
if (target_url) {
scope.finishSelection = function() {
Rest.setUrl(target_url);
scope.queue = [];
scope.formModalActionDisabled = true;
function finished() {
scope.selected = [];
if (returnToCaller !== undefined) {
ReturnToCaller(returnToCaller);
}
else {
$('#form-modal').modal('hide');
scope.$emit('modalClosed');
}
}
if (scope.callFinishedRemove) {
scope.callFinishedRemove();
}
scope.callFinishedRemove = scope.$on('callFinished', function() {
// We call the API for each selected item. We need to hang out until all the api
// calls are finished.
if (scope.queue.length == scope.selected.length) {
var errors = 0;
for (var i=0; i < scope.queue.length; i++) {
if (scope.queue[i].result == 'error') {
ProcessErrors(scope, scope.queue[i].data, scope.queue[i].status, null,
{ hdr: 'POST Failure', msg: 'Failed to add ' + list.iterator +
'. POST returned status: ' + scope.queue[i].status });
errors++;
}
}
if (errors == 0) {
finished();
}
}
});
if (scope.selected.length > 0 ) {
for (var j=0; j < scope.selected.length; j++) {
Rest.post(scope.selected[j])
.success( function(data, status, headers, config) {
scope.queue.push({ result: 'success', data: data, status: status });
scope.$emit('callFinished');
})
.error( function(data, status, headers, config) {
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
scope.$emit('callFinished');
});
}
}
else {
$('#form-modal').modal('hide');
scope.$emit('modalClosed');
finished();
}
}
}
if (scope.callFinishedRemove) {
scope.callFinishedRemove();
}
scope.callFinishedRemove = scope.$on('callFinished', function() {
// We call the API for each selected item. We need to hang out until all the api
// calls are finished.
if (scope.queue.length == scope.selected.length) {
var errors = 0;
for (var i=0; i < scope.queue.length; i++) {
if (scope.queue[i].result == 'error') {
ProcessErrors(scope, scope.queue[i].data, scope.queue[i].status, null,
{ hdr: 'POST Failure', msg: 'Failed to add ' + list.iterator +
'. POST returned status: ' + scope.queue[i].status });
errors++;
}
}
if (errors == 0) {
finished();
}
}
});
if (scope.selected.length > 0 ) {
for (var j=0; j < scope.selected.length; j++) {
Rest.post(scope.selected[j])
.success( function(data, status, headers, config) {
scope.queue.push({ result: 'success', data: data, status: status });
scope.$emit('callFinished');
})
.error( function(data, status, headers, config) {
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
scope.$emit('callFinished');
});
}
}
else {
finished();
}
}
}
scope.formModalAction = scope.finishSelection;
+1 -1
View File
@@ -59,7 +59,7 @@ angular.module('RelatedPaginateHelper', ['RefreshRelatedHelper', 'ngCookies'])
$cookieStore.put(iterator + 'PageSize', scope[iterator + 'PageSize']);
url = url.replace(/\/\?.*$/,'/');
url += (scope[iterator + 'SearchParams']) ? scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + 'PageSize' ] :
url += (scope[iterator + 'SearchParams']) ? '?' + scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + 'PageSize' ] :
'?page_size=' + scope[iterator + 'PageSize' ];
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: url });
}
+3 -3
View File
@@ -49,7 +49,7 @@ angular.module('CredentialsListDefinition', [])
mode: 'all', // One of: edit, select, all
ngClick: 'addCredential()',
basePaths: ['teams','users'], // base path must be in list, or action not available
"class": 'btn-success btn-mini',
"class": 'btn-success btn-sm',
awToolTip: 'Create a new credential'
}
},
@@ -59,7 +59,7 @@ angular.module('CredentialsListDefinition', [])
ngClick: "editCredential(\{\{ credential.id \}\})",
icon: 'icon-edit',
label: 'Edit',
"class": 'btn-mini btn-default',
"class": 'btn-xs btn-default',
awToolTip: 'View/Edit credential'
},
@@ -67,7 +67,7 @@ angular.module('CredentialsListDefinition', [])
ngClick: "deleteCredential(\{\{ credential.id \}\},'\{\{ credential.name \}\}')",
icon: 'icon-trash',
label: 'Delete',
"class": 'btn-mini btn-danger',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete credential'
}
}
+3 -3
View File
@@ -35,7 +35,7 @@ angular.module('GroupListDefinition', [])
dataContainer: '#form-modal .modal-content',
icon: "icon-question-sign",
mode: 'all',
'class': 'btn-mini btn-info btn-help',
'class': 'btn-xs btn-info btn-help pull-right',
awToolTip: 'Click for help',
dataTitle: 'Adding Groups',
id: 'group-help-button',
@@ -48,7 +48,7 @@ angular.module('GroupListDefinition', [])
label: 'Edit',
ngClick: "editGroup(\{\{ group.id \}\})",
icon: 'icon-edit',
"class": 'btn-mini btn-default',
"class": 'btn-xs btn-default',
awToolTip: 'View/Edit group'
},
@@ -56,7 +56,7 @@ angular.module('GroupListDefinition', [])
label: 'Delete',
ngClick: "deleteGroup(\{\{ group.id \}\},'\{\{ group.name \}\}')",
icon: 'icon-trash',
"class": 'btn-mini btn-danger',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete group'
}
}
+3 -3
View File
@@ -35,7 +35,7 @@ angular.module('HostListDefinition', [])
dataContainer: '#form-modal .modal-content',
icon: "icon-question-sign",
mode: 'all',
'class': 'btn-mini btn-info btn-help',
'class': 'btn-xs btn-info btn-help',
awToolTip: 'Click for help',
dataTitle: 'Selecting Hosts',
iconSize: 'large',
@@ -48,7 +48,7 @@ angular.module('HostListDefinition', [])
label: 'Edit',
ngClick: "editHost(\{\{ host.id \}\})",
icon: 'icon-edit',
"class": 'btn-mini btn-default',
"class": 'btn-xs btn-default',
awToolTip: 'View/Edit host'
},
@@ -56,7 +56,7 @@ angular.module('HostListDefinition', [])
label: 'Delete',
ngClick: "deleteHost(\{\{ host.id \}\},'\{\{ host.name \}\}')",
icon: 'icon-trash',
"class": 'btn-mini btn-danger',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete host'
}
}
+3 -3
View File
@@ -54,7 +54,7 @@ angular.module('InventoriesListDefinition', [])
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addInventory()',
"class": 'btn-mini btn-success',
"class": 'btn-sm btn-success',
awToolTip: 'Create a new inventory'
}
},
@@ -64,7 +64,7 @@ angular.module('InventoriesListDefinition', [])
label: 'Edit',
ngClick: "editInventory(\{\{ inventory.id \}\})",
icon: 'icon-edit',
"class": 'btn-mini btn-default',
"class": 'btn-xs btn-default',
awToolTip: 'View/Edit inventory'
},
@@ -72,7 +72,7 @@ angular.module('InventoriesListDefinition', [])
label: 'Delete',
ngClick: "deleteInventory(\{\{ inventory.id \}\},'\{\{ inventory.name \}\}')",
icon: 'icon-trash',
"class": 'btn-mini btn-danger',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete inventory'
}
}
+4 -4
View File
@@ -63,14 +63,14 @@ angular.module('JobEventsListDefinition', [])
icon: 'icon-refresh',
label: 'Refresh',
awToolTip: 'Refresh the page',
"class": 'btn-mini btn-success',
"class": 'btn-sm btn-success',
mode: 'all'
},
edit: {
label: 'Details',
ngClick: "jobDetails()",
icon: 'icon-zoom-in',
"class": 'btn btn-default btn-mini',
"class": 'btn btn-default btn-sm',
awToolTip: 'Edit job details',
mode: 'all'
},
@@ -78,7 +78,7 @@ angular.module('JobEventsListDefinition', [])
label: 'Hosts',
icon: 'icon-th-large',
ngClick: "jobSummary()",
"class": 'btn btn-default btn-mini',
"class": 'btn btn-default btn-sm',
awToolTip: 'View host summary',
mode: 'all'
}
@@ -89,7 +89,7 @@ angular.module('JobEventsListDefinition', [])
label: 'View',
ngClick: "viewJobEvent(\{\{ jobevent.id \}\})",
icon: 'icon-zoom-in',
"class": 'btn-default btn-mini',
"class": 'btn-default btn-xs',
awToolTip: 'View event details'
}
}
+6 -6
View File
@@ -60,7 +60,7 @@ angular.module('JobHostDefinition', [])
label: 'Refresh',
icon: 'icon-refresh',
ngClick: "refresh()",
"class": 'btn-success btn-mini',
"class": 'btn-success btn-sm',
awToolTip: 'Refresh the page',
mode: 'all'
},
@@ -68,7 +68,7 @@ angular.module('JobHostDefinition', [])
label: 'Details',
icon: 'icon-edit',
ngClick: "jobDetails()",
"class": 'btn btn-default btn-mini',
"class": 'btn btn-default btn-sm',
awToolTip: 'Edit job details',
mode: 'all'
},
@@ -76,7 +76,7 @@ angular.module('JobHostDefinition', [])
label: 'Events',
icon: 'icon-list-ul',
ngClick: "jobEvents()",
"class": 'btn btn-default btn-mini',
"class": 'btn btn-default btn-sm',
awToolTip: 'View job events',
mode: 'all'
},
@@ -87,11 +87,11 @@ angular.module('JobHostDefinition', [])
"<dt>Unreachable</dt><dd>Times the ansible server could not reach the host.</dd>\n" +
"<dt>Skipped</dt><dd>Tasks bypassed and not performed on the host due to prior task failure or the host being unreachable.</dd>\n" +
"</dl>\n",
dataPlacement: 'right',
dataContainer: ".container",
dataPlacement: 'left',
dataContainer: "body",
icon: "icon-question-sign",
mode: 'all',
'class': 'btn-info btn-mini btn-help',
'class': 'btn-info btn-xs btn-help pull-right',
awToolTip: 'Click for help',
dataTitle: 'Job Host Summary',
id: 'jobhost-help-button',
+4 -4
View File
@@ -34,7 +34,7 @@ angular.module('JobTemplatesListDefinition', [])
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addJobTemplate()',
"class": 'btn-success btn-mini',
"class": 'btn-success btn-sm',
basePaths: ['job_templates'],
awToolTip: 'Create a new template'
}
@@ -46,13 +46,13 @@ angular.module('JobTemplatesListDefinition', [])
ngClick: "editJobTemplate(\{\{ job_template.id \}\})",
icon: 'icon-edit',
awToolTip: 'Edit template',
"class": 'btn-default btn-mini'
"class": 'btn-default btn-xs'
},
submit: {
label: 'Launch',
icon: 'icon-rocket',
mode: 'all',
"class": 'btn-mini btn-success',
"class": 'btn-xs btn-success',
ngClick: 'submitJob(\{\{ job_template.id \}\})',
awToolTip: 'Start a job using this template'
},
@@ -60,7 +60,7 @@ angular.module('JobTemplatesListDefinition', [])
label: 'Delete',
ngClick: "deleteJobTemplate(\{\{ job_template.id \}\},'\{\{ job_template.name \}\}')",
icon: 'icon-trash',
"class": 'btn-danger btn-mini',
"class": 'btn-danger btn-xs',
awToolTip: 'Delete template'
}
}
+7 -7
View File
@@ -57,7 +57,7 @@ angular.module('JobsListDefinition', [])
actions: {
refresh: {
label: 'Refresh',
"class": 'btn-success btn-mini',
"class": 'btn-success btn-sm',
ngClick: "refreshJob(\{\{ job.id \}\})",
icon: 'icon-refresh',
awToolTip: 'Refresh the page',
@@ -70,7 +70,7 @@ angular.module('JobsListDefinition', [])
label: 'Hosts',
icon: 'icon-th-large',
ngClick: "viewSummary(\{{ job.id \}\}, '\{\{ job.name \}\}')",
"class": 'btn btn-default btn-mini',
"class": 'btn btn-default btn-xs',
awToolTip: 'View host summary',
ngDisabled: "job.status == 'new'"
},
@@ -79,7 +79,7 @@ angular.module('JobsListDefinition', [])
icon: 'icon-list-ul',
mode: 'all',
ngClick: "viewEvents(\{{ job.id \}\}, '\{\{ job.name \}\}')",
"class": 'btn btn-default btn-mini',
"class": 'btn btn-default btn-xs',
awToolTip: 'View events',
ngDisabled: "job.status == 'new'"
},
@@ -87,21 +87,21 @@ angular.module('JobsListDefinition', [])
label: 'Details',
icon: 'icon-zoom-in',
ngClick: "editJob(\{\{ job.id \}\}, '\{\{ job.name \}\}')",
"class": 'btn btn-default btn-mini',
"class": 'btn btn-default btn-xs',
awToolTip: 'View job details'
},
rerun: {
icon: 'icon-retweet',
mode: 'all',
ngClick: "submitJob(\{\{ job.id \}\}, '\{\{ job.summary_fields.job_template.name \}\}' )",
"class": 'btn-success btn-mini',
"class": 'btn-success btn-xs',
awToolTip: 'Re-run this job'
},
cancel: {
icon: 'icon-minus-sign',
mode: 'all',
ngClick: 'deleteJob(\{\{ job.id \}\})',
"class": 'btn-danger btn-mini',
"class": 'btn-danger btn-xs',
awToolTip: 'Cancel job',
ngShow: "job.status == 'pending' || job.status == 'running'"
},
@@ -109,7 +109,7 @@ angular.module('JobsListDefinition', [])
icon: 'icon-trash',
mode: 'all',
ngClick: 'deleteJob(\{\{ job.id \}\})',
"class": 'btn-danger btn-mini',
"class": 'btn-danger btn-xs',
awToolTip: 'Delete this job',
ngShow: "job.status != 'pending' && job.status != 'running'"
}
+3 -3
View File
@@ -33,7 +33,7 @@ angular.module('OrganizationListDefinition', [])
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addOrganization()',
"class": 'btn-success btn-mini',
"class": 'btn-success btn-sm',
awToolTip: 'Create a new organization'
}
},
@@ -43,7 +43,7 @@ angular.module('OrganizationListDefinition', [])
label: 'Edit',
ngClick: "editOrganization(\{\{ organization.id \}\})",
icon: 'icon-edit',
"class": 'btn-mini btn-default',
"class": 'btn-xs btn-default',
awToolTip: 'View/Edit organization'
},
@@ -51,7 +51,7 @@ angular.module('OrganizationListDefinition', [])
label: 'Delete',
ngClick: "deleteOrganization(\{\{ organization.id \}\},'\{\{ organization.name \}\}')",
icon: 'icon-trash',
"class": 'btn-mini btn-danger',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete organization'
}
}
+3 -3
View File
@@ -47,7 +47,7 @@ angular.module('PermissionListDefinition', [])
label: 'Create New',
mode: 'all', // One of: edit, select, all
ngClick: 'addPermission()',
"class": 'btn-success btn-mini',
"class": 'btn-success btn-sm',
awToolTip: 'Add a new permission'
}
},
@@ -57,7 +57,7 @@ angular.module('PermissionListDefinition', [])
label: 'Edit',
ngClick: "editPermission(\{\{ permission.id \}\})",
icon: 'icon-edit',
"class": 'btn-mini btn-default',
"class": 'btn-xs btn-default',
awToolTip: 'View/Edit permission'
},
@@ -65,7 +65,7 @@ angular.module('PermissionListDefinition', [])
label: 'Delete',
ngClick: "deletePermission(\{\{ permission.id \}\},'\{\{ permission.name \}\}')",
icon: 'icon-trash',
"class": 'btn-mini btn-danger',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete permission'
}
}
+3 -3
View File
@@ -35,7 +35,7 @@ angular.module('ProjectsListDefinition', [])
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addProject()',
"class": 'btn-success btn-mini',
"class": 'btn-success btn-sm',
awToolTip: 'Create a new project'
}
},
@@ -45,7 +45,7 @@ angular.module('ProjectsListDefinition', [])
label: 'Edit',
ngClick: "editProject(\{\{ project.id \}\})",
icon: 'icon-edit',
"class": 'btn-mini btn-default',
"class": 'btn-xs btn-default',
awToolTip: 'View/edit project'
},
@@ -53,7 +53,7 @@ angular.module('ProjectsListDefinition', [])
label: 'Delete',
ngClick: "deleteProject(\{\{ project.id \}\},'\{\{ project.name \}\}')",
icon: 'icon-trash',
"class": 'btn-mini btn-danger',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete project'
}
}
+3 -3
View File
@@ -40,7 +40,7 @@ angular.module('TeamsListDefinition', [])
icon: 'icon-plus',
mode: 'all', // One of: edit, select, all
ngClick: 'addTeam()',
"class": 'btn-mini btn-success',
"class": 'btn-sm btn-success',
awToolTip: 'Create a new team'
}
},
@@ -50,7 +50,7 @@ angular.module('TeamsListDefinition', [])
label: 'Edit',
ngClick: "editTeam(\{\{ team.id \}\})",
icon: 'icon-edit',
"class": 'btn-mini btn-default',
"class": 'btn-xs btn-default',
awToolTip: 'View/Edit team'
},
@@ -58,7 +58,7 @@ angular.module('TeamsListDefinition', [])
label: 'Delete',
ngClick: "deleteTeam(\{\{ team.id \}\},'\{\{ team.name \}\}')",
icon: 'icon-trash',
"class": 'btn-mini btn-danger',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete team'
}
}
+3 -3
View File
@@ -40,7 +40,7 @@ angular.module('UserListDefinition', [])
mode: 'all', // One of: edit, select, all
ngClick: 'addUser()',
basePaths: ['organizations','users'], // base path must be in list, or action not available
"class": 'btn-success btn-mini',
"class": 'btn-success btn-sm',
awToolTip: 'Create a new user'
}
},
@@ -50,7 +50,7 @@ angular.module('UserListDefinition', [])
label: 'Edit',
ngClick: "editUser(\{\{ user.id \}\})",
icon: 'icon-edit',
"class": 'btn-mini btn-default',
"class": 'btn-xs btn-default',
awToolTip: 'View/Edit user'
},
@@ -58,7 +58,7 @@ angular.module('UserListDefinition', [])
label: 'Delete',
ngClick: "deleteUser(\{\{ user.id \}\},'\{\{ user.username \}\}')",
icon: 'icon-trash',
"class": 'btn-mini btn-danger',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete user'
}
}
+28
View File
@@ -307,6 +307,7 @@ legend {
}
.page-size {
height: 25px;
font-size: 10.5px;
line-height: normal;
}
@@ -573,6 +574,10 @@ input[type="text"].job-successful {
}
}
a.disabled {
color: @grey;
}
.navbar-form {
display: inline-block;
float: right;
@@ -642,6 +647,25 @@ input[type="text"].job-successful {
margin: 5px 0;
}
.host-groups {
margin-top: 15px;
select {
height: 150px;
}
}
.host-group-buttons {
margin-top: 20px;
text-align: center;
p {
padding-top: 10px;
font-size: 12px;
font-weight: normal;
}
}
.search-tree {
ul {
list-style-type: none;
@@ -671,6 +695,10 @@ input[type="text"].job-successful {
}
}
.disabled {
color: @grey;
}
.parse-selection {
display: inline-block;
margin: 5px 0 8px 0;
+37 -1
View File
@@ -279,6 +279,35 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
}
}])
.directive('awMultiSelect', [ function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
$(elm).multiselect ({
buttonClass: 'btn-default, btn-mini',
buttonWidth: 'auto',
buttonContainer: '<div class="btn-group" />',
maxHeight: false,
buttonText: function(options) {
if (options.length == 0) {
return 'None selected <b class="caret"></b>';
}
else if (options.length > 3) {
return options.length + ' selected <b class="caret"></b>';
}
else {
var selected = '';
options.each(function() {
selected += $(this).text() + ', ';
});
return selected.substr(0, selected.length -2) + ' <b class="caret"></b>';
}
}
});
}
}
}])
//
// Enable jqueryui spinner widget on a numeric input field
//
@@ -317,6 +346,9 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
}
}])
/* This has become more than a simple directive. All the logic for building the group selector tree
on the Hosts tab is here. Probably needs to move into the Hosts helper and/or Inventory helper.
*/
.directive('awTree', ['Rest', 'ProcessErrors', 'Authorization', '$compile', '$rootScope', 'Wait',
function(Rest, ProcessErrors, Authorization, $compile, $rootScope, Wait) {
return {
@@ -360,7 +392,8 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
else {
group = null;
title = 'All Hosts'
}
}
// The following will trigger the host list to load. See Inventory.js controller.
scope.$emit('refreshHost', group, title);
}
@@ -527,6 +560,9 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Hos
activateElm.bind('click', activate);
}
// Responds to hostTabInit event, thrown from Hosts.js helper. Once the initial
// inventory node is loaded, force the root level groups to load and populate the
// host list with All Hosts.
if ($rootScope.hostTabInitRemove) {
$rootScope.hostTabInitRemove();
}
+26 -7
View File
@@ -52,15 +52,18 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
if (options.buildTree) {
element.html(this.buildTree(options));
}
else if (options.html) {
element.html(options.html);
}
else {
element.html(this.build(options));
element.html(this.build(options));
}
this.scope = element.scope(); // Set scope specific to the element we're compiling, avoids circular reference
// From here use 'scope' to manipulate the form, as the form is not in '$scope'
$compile(element)(this.scope);
if (options.buildTree == undefined || options.buildTree == false) {
if (!options.buildTree == false && !options.html) {
// Reset the scope to prevent displaying old data from our last visit to this form
for (var fld in form.fields) {
this.scope[fld] = null;
@@ -86,7 +89,10 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
});
if (options.modal) {
this.scope.formHeader = (options.mode == 'add') ? form.addTitle : form.editTitle; //Default title for default modal
this.scope.formModalActionDisabled = false;
if (form) {
this.scope.formHeader = (options.mode == 'add') ? form.addTitle : form.editTitle; //Default title for default modal
}
this.scope.formModalInfo = false //Disable info button for default modal
if (options.modal_selector) {
$(options.modal_selector).modal({ show: true, backdrop: 'static', keyboard: true });
@@ -954,7 +960,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
"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-hide=\"hostDeleteHide\" " +
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";
@@ -988,7 +994,6 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
html += "<table class=\"" + form.related[itm].iterator + " table table-condensed table-hover\">\n";
html += "<thead>\n";
html += "<tr>\n";
//html += "<th>#</th>\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) {
@@ -1030,11 +1035,25 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
for (var fld in form.related[itm].fields) {
cnt++;
rfield = form.related[itm].fields[fld];
html += Column({ list: form.related[itm], fld: fld, options: options, base: base })
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 += "<td>";
html += "<div class=\"btn-group\">\n";
html += "<div class=\"btn-group btn-group-sm\">\n";
html += "<button type=\"button\" class=\"btn btn-default btn-mini dropdown-toggle\" data-toggle=\"dropdown\">";
html += "View <span class=\"caret\"></span></button>\n";
html += "<ul class=\"dropdown-menu pull-right\" role=\"menu\" aria-labelledby=\"dropdownMenu1\">\n";
+14 -13
View File
@@ -211,10 +211,12 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += (params.size) ? params.size : "col-lg-4";
html += "\">\n";
html += (label) ? "<label>" + label +"</label>" : "";
html += "<div class=\"input-group\">\n";
html += "<div class=\"input-group";
html += (useMini) ? " input-group-sm" : " input-group-sm";
html += "\">\n";
html += "<div class=\"input-group-btn\">\n";
html += "<button type=\"button\" class=\"btn ";
html += (useMini) ? "btn-mini " : "btn-small ";
// html += (useMini) ? "btn-mini " : "btn-small ";
html += "dropdown-toggle\" data-toggle=\"dropdown\">\n";
html += "<span ng-bind=\"" + iterator + "SearchFieldLabel\"></span>\n";
html += "<span class=\"caret\"></span>\n";
@@ -232,18 +234,18 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += "</div><!-- input-group-btn -->\n";
html += "<select ng-show=\"" + iterator + "SelectShow\" ng-model=\""+ iterator + "SearchSelectValue\" ng-change=\"search('" + iterator + "')\" ";
html += "ng-options=\"c.name for c in " + iterator + "SearchSelectOpts\" class=\"search-select";
html += (useMini) ? " input-mini" : " input-small";
html += "ng-options=\"c.name for c in " + iterator + "SearchSelectOpts\" class=\"form-control search-select";
//html += (useMini) ? " input-sm" : "";
html += "\"></select>\n";
html += "<input type=\"text\" ng-hide=\"" + iterator + "SelectShow || " + iterator + "InputHide\" class=\"form-control ";
html += (useMini) ? " input-mini" : " input-small";
//html += (useMini) ? " input-sm" : " input-sm";
html += "\" ng-model=\"" + iterator + "SearchValue\" ng-change=\"search('" + iterator +
"')\" placeholder=\"Search\" type=\"text\" >\n";
html += "<div class=\"input-group-btn\">\n";
html += "<button type=\"button\" ng-hide=\"" + iterator + "SelectShow || " + iterator + "HideSearchType || " + iterator + "InputHide\" class=\"btn ";
html += (useMini) ? "btn-mini " : "btn-small ";
//html += (useMini) ? "btn-x " : "btn-small ";
html += "dropdown-toggle\" data-toggle=\"dropdown\">\n";
html += "<span ng-bind=\"" + iterator + "SearchTypeLabel\"></span>\n";
html += "<span class=\"caret\"></span>\n";
@@ -279,21 +281,20 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += (useMini) ? " related-footer" : "";
html += "\">\n";
html += "<form class=\"form-inline\">\n";
html += "<button class=\"previous btn btn-light";
html += (useMini) ? " btn-mini\" " : "\" ";
html += "<button type=\"button\" class=\"previous btn btn-light";
html += (useMini) ? " btn-xs\" " : "\" ";
html += "ng-click=\"prevSet('" + set + "','" + iterator + "')\" " +
"ng-disabled=\"" + iterator + "PrevUrl == null || " + iterator + "PrevUrl == undefined\"><i class=\"icon-caret-left\"></i> Prev</button>\n";
html += "<button class=\"next btn btn-light";
html += (useMini) ? " btn-mini\" " : "\" ";
html += "<button type=\"button\" class=\"next btn btn-light";
html += (useMini) ? " btn-xs\" " : "\" ";
html += " ng-click=\"nextSet('" + set + "','" + iterator + "')\"" +
"ng-disabled=\"" + iterator + "NextUrl == null || " + iterator + "NextUrl == undefined\">Next <i class=\"icon-caret-right\"></i></button>\n";
if (mode != 'lookup') {
html += "<label class=\"page-size-label\">Rows per page: </label>\n";
html += "<select ng-model=\"" + iterator + "PageSize\" ng-change=\"changePageSize('" +
set + "'," + "'" + iterator + "')\" class=\"input-mini";
//html += (useMini) ? " field-mini-height" : "";
html += " page-size\">\n";
set + "'," + "'" + iterator + "')\" ";
html += "class=\"page-size\">\n";
html += "<option value=\"10\" selected>10</option>\n";
html += "<option value=\"20\" selected>20</option>\n";
html += "<option value=\"40\">40</option>\n";
+6 -5
View File
@@ -33,7 +33,7 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
// pass in button object, get back html
var html = '';
html += "<button type=\"button\" " + this.attr(btn, 'ngClick') + "class=\"btn";
html += (btn['class']) ? " " + btn['class'] : " btn-small";
html += (btn['class']) ? " " + btn['class'] : " btn-sm";
html += (btn['awPopOver']) ? " help-link-white" : "";
html += "\" ";
html += (btn.id) ? "id=\"" + btn.id + "\" " : "";
@@ -96,6 +96,7 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
if (options.mode == 'lookup') {
// options should include {hdr: <dialog header>, action: <function...> }
this.scope.formModalActionDisabled = false;
this.scope.lookupHeader = options.hdr;
$('#lookup-modal').modal({ backdrop: 'static', keyboard: true });
$(document).bind('keydown', function(e) {
@@ -143,17 +144,17 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
}
if (options.mode == 'lookup' || options.id != undefined) {
html += SearchWidget({ iterator: list.iterator, template: list, mini: true , size: 'col-lg-6' });
html += SearchWidget({ iterator: list.iterator, template: list, mini: true , size: 'col-lg-8' });
}
else {
html += SearchWidget({ iterator: list.iterator, template: list, mini: false });
html += SearchWidget({ iterator: list.iterator, template: list, mini: true });
}
if (options.mode != 'lookup') {
//actions
var base = $location.path().replace(/^\//,'').split('/')[0];
html += "<div class=\"";
html += (options.id != undefined) ? "col-lg-5" : "col-lg-7";
html += (options.id != undefined) ? "col-lg-3" : "col-lg-7";
html += "\">\n";
for (action in list.actions) {
if (list.actions[action].mode == 'all' || list.actions[action].mode == options.mode) {
@@ -170,7 +171,7 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
dataPlacement: 'left',
dataContainer: 'body',
icon: "icon-question-sign",
'class': 'btn-mini btn-help btn-info',
'class': 'btn-sm btn-help btn-info',
awToolTip: 'Click for help',
dataTitle: 'Help',
iconSize: 'large'
+2 -3
View File
@@ -222,7 +222,6 @@ angular.module('Utilities',[])
var spinnyh = $('.spinny').height();
var x = (docw - spinnyw) / 2;
var y = (doch - spinnyh) / 2;
console.log($(document));
$('.overlay').css({
width: $('html').width(),
height: $(document).height() + 200
@@ -230,10 +229,10 @@ angular.module('Utilities',[])
$('.spinny').css({
top: y,
left: x
}).fadeIn(500);
}).fadeIn(400);
}
else {
$('.spinny, .overlay').fadeOut(2000);
$('.spinny, .overlay').fadeOut(1000);
}
}
}]);
+93 -60
View File
@@ -49,7 +49,7 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
// http://blog.alexmaccaw.com/css-transitions
$.fn.emulateTransitionEnd = function (duration) {
var called = false, $el = this
var called = false, $el = this
$(this).one($.support.transition.end, function () { called = true })
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
setTimeout(callback, duration)
@@ -219,7 +219,9 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
var $parent = this.$element.closest('[data-toggle="buttons"]')
if ($parent.length) {
var $input = this.$element.find('input').prop('checked', !this.$element.hasClass('active'))
var $input = this.$element.find('input')
.prop('checked', !this.$element.hasClass('active'))
.trigger('change')
if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active')
}
@@ -235,7 +237,7 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
$.fn.button = function (option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('button')
var data = $this.data('bs.button')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.button', (data = new Button(this, options)))
@@ -312,6 +314,7 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
Carousel.DEFAULTS = {
interval: 5000
, pause: 'hover'
, wrap: true
}
Carousel.prototype.cycle = function (e) {
@@ -376,12 +379,15 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
var fallback = type == 'next' ? 'first' : 'last'
var that = this
if (!$next.length) {
if (!this.options.wrap) return
$next = this.$element.find('.item')[fallback]()
}
this.sliding = true
isCycling && this.pause()
$next = $next.length ? $next : this.$element.find('.item')[fallback]()
var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })
if ($next.hasClass('active')) return
@@ -533,7 +539,7 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
var actives = this.$parent && this.$parent.find('> .accordion-group > .in')
var actives = this.$parent && this.$parent.find('> .panel > .in')
if (actives && actives.length) {
var hasData = actives.data('bs.collapse')
@@ -654,7 +660,7 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
var $parent = parent && $(parent)
if (!data || !data.transitioning) {
if ($parent) $parent.find('[data-toggle=collapse][data-parent=' + parent + ']').not($this).addClass('collapsed')
if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed')
$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
}
@@ -705,7 +711,7 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
clearMenus()
if (!isActive) {
if ('ontouchstart' in document.documentElement) {
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
// if mobile we we use a backdrop because click events don't delegate
$('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
}
@@ -717,9 +723,9 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
$parent
.toggleClass('open')
.trigger('shown.bs.dropdown')
}
$this.focus()
$this.focus()
}
return false
}
@@ -845,11 +851,11 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
var Modal = function (element, options) {
this.options = options
this.$element = $(element).on('click.dismiss.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
this.$element = $(element)
this.$backdrop =
this.isShown = null
if (this.options.remote) this.$element.find('.modal-body').load(this.options.remote)
if (this.options.remote) this.$element.load(this.options.remote)
}
Modal.DEFAULTS = {
@@ -858,13 +864,13 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
, show: true
}
Modal.prototype.toggle = function () {
return this[!this.isShown ? 'show' : 'hide']()
Modal.prototype.toggle = function (_relatedTarget) {
return this[!this.isShown ? 'show' : 'hide'](_relatedTarget)
}
Modal.prototype.show = function () {
Modal.prototype.show = function (_relatedTarget) {
var that = this
var e = $.Event('show.bs.modal')
var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
this.$element.trigger(e)
@@ -874,6 +880,8 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
this.escape()
this.$element.on('click.dismiss.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
this.backdrop(function () {
var transition = $.support.transition && that.$element.hasClass('fade')
@@ -893,13 +901,15 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
that.enforceFocus()
var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
transition ?
that.$element
that.$element.find('.modal-dialog') // wait for modal to slide in
.one($.support.transition.end, function () {
that.$element.focus().trigger('shown.bs.modal')
that.$element.focus().trigger(e)
})
.emulateTransitionEnd(300) :
that.$element.focus().trigger('shown.bs.modal')
that.$element.focus().trigger(e)
})
}
@@ -921,6 +931,7 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
this.$element
.removeClass('in')
.attr('aria-hidden', true)
.off('click.dismiss.modal')
$.support.transition && this.$element.hasClass('fade') ?
this.$element
@@ -973,7 +984,7 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
.appendTo(document.body)
this.$element.on('click', $.proxy(function (e) {
this.$element.on('click.dismiss.modal', $.proxy(function (e) {
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus.call(this.$element[0])
@@ -1012,15 +1023,15 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
var old = $.fn.modal
$.fn.modal = function (option) {
$.fn.modal = function (option, _relatedTarget) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.modal')
var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
if (typeof option == 'string') data[option]()
else if (options.show) data.show()
if (typeof option == 'string') data[option](_relatedTarget)
else if (options.show) data.show(_relatedTarget)
})
}
@@ -1043,28 +1054,26 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
var $this = $(this)
var href = $this.attr('href')
var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
var option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
var option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
e.preventDefault()
$target
.modal(option)
.modal(option, this)
.one('hide', function () {
$this.is(':visible') && $this.focus()
})
})
$(function () {
var $body = $(document.body)
.on('shown.bs.modal', '.modal', function () { $body.addClass('modal-open') })
.on('hidden.bs.modal', '.modal', function () { $body.removeClass('modal-open') })
})
$(document)
.on('show.bs.modal', '.modal', function () { $(document.body).addClass('modal-open') })
.on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })
}(window.jQuery);
/* ========================================================================
* Bootstrap: tooltip.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#affix
* http://twbs.github.com/bootstrap/javascript.html#tooltip
* Inspired by the original jQuery.tipsy by Jason Frame
* ========================================================================
* Copyright 2012 Twitter, Inc.
@@ -1128,7 +1137,7 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
var eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
}
}
@@ -1155,37 +1164,43 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
return options
}
Tooltip.prototype.enter = function (obj) {
var defaults = this.getDefaults()
Tooltip.prototype.getDelegateOptions = function () {
var options = {}
var defaults = this.getDefaults()
this._options && $.each(this._options, function (key, value) {
if (defaults[key] != value) options[key] = value
})
return options
}
Tooltip.prototype.enter = function (obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget)[this.type](options).data('bs.' + this.type)
obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
clearTimeout(self.timeout)
self.hoverState = 'in'
if (!self.options.delay || !self.options.delay.show) return self.show()
self.hoverState = 'in'
self.timeout = setTimeout(function () {
self.timeout = setTimeout(function () {
if (self.hoverState == 'in') self.show()
}, self.options.delay.show)
}
Tooltip.prototype.leave = function (obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget)[this.type](this._options).data('bs.' + this.type)
obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
clearTimeout(self.timeout)
self.hoverState = 'out'
if (!self.options.delay || !self.options.delay.hide) return self.hide()
self.hoverState = 'out'
self.timeout = setTimeout(function () {
self.timeout = setTimeout(function () {
if (self.hoverState == 'out') self.hide()
}, self.options.delay.hide)
}
@@ -1243,12 +1258,9 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
.addClass(placement)
}
var tp = placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
this.applyPlacement(tp, placement)
this.applyPlacement(calculatedOffset, placement)
this.$element.trigger('shown.bs.' + this.type)
}
}
@@ -1260,25 +1272,33 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
var height = $tip[0].offsetHeight
// manually read margins because getBoundingClientRect includes difference
offset.top = offset.top + parseInt($tip.css('margin-top'), 10)
offset.left = offset.left + parseInt($tip.css('margin-left'), 10)
var marginTop = parseInt($tip.css('margin-top'), 10)
var marginLeft = parseInt($tip.css('margin-left'), 10)
// we must check for NaN for ie 8/9
if (isNaN(marginTop)) marginTop = 0
if (isNaN(marginLeft)) marginLeft = 0
offset.top = offset.top + marginTop
offset.left = offset.left + marginLeft
$tip
.offset(offset)
.addClass('in')
// check to see if placing tip in new offset caused the tip to resize itself
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (placement == 'top' && actualHeight != height) {
replace = true
offset.top = offset.top + height - actualHeight
offset.top = offset.top + height - actualHeight
}
if (placement == 'bottom' || placement == 'top') {
if (/bottom|top/.test(placement)) {
var delta = 0
if (offset.left < 0){
if (offset.left < 0) {
delta = offset.left * -2
offset.left = 0
@@ -1313,6 +1333,10 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
var $tip = this.tip()
var e = $.Event('hide.bs.' + this.type)
function complete() {
if (that.hoverState != 'in') $tip.detach()
}
this.$element.trigger(e)
if (e.isDefaultPrevented()) return
@@ -1321,9 +1345,9 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
$.support.transition && this.$tip.hasClass('fade') ?
$tip
.one($.support.transition.end, $tip.detach)
.one($.support.transition.end, complete)
.emulateTransitionEnd(150) :
$tip.detach()
complete()
this.$element.trigger('hidden.bs.' + this.type)
@@ -1349,6 +1373,13 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
}, this.$element.offset())
}
Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
}
Tooltip.prototype.getTitle = function () {
var title
var $e = this.$element
@@ -1364,8 +1395,8 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
return this.$tip = this.$tip || $(this.options.template)
}
Tooltip.prototype.arrow =function(){
return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
Tooltip.prototype.arrow = function () {
return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
}
Tooltip.prototype.validate = function () {
@@ -1389,7 +1420,7 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
}
Tooltip.prototype.toggle = function (e) {
var self = e ? $(e.currentTarget)[this.type](this._options).data('bs.' + this.type) : this
var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
}
@@ -1487,7 +1518,9 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
$tip.removeClass('fade top bottom left right in')
$tip.find('.popover-title:empty').hide()
// IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
// this manually by checking the contents.
if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
}
Popover.prototype.hasContent = function () {
@@ -1504,15 +1537,15 @@ if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
o.content)
}
Popover.prototype.arrow = function () {
return this.$arrow = this.$arrow || this.tip().find('.arrow')
}
Popover.prototype.tip = function () {
if (!this.$tip) this.$tip = $(this.options.template)
return this.$tip
}
Popover.prototype.destroy = function () {
this.hide().$element.off('.' + this.type).removeData(this.type)
}
// POPOVER PLUGIN DEFINITION
// =========================
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -62,6 +62,7 @@
<script src="{{ STATIC_URL }}js/forms/Permissions.js"></script>
<script src="{{ STATIC_URL }}js/forms/JobEventData.js"></script>
<script src="{{ STATIC_URL }}js/forms/License.js"></script>
<script src="{{ STATIC_URL }}js/forms/HostGroups.js"></script>
<script src="{{ STATIC_URL }}js/lists/Users.js"></script>
<script src="{{ STATIC_URL }}js/lists/Organizations.js"></script>
<script src="{{ STATIC_URL }}js/lists/Admins.js"></script>
@@ -220,7 +221,7 @@
<button ng-show="formModalInfo !== undefined && formModalInfo != ''" ng-click="formModalInfoAction()"
class="btn btn-mini pull-left"><i class="icon-zoom-in"></i> <span ng-bind="formModalInfo"></span></button>
<a href="#" ng-show="formModalCancelShow" data-target="#form-modal" data-dismiss="modal" class="btn btn-default">Cancel</a>
<a href="" ng-bind="formModalActionLabel" ng-click="formModalAction()" class="btn btn-primary"></a>
<a href="" ng-bind="formModalActionLabel" ng-click="formModalAction()" ng-disabled="formModalActionDisabled" class="btn btn-primary"></a>
</div>
</div><!-- modal-content -->
</div><!-- modal-dialog -->