Upgraded AWX to Twitter Bootstrap 3 RC1

This commit is contained in:
chouseknecht
2013-08-02 18:26:34 -04:00
parent f3cbda4352
commit 94ae9ffd43
40 changed files with 5172 additions and 7977 deletions

View File

@@ -13,7 +13,7 @@
body { body {
color: #171717; color: #171717;
padding-top: 60px; padding-top: 100px;
} }
.text-center { .text-center {
@@ -28,9 +28,18 @@
white-space: nowrap; white-space: nowrap;
} }
.tab-content {
padding-top: 20px;
}
.btn .caret {
border-top-color: #787878;
}
/* Attempt to make button heights consistent. For some reason success, info, etc. are /* Attempt to make button heights consistent. For some reason success, info, etc. are
taller than plain .btn */ taller than plain .btn */
/*
.btn-success, .btn-danger, .btn-info, .btn-primary, .btn-warning { .btn-success, .btn-danger, .btn-info, .btn-primary, .btn-warning {
padding-top: 1px; padding-top: 1px;
padding-bottom: 2px; padding-bottom: 2px;
@@ -46,7 +55,9 @@
padding-top: 3px; padding-top: 3px;
padding-bottom: 1px; padding-bottom: 1px;
} }
*/
/*
.btn-inventory-edit { .btn-inventory-edit {
padding-top: 2px; padding-top: 2px;
padding-bottom: 1px; padding-bottom: 1px;
@@ -64,10 +75,7 @@
padding-left: 10px; padding-left: 10px;
padding-right: 10px; padding-right: 10px;
} }
*/
.icon-plus {
font-size: 10px;
}
/* End btn heights */ /* End btn heights */
@@ -93,18 +101,16 @@
min-height: 15px; min-height: 15px;
} }
.container-fluid { .main-container {
min-height: 700px; min-height: 700px;
} }
.navbar-fixed-top .container { .navbar {
width: 100%; background-color: #171717;
} }
.navbar-inverse .navbar-inner { .navbar .nav {
background-color: #171717; margin-top: 15px;
border-color: #171717;
padding-right: 15px;
} }
.navbar-inverse .nav > li > a { .navbar-inverse .nav > li > a {
@@ -116,25 +122,30 @@
color: #2078be; color: #2078be;
} }
.navbar .brand { /* Using inline-block rather than block keeps
margin-left: 15px; brand img from right aligning into the collapse button
on mobile screens */
.navbar-brand {
display: inline-block;
padding: 0; padding: 0;
} }
.navbar .brand img { .navbar-brand img {
width: 260px; max-width: 260px;
} }
ß
.navbar .nav {
margin-top: 15px;
}
a:hover { a:hover {
text-decoration: none; text-decoration: none;
} }
.help-link, .help-link:active, .help-link:visited { .help-link, .help-link:active, .help-link:visited {
color: #49afcd; color: #49afcd;
text-decoration: none;
}
.help-link:hover {
text-decoration: none;
color: #1778c3;
} }
.site-footer { .site-footer {
@@ -185,7 +196,25 @@
max-width: 100px; max-width: 100px;
} }
/* Outline required fields in Red when focused */
.form-control[required]:focus {
border-color: rgba(204, 0, 0, 0.8);
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px rgba(204, 0, 0, 0.6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 5px rgba(204, 0, 0, 0.6);
}
/* For some reason TB 3 RC1 does not provide an input-mini */
.input-mini {
height: 26px;
padding: 3px 8px;
font-size: 12px;
border-radius: 3px;
}
.error { .error {
margin-top: 5px;
line-height: normal;
font-size: 12px; font-size: 12px;
color: #FF0000; color: #FF0000;
} }
@@ -339,6 +368,7 @@
display: inline-block; display: inline-block;
vertical-align: bottom; vertical-align: bottom;
margin-bottom: 15px; margin-bottom: 15px;
padding-left: 0;
} }
.list-actions { .list-actions {
@@ -450,6 +480,7 @@
margin-top:5px; margin-top:5px;
} }
.form-items .search-widget { .form-items .search-widget {
margin-top: 15px; margin-top: 15px;
} }
@@ -553,17 +584,18 @@
} }
.parse-selection { .parse-selection {
display: inline-block;
font-size: 12px; font-size: 12px;
line-height: normal;
margin: 5px 0 8px 0; margin: 5px 0 8px 0;
} }
.parse-selection .radio.inline { .parse-selection input {
padding-top: 0; margin-left: 5px;
font-size: 12px;
} }
.parse-selection label:first-child { .parse-select .parse-label {
margin-left: 5px; margin-left: 3px;
} }
#tree-view { #tree-view {
@@ -621,34 +653,6 @@
padding-bottom: 5px; padding-bottom: 5px;
} }
/* form displayed in modal window */
.horizontal-narrow .control-label {
float: left;
width: 100px;
padding-top: 5px;
text-align: right;
}
.horizontal-narrow .controls {
*display: inline-block;
*padding-left: 20px;
margin-left: 120px;
*margin-left: 0;
}
.horizontal-narrow .controls:first-child {
*padding-left: 120px;
}
.modal-input-xlarge {
width: 350px;
}
.modal-input-xxlarge {
width: 98%;
}
.form-section-title { .form-section-title {
font-weight: bold; font-weight: bold;
width: 100%; width: 100%;
@@ -723,23 +727,16 @@
/* Portrait tablet to landscape and desktop */ /* Portrait tablet to landscape and desktop */
@media (min-width: 768px) and (max-width: 979px) { @media (min-width: 768px) and (max-width: 979px) {
body {
padding-top: 0px;
}
} }
/* Landscape phone to portrait tablet */ /* Landscape phone to portrait tablet */
@media (max-width: 767px) { @media (max-width: 767px) {
body {
padding-top: 0px;
}
} }
/* Landscape phones and down */ /* Landscape phones and down */
@media (max-width: 480px) { @media (max-width: 480px) {
body {
padding-top: 0px;
}
/* Job events */ /* Job events */
.level-1, .level-2, .level-3, .level-3-detail { .level-1, .level-2, .level-3, .level-3-detail {
@@ -750,21 +747,4 @@
table-layout: fixed; table-layout: fixed;
word-wrap: break-word; word-wrap: break-word;
} }
/* form displayed in modal window */
.horizontal-narrow .control-label {
width: 105px;
}
.horizontal-narrow .controls {
margin-left: 125px;
}
.horizontal-narrow .controls:first-child {
*padding-left: 125px;
}
.modal-input-xlarge {
width: 200px;
}
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -210,9 +210,9 @@ angular.module('ansible', [
when('/teams/:user_id/credentials/:credential_id', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/:user_id/credentials/:credential_id', { templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsEdit }). controller: CredentialsEdit }).
when('/login', { templateUrl: urlPrefix + 'partials/login-dialog.html', controller: Authenticate }). when('/login', { templateUrl: urlPrefix + 'partials/organizations.html', controller: Authenticate }).
when('/logout', { templateUrl: urlPrefix + 'partials/login-dialog.html', controller: Authenticate }). when('/logout', { templateUrl: urlPrefix + 'partials/organizations.html', controller: Authenticate }).
otherwise({redirectTo: '/'}); otherwise({redirectTo: '/'});
}]) }])

View File

@@ -12,22 +12,30 @@
function Authenticate($window, $scope, $rootScope, $location, Authorization, ToggleClass, Alert) function Authenticate($window, $scope, $rootScope, $location, Authorization, ToggleClass, Alert)
{ {
// Authorization is injected from AuthService found in services.js // Display the login dialog
$('#login-modal').modal({ show: true, keyboard: false, backdrop: 'static' });
var scope = angular.element(document.getElementById('login-modal')).scope();
// Reset the login form
scope['login_username'] = null;
scope['login_password'] = null;
scope['loginForm']['login_username'].$setPristine();
scope['loginForm']['login_password'].$setPristine();
if ($location.path() == '/logout') { if ($location.path() == '/logout') {
//if logout request, clear AuthToken and user session data //if logout request, clear AuthToken and user session data
Authorization.logout(); Authorization.logout();
} }
$scope.sessionTimeout = ($AnsibleConfig.session_timeout / 60).toFixed(2); scope.sessionTimeout = ($AnsibleConfig.session_timeout / 60).toFixed(2);
$scope.AWXLoginLogo = $staticURL + 'img/AWX_logo.png';
if ($rootScope.userLoggedIn) { if ($rootScope.userLoggedIn) {
// If we're logged in, check for session timeout // If we're logged in, check for session timeout
$scope.sessionExpired = Authorization.didSessionExpire(); scope.sessionExpired = Authorization.didSessionExpire();
} }
else { else {
$scope.sessionExpired = false; scope.sessionExpired = false;
} }
$rootScope.userLoggedIn = false; //hide the logout link. if you got here, you're logged out. $rootScope.userLoggedIn = false; //hide the logout link. if you got here, you're logged out.
@@ -40,70 +48,73 @@ function Authenticate($window, $scope, $rootScope, $location, Authorization, Tog
} }
}); });
// Display the login dialog scope.reset = function() {
$('#login-modal').modal({ show: true, keyboard: false, backdrop: 'static' });
$scope.reset = function() {
$('#login-form input').each( function(index) { $(this).val(''); }); $('#login-form input').each( function(index) { $(this).val(''); });
}; };
// Call the API to get an auth token // Call the API to get an auth token
$scope.systemLogin = function(username, password) { scope.systemLogin = function(username, password) {
$('.api-error').empty(); $('.api-error').empty();
var token; var token;
Authorization.retrieveToken(username, password) if (username == null || username == undefined || username == '' ||
.success( function(data, status, headers, config) { password == null || password == undefined || password == '' ) {
$('#login-modal').modal('hide'); Alert('Error!', 'Please provide a username and password before attempting to login.');
token = data.token; }
Authorization.setToken(data.token); else {
$scope.reset(); Authorization.retrieveToken(username, password)
.success( function(data, status, headers, config) {
$('#login-modal').modal('hide');
token = data.token;
Authorization.setToken(data.token);
scope.reset();
// Force request to /organizations to query with the correct token -in the event a new user // Force request to /organizations to query with the correct token -in the event a new user
// has logged in. // has logged in.
var today = new Date(); var today = new Date();
today.setTime(today.getTime() + ($AnsibleConfig.session_timeout * 1000)); today.setTime(today.getTime() + ($AnsibleConfig.session_timeout * 1000));
$rootScope.token = token; $rootScope.token = token;
$rootScope.userLoggedIn = true; $rootScope.userLoggedIn = true;
$rootScope.token_expire = today.getTime(); $rootScope.token_expire = today.getTime();
// Get all the profile/access info regarding the logged in user // Get all the profile/access info regarding the logged in user
Authorization.getUser() Authorization.getUser()
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
Authorization.setUserInfo(data); Authorization.setUserInfo(data);
Authorization.getLicense() Authorization.getLicense()
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
Authorization.setLicense(data['license_info']); Authorization.setLicense(data['license_info']);
$location.path('/organizations'); $location.path('/organizations');
}) })
.error(function(data, status, headers, config) { .error(function(data, status, headers, config) {
Alert('Error', 'Failed to access user information. GET returned status: ' + status); Alert('Error', 'Failed to access user information. GET returned status: ' + status);
}); });
}) })
.error( function(data, status, headers, config) { .error( function(data, status, headers, config) {
Alert('Error', 'Failed to access license information. GET returned status: ' + status); Alert('Error', 'Failed to access license information. GET returned status: ' + status);
}); });
}) })
.error( function(data, status, headers, config) { .error( function(data, status, headers, config) {
if ( data.non_field_errors && data.non_field_errors.length == 0 ) { if ( data.non_field_errors && data.non_field_errors.length == 0 ) {
// show field specific errors returned by the API // show field specific errors returned by the API
for (var key in data) { for (var key in data) {
$scope[key + 'Error'] = data[key][0]; scope[key + 'Error'] = data[key][0];
} }
} }
else { else {
var hdr, msg; var hdr, msg;
if ( data.non_field_errors && data.non_field_errors.length > 0 ) { if ( data.non_field_errors && data.non_field_errors.length > 0 ) {
hdr = 'Error'; hdr = 'Error';
msg = data.non_field_errors[0]; msg = data.non_field_errors[0];
} }
else { else {
hdr = 'Error'; hdr = 'Error';
msg = 'The login attempt failed with a status of: ' + status; msg = 'The login attempt failed with a status of: ' + status;
} }
$scope.reset(); scope.reset();
Alert(hdr, msg); Alert(hdr, msg);
} }
}); });
}
} }
} }

View File

@@ -43,13 +43,16 @@ function JobEventsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
rows = (n) ? n.length : 1; rows = (n) ? n.length : 1;
rows = (rows > 10) ? 10 : rows; rows = (rows > 10) ? 10 : rows;
found = true; found = true;
html += "<div class=\"form-group\">\n";
html += "<label>Traceback:</label>\n"; html += "<label>Traceback:</label>\n";
html += "<textarea readonly class=\"input-xxlarge nowrap\" rows=\"" + rows + "\">" + eventData.res + "</textarea>\n"; html += "<textarea readonly class=\"form-control nowrap\" rows=\"" + rows + "\">" + eventData.res + "</textarea>\n";
html += "</div>\n";
} }
else { else {
for (var fld in eventData.res) { for (var fld in eventData.res) {
if ( (fld == 'msg' || fld == 'stdout' || fld == 'stderr') && if ( (fld == 'msg' || fld == 'stdout' || fld == 'stderr') &&
(eventData.res[fld] !== null && eventData.res[fld] !== '') ) { (eventData.res[fld] !== null && eventData.res[fld] !== '') ) {
html += "<div class=\"form-group\">\n";
html += "<label>"; html += "<label>";
switch(fld) { switch(fld) {
case 'msg': case 'msg':
@@ -64,7 +67,8 @@ function JobEventsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
n = eventData['res'][fld].match(/\n/g); n = eventData['res'][fld].match(/\n/g);
rows = (n) ? n.length : 1; rows = (n) ? n.length : 1;
rows = (rows > 10) ? 10 : rows; rows = (rows > 10) ? 10 : rows;
html += "<textarea readonly class=\"input-xxlarge nowrap\" rows=\"" + rows + "\">" + eventData.res[fld] + "</textarea>\n"; html += "<textarea readonly class=\"form-control nowrap\" rows=\"" + rows + "\">" + eventData.res[fld] + "</textarea>\n";
html += "</div>\n";
found = true; found = true;
} }
if ( fld == "results" && Array.isArray(eventData.res[fld]) && eventData.res[fld].length > 0 ) { if ( fld == "results" && Array.isArray(eventData.res[fld]) && eventData.res[fld].length > 0 ) {
@@ -77,14 +81,18 @@ function JobEventsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
rows = (n) ? n.length : 1; rows = (n) ? n.length : 1;
rows = (rows > 10) ? 10 : rows; rows = (rows > 10) ? 10 : rows;
if (txt !== '') { if (txt !== '') {
html += "<div class=\"form-group\">\n";
html += "<label>Results:</label>\n"; html += "<label>Results:</label>\n";
html += "<textarea readonly class=\"input-xxlarge nowrap\" rows=\"" + rows + "\">" + txt + "</textarea>\n"; html += "<textarea readonly class=\"form-control nowrap\" rows=\"" + rows + "\">" + txt + "</textarea>\n";
html += "</div>\n";
found = true; found = true;
} }
} }
if (fld == "rc" && eventData.res[fld] != '') { if (fld == "rc" && eventData.res[fld] != '') {
html += "<div class=\"form-group\">\n";
html += "<label>Return Code:</label>\n"; html += "<label>Return Code:</label>\n";
html += "<input type=\"text\" class=\"input-mini\" value=\"" + eventData.res[fld] + "\" readonly >\n"; html += "<input type=\"text\" class=\"form-control\" value=\"" + eventData.res[fld] + "\" readonly >\n";
html += "</div>\n";
found = true; found = true;
} }
} }
@@ -92,7 +100,7 @@ function JobEventsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
html = (found) ? "<form class=\"event-form\">\n" + html + "</form>\n" : ''; html = (found) ? "<form class=\"event-form\">\n" + html + "</form>\n" : '';
} }
if (eventData['host']) { if (eventData['host']) {
html = "<span class=\"event-detail-host visible-phone visible-tablet\">" + eventData['host'] + "</span>\n" + html; html = "<span class=\"event-detail-host visible-sm\">" + eventData['host'] + "</span>\n" + html;
} }
else { else {
html = (html == '' ) ? null : html; html = (html == '' ) ? null : html;

View File

@@ -14,7 +14,8 @@ angular.module('GroupFormDefinition', [])
editTitle: '{{ name }}', //Legend in edit mode editTitle: '{{ name }}', //Legend in edit mode
name: 'group', //Form name attribute name: 'group', //Form name attribute
well: false, //Wrap the form with TB well well: false, //Wrap the form with TB well
"class": 'horizontal-narrow', formLabelSize: 'col-lg-3',
formFieldSize: 'col-lg-9',
fields: { fields: {
name: { name: {

View File

@@ -13,8 +13,9 @@ angular.module('HostFormDefinition', [])
addTitle: 'Create Host', //Legend in add mode addTitle: 'Create Host', //Legend in add mode
editTitle: '{{ name }}', //Legend in edit mode editTitle: '{{ name }}', //Legend in edit mode
name: 'host', //Form name attribute name: 'host', //Form name attribute
"class": 'horizontal-narrow',
well: false, //Wrap the form with TB well well: false, //Wrap the form with TB well
formLabelSize: 'col-lg-3',
formFieldSize: 'col-lg-9',
fields: { fields: {
name: { name: {

View File

@@ -113,7 +113,7 @@ angular.module('InventoryFormDefinition', [])
select: { select: {
ngClick: "selectHost()", ngClick: "selectHost()",
icon: 'icon-check', icon: 'icon-check',
label: 'Add Existing Host', label: 'Add Existing',
awToolTip: 'Select existing host', awToolTip: 'Select existing host',
ngHide: 'createButtonShow == false', ngHide: 'createButtonShow == false',
"class": 'btn btn-pad' "class": 'btn btn-pad'
@@ -121,7 +121,7 @@ angular.module('InventoryFormDefinition', [])
create: { create: {
ngClick: "createHost()", ngClick: "createHost()",
icon: 'icon-plus', icon: 'icon-plus',
label: 'Create New Host', label: 'Create New',
awToolTip: 'Create a new host', awToolTip: 'Create a new host',
ngHide: 'createButtonShow == false', ngHide: 'createButtonShow == false',
"class": 'btn-success' "class": 'btn-success'

View File

@@ -43,7 +43,8 @@ angular.module('JobTemplateFormDefinition', [])
" on the selected hosts.</p> <p>Setting the type to <em>check</em> will not execute the playbook. Instead, ansible will check playbook " + " on the selected hosts.</p> <p>Setting the type to <em>check</em> will not execute the playbook. Instead, ansible will check playbook " +
" syntax, test environment setup and report problems.</p>", " syntax, test environment setup and report problems.</p>",
dataTitle: 'Job Type', dataTitle: 'Job Type',
dataPlacement: 'right' dataPlacement: 'right',
dataContainer: "body"
}, },
inventory: { inventory: {
label: 'Inventory', label: 'Inventory',
@@ -100,7 +101,8 @@ angular.module('JobTemplateFormDefinition', [])
awPopOver: "<p>The number of parallel or simultaneous processes to use while executing the playbook. Provide a value between 0 and 100. " + awPopOver: "<p>The number of parallel or simultaneous processes to use while executing the playbook. Provide a value between 0 and 100. " +
"A value of zero will use the ansible default setting of 5 parallel processes.</p>", "A value of zero will use the ansible default setting of 5 parallel processes.</p>",
dataTitle: 'Forks', dataTitle: 'Forks',
dataPlacement: 'right' dataPlacement: 'right',
dataContainer: "body"
}, },
limit: { limit: {
label: 'Limit', label: 'Limit',
@@ -113,7 +115,8 @@ angular.module('JobTemplateFormDefinition', [])
"<a href=\"http://ansible.cc/docs/patterns.html#selecting-targets\" target=\"_blank\">Selecting Targets section</a> under Inventory and Patterns " + "<a href=\"http://ansible.cc/docs/patterns.html#selecting-targets\" target=\"_blank\">Selecting Targets section</a> under Inventory and Patterns " +
" in the Ansible documentation.</p>", " in the Ansible documentation.</p>",
dataTitle: 'Limit', dataTitle: 'Limit',
dataPlacement: 'right' dataPlacement: 'right',
dataContainer: "body"
}, },
verbosity: { verbosity: {
label: 'Verbosity', label: 'Verbosity',
@@ -125,7 +128,8 @@ angular.module('JobTemplateFormDefinition', [])
column: 1, column: 1,
awPopOver: "<p>Control the level of output ansible will produce as the playbook executes.</p>", awPopOver: "<p>Control the level of output ansible will produce as the playbook executes.</p>",
dataTitle: 'Verbosity', dataTitle: 'Verbosity',
dataPlacement: 'right' dataPlacement: 'right',
dataContainer: "body"
}, },
variables: { variables: {
label: 'Extra Variables', label: 'Extra Variables',
@@ -143,7 +147,8 @@ angular.module('JobTemplateFormDefinition', [])
"YAML:<br />\n" + "YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n", "<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n",
dataTitle: 'Extra Variables', dataTitle: 'Extra Variables',
dataPlacement: 'left' dataPlacement: 'left',
dataContainer: "body"
}, },
job_tags: { job_tags: {
label: 'Job Tags', label: 'Job Tags',
@@ -161,7 +166,8 @@ angular.module('JobTemplateFormDefinition', [])
"in the Job Tags field:<\p>\n" + "in the Job Tags field:<\p>\n" +
"<blockquote>configuration,packages</blockquote>\n", "<blockquote>configuration,packages</blockquote>\n",
dataTitle: "Job Tags", dataTitle: "Job Tags",
dataPlacement: "left" dataPlacement: "left",
dataContainer: "body"
}, },
allow_callbacks: { allow_callbacks: {
label: 'Allow Callbacks', label: 'Allow Callbacks',
@@ -182,8 +188,8 @@ angular.module('JobTemplateFormDefinition', [])
"in one of your defined inventories, the request will be denied.</p>" + "in one of your defined inventories, the request will be denied.</p>" +
"<p>Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.</p>", "<p>Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.</p>",
detailPlacement: 'left', detailPlacement: 'left',
dataContainer: '#job_templates', dataTitle: 'Callback URL',
dataTitle: 'Callback URL' dataContainer: "body"
}, },
callback_url: { callback_url: {
label: 'Callback URL', label: 'Callback URL',
@@ -202,8 +208,8 @@ angular.module('JobTemplateFormDefinition', [])
"in one of your defined inventories, the request will be denied.</p>" + "in one of your defined inventories, the request will be denied.</p>" +
"<p>Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.</p>", "<p>Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.</p>",
detailPlacement: 'left', detailPlacement: 'left',
dataContainer: '#job_templates', dataTitle: 'Callback URL',
dataTitle: 'Callback URL' dataContainer: "body"
}, },
host_config_key: { host_config_key: {
label: 'Host Config Key', label: 'Host Config Key',
@@ -216,7 +222,7 @@ angular.module('JobTemplateFormDefinition', [])
"<p class=\"code-breakable\">curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " + "<p class=\"code-breakable\">curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
"http://your.server.com:999/api/v1/job_templates/1/callback/</p>\n", "http://your.server.com:999/api/v1/job_templates/1/callback/</p>\n",
detailPlacement: 'left', detailPlacement: 'left',
dataContainer: '#job_templates' dataContainer: "body"
} }
}, },

View File

@@ -253,16 +253,18 @@ angular.module('JobFormDefinition', [])
label: 'Standard Out', label: 'Standard Out',
type: 'textarea', type: 'textarea',
readonly: true, readonly: true,
xtraWide: true,
rows: "\{\{ stdout_rows \}\}", rows: "\{\{ stdout_rows \}\}",
"class": 'span12 nowrap', "class": 'nowrap',
ngShow: "result_stdout != ''" ngShow: "result_stdout != ''"
}, },
result_traceback: { result_traceback: {
label: 'Traceback', label: 'Traceback',
type: 'textarea', type: 'textarea',
xtraWide: true,
readonly: true, readonly: true,
rows: "\{\{ traceback_rows \}\}", rows: "\{\{ traceback_rows \}\}",
"class": 'span12 nowrap', "class": 'nowrap',
ngShow: "result_traceback != ''" ngShow: "result_traceback != ''"
} }
}, },
@@ -292,10 +294,6 @@ angular.module('JobFormDefinition', [])
awToolTip: 'Edit job events', awToolTip: 'Edit job events',
mode: 'all' mode: 'all'
} }
},
related: { //related colletions (and maybe items?)
} }
}); //Form }); //Form

View File

@@ -56,7 +56,7 @@ angular.module('AccessHelper', ['RestServices', 'Utilities', 'ngCookies'])
$rootScope.license_tested = true; $rootScope.license_tested = true;
if (license['valid_key'] !== undefined && license['valid_key'] == false) { if (license['valid_key'] !== undefined && license['valid_key'] == false) {
// The license is invalid. Stop the user from logging in. // The license is invalid. Stop the user from logging in.
status = 'alert-error'; status = 'alert-danger';
hdr = 'License Error'; hdr = 'License Error';
msg = 'Something is wrong with your /etc/awx/license file on this server. ' + msg = 'Something is wrong with your /etc/awx/license file on this server. ' +
'Please contact <a href="mailto:info@ansibleworks.com">info@ansibleworks.com</a> for assistance.'; 'Please contact <a href="mailto:info@ansibleworks.com">info@ansibleworks.com</a> for assistance.';

View File

@@ -24,7 +24,6 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
name: 'job_events', name: 'job_events',
well: false, well: false,
forceListeners: true, forceListeners: true,
'class': 'horizontal-narrow',
fields: { fields: {
status: { status: {
labelClass: 'job-\{\{ status \}\}', labelClass: 'job-\{\{ status \}\}',
@@ -76,37 +75,38 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
ngShow: "rc !== ''" ngShow: "rc !== ''"
}, },
msg: { msg: {
label: false, label: 'Msg',
type: 'textarea', type: 'textarea',
readonly: true, readonly: true,
section: 'Results', section: 'Results',
'class': 'modal-input-xxlarge nowrap', 'class': 'nowrap',
ngShow: "msg !== ''", ngShow: "msg !== ''",
rows: 10 rows: 10
}, },
stdout: { stdout: {
label: false, label: 'Std Out',
type: 'textarea', type: 'textarea',
readonly: true, readonly: true,
section: 'Results', section: 'Results',
'class': 'modal-input-xxlarge nowrap', 'class': 'nowrap',
ngShow: "stdout !== ''", ngShow: "stdout !== ''",
rows: 10 rows: 10
}, },
stderr: { stderr: {
label: false, label: 'Std Err',
type: 'textarea', type: 'textarea',
readonly: true, readonly: true,
section: 'Results', section: 'Results',
'class': 'modal-input-xxlarge nowrap', 'class': 'nowrap',
ngShow: "stderr !== ''", ngShow: "stderr !== ''",
rows: 10 rows: 10
}, },
results: { results: {
label: false, label: 'Results',
type: 'textarea', type: 'textarea',
section: 'Results',
readonly: true, readonly: true,
'class': 'modal-input-xxlarge nowrap', 'class': 'nowrap',
ngShow: "results !== ''", ngShow: "results !== ''",
rows: 10 rows: 10
}, },
@@ -122,7 +122,7 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
type: 'textarea', type: 'textarea',
readonly: true, readonly: true,
section: 'Traceback', section: 'Traceback',
'class': 'modal-input-xxlarge nowrap', 'class': 'nowrap',
ngShow: "traceback !== ''", ngShow: "traceback !== ''",
rows: 10 rows: 10
}, },
@@ -148,7 +148,7 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
ngShow: "module_name !== ''" ngShow: "module_name !== ''"
}, },
module_args: { module_args: {
label: 'Arguments', label: 'Args',
type: 'text', type: 'text',
readonly: true, readonly: true,
section: 'Module', section: 'Module',

View File

@@ -37,7 +37,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
scope.formModalCancelShow = true; scope.formModalCancelShow = true;
scope.formModalActionClass = 'btn btn-success'; scope.formModalActionClass = 'btn btn-success';
$('.popover').remove(); //remove any lingering pop-overs $('.popover').popover('hide'); //remove any lingering pop-overs
$('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success'); $('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success');
$('#form-modal').modal({ backdrop: 'static', keyboard: false }); $('#form-modal').modal({ backdrop: 'static', keyboard: false });

View File

@@ -52,7 +52,7 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H
HostsReload(params); HostsReload(params);
}); });
$('.popover').remove(); //remove any lingering pop-overs $('.popover').popover('hide'); //remove any lingering pop-overs
$('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success'); $('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success');
$('#form-modal').modal({ backdrop: 'static', keyboard: false }); $('#form-modal').modal({ backdrop: 'static', keyboard: false });

View File

@@ -49,7 +49,7 @@ angular.module('CredentialsListDefinition', [])
mode: 'all', // One of: edit, select, all mode: 'all', // One of: edit, select, all
ngClick: 'addCredential()', ngClick: 'addCredential()',
basePaths: ['teams','users'], // base path must be in list, or action not available basePaths: ['teams','users'], // base path must be in list, or action not available
"class": 'btn-success btn-small', "class": 'btn-success btn-mini',
awToolTip: 'Create a new credential' awToolTip: 'Create a new credential'
} }
}, },
@@ -59,7 +59,7 @@ angular.module('CredentialsListDefinition', [])
ngClick: "editCredential(\{\{ credential.id \}\})", ngClick: "editCredential(\{\{ credential.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
label: 'Edit', label: 'Edit',
"class": 'btn-small', "class": 'btn-mini',
awToolTip: 'View/Edit credential' awToolTip: 'View/Edit credential'
}, },
@@ -67,7 +67,7 @@ angular.module('CredentialsListDefinition', [])
ngClick: "deleteCredential(\{\{ credential.id \}\},'\{\{ credential.name \}\}')", ngClick: "deleteCredential(\{\{ credential.id \}\},'\{\{ credential.name \}\}')",
icon: 'icon-trash', icon: 'icon-trash',
label: 'Delete', label: 'Delete',
"class": 'btn-small btn-danger', "class": 'btn-mini btn-danger',
awToolTip: 'Delete credential' awToolTip: 'Delete credential'
} }
} }

View File

@@ -33,7 +33,7 @@ angular.module('GroupListDefinition', [])
icon: 'icon-plus', icon: 'icon-plus',
mode: 'all', // One of: edit, select, all mode: 'all', // One of: edit, select, all
ngClick: 'createGroup()', ngClick: 'createGroup()',
"class": 'btn-success btn-small', "class": 'btn-success btn-mini',
awToolTip: 'Create a new group' awToolTip: 'Create a new group'
}, },
help: { help: {
@@ -44,7 +44,7 @@ angular.module('GroupListDefinition', [])
dataContainer: "#form-modal", dataContainer: "#form-modal",
icon: "icon-question-sign", icon: "icon-question-sign",
mode: 'all', mode: 'all',
'class': 'btn-small btn-info', 'class': 'btn-mini btn-info',
awToolTip: 'Click for help', awToolTip: 'Click for help',
dataTitle: 'Adding Groups', dataTitle: 'Adding Groups',
id: 'group-help-button', id: 'group-help-button',
@@ -57,7 +57,7 @@ angular.module('GroupListDefinition', [])
label: 'Edit', label: 'Edit',
ngClick: "editGroup(\{\{ group.id \}\})", ngClick: "editGroup(\{\{ group.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
"class": 'btn-small', "class": 'btn-mini',
awToolTip: 'View/Edit group' awToolTip: 'View/Edit group'
}, },
@@ -65,7 +65,7 @@ angular.module('GroupListDefinition', [])
label: 'Delete', label: 'Delete',
ngClick: "deleteGroup(\{\{ group.id \}\},'\{\{ group.name \}\}')", ngClick: "deleteGroup(\{\{ group.id \}\},'\{\{ group.name \}\}')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-small btn-danger', "class": 'btn-mini btn-danger',
awToolTip: 'Delete group' awToolTip: 'Delete group'
} }
} }

View File

@@ -35,7 +35,7 @@ angular.module('HostListDefinition', [])
dataContainer: "#form-modal", dataContainer: "#form-modal",
icon: "icon-question-sign", icon: "icon-question-sign",
mode: 'all', mode: 'all',
'class': 'btn-small btn-info', 'class': 'btn-mini btn-info',
awToolTip: 'Click for help', awToolTip: 'Click for help',
dataTitle: 'Selecting Hosts', dataTitle: 'Selecting Hosts',
iconSize: 'large', iconSize: 'large',
@@ -48,7 +48,7 @@ angular.module('HostListDefinition', [])
label: 'Edit', label: 'Edit',
ngClick: "editHost(\{\{ host.id \}\})", ngClick: "editHost(\{\{ host.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
"class": 'btn-small', "class": 'btn-mini',
awToolTip: 'View/Edit host' awToolTip: 'View/Edit host'
}, },
@@ -56,7 +56,7 @@ angular.module('HostListDefinition', [])
label: 'Delete', label: 'Delete',
ngClick: "deleteHost(\{\{ host.id \}\},'\{\{ host.name \}\}')", ngClick: "deleteHost(\{\{ host.id \}\},'\{\{ host.name \}\}')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-small btn-danger', "class": 'btn-mini btn-danger',
awToolTip: 'Delete host' awToolTip: 'Delete host'
} }
} }

View File

@@ -54,7 +54,7 @@ angular.module('InventoriesListDefinition', [])
icon: 'icon-plus', icon: 'icon-plus',
mode: 'all', // One of: edit, select, all mode: 'all', // One of: edit, select, all
ngClick: 'addInventory()', ngClick: 'addInventory()',
"class": 'btn-small btn-success', "class": 'btn-mini btn-success',
awToolTip: 'Create a new inventory' awToolTip: 'Create a new inventory'
} }
}, },
@@ -64,7 +64,7 @@ angular.module('InventoriesListDefinition', [])
label: 'Edit', label: 'Edit',
ngClick: "editInventory(\{\{ inventory.id \}\})", ngClick: "editInventory(\{\{ inventory.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
"class": 'btn-small', "class": 'btn-mini',
awToolTip: 'View/Edit inventory' awToolTip: 'View/Edit inventory'
}, },
@@ -72,7 +72,7 @@ angular.module('InventoriesListDefinition', [])
label: 'Delete', label: 'Delete',
ngClick: "deleteInventory(\{\{ inventory.id \}\},'\{\{ inventory.name \}\}')", ngClick: "deleteInventory(\{\{ inventory.id \}\},'\{\{ inventory.name \}\}')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-small btn-danger', "class": 'btn-mini btn-danger',
awToolTip: 'Delete inventory' awToolTip: 'Delete inventory'
} }
} }

View File

@@ -53,7 +53,7 @@ angular.module('JobEventsListDefinition', [])
nosort: true, nosort: true,
searchOnly: false, searchOnly: false,
id: 'job-event-host-header', id: 'job-event-host-header',
columnClass: 'hidden-phone hidden-tablet' columnClass: 'hidden-sm'
} }
}, },
@@ -63,14 +63,14 @@ angular.module('JobEventsListDefinition', [])
icon: 'icon-refresh', icon: 'icon-refresh',
label: 'Refresh', label: 'Refresh',
awToolTip: 'Refresh the page', awToolTip: 'Refresh the page',
"class": 'btn-small btn-success', "class": 'btn-mini btn-success',
mode: 'all' mode: 'all'
}, },
edit: { edit: {
label: 'Details', label: 'Details',
ngClick: "jobDetails()", ngClick: "jobDetails()",
icon: 'icon-zoom-in', icon: 'icon-zoom-in',
"class": 'btn btn-small', "class": 'btn btn-mini',
awToolTip: 'Edit job details', awToolTip: 'Edit job details',
mode: 'all' mode: 'all'
}, },
@@ -78,7 +78,7 @@ angular.module('JobEventsListDefinition', [])
label: 'Hosts', label: 'Hosts',
icon: 'icon-th-large', icon: 'icon-th-large',
ngClick: "jobSummary()", ngClick: "jobSummary()",
"class": 'btn btn-small', "class": 'btn btn-mini',
awToolTip: 'View host summary', awToolTip: 'View host summary',
mode: 'all' mode: 'all'
} }
@@ -89,7 +89,7 @@ angular.module('JobEventsListDefinition', [])
label: 'View', label: 'View',
ngClick: "viewJobEvent(\{\{ jobevent.id \}\})", ngClick: "viewJobEvent(\{\{ jobevent.id \}\})",
icon: 'icon-zoom-in', icon: 'icon-zoom-in',
"class": 'btn-small', "class": 'btn-mini',
awToolTip: 'View event details' awToolTip: 'View event details'
} }
} }

View File

@@ -60,7 +60,7 @@ angular.module('JobHostDefinition', [])
label: 'Refresh', label: 'Refresh',
icon: 'icon-refresh', icon: 'icon-refresh',
ngClick: "refresh()", ngClick: "refresh()",
"class": 'btn-success btn-small', "class": 'btn-success btn-mini',
awToolTip: 'Refresh the page', awToolTip: 'Refresh the page',
mode: 'all' mode: 'all'
}, },
@@ -68,7 +68,7 @@ angular.module('JobHostDefinition', [])
label: 'Details', label: 'Details',
icon: 'icon-edit', icon: 'icon-edit',
ngClick: "jobDetails()", ngClick: "jobDetails()",
"class": 'btn btn-small', "class": 'btn btn-mini',
awToolTip: 'Edit job details', awToolTip: 'Edit job details',
mode: 'all' mode: 'all'
}, },
@@ -76,7 +76,7 @@ angular.module('JobHostDefinition', [])
label: 'Events', label: 'Events',
icon: 'icon-list-ul', icon: 'icon-list-ul',
ngClick: "jobEvents()", ngClick: "jobEvents()",
"class": 'btn btn-small', "class": 'btn btn-mini',
awToolTip: 'View job events', awToolTip: 'View job events',
mode: 'all' mode: 'all'
}, },

View File

@@ -34,7 +34,7 @@ angular.module('JobTemplatesListDefinition', [])
icon: 'icon-plus', icon: 'icon-plus',
mode: 'all', // One of: edit, select, all mode: 'all', // One of: edit, select, all
ngClick: 'addJobTemplate()', ngClick: 'addJobTemplate()',
"class": 'btn-success btn-small', "class": 'btn-success btn-mini',
basePaths: ['job_templates'], basePaths: ['job_templates'],
awToolTip: 'Create a new template' awToolTip: 'Create a new template'
} }
@@ -46,13 +46,13 @@ angular.module('JobTemplatesListDefinition', [])
ngClick: "editJobTemplate(\{\{ job_template.id \}\})", ngClick: "editJobTemplate(\{\{ job_template.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
awToolTip: 'Edit template', awToolTip: 'Edit template',
"class": 'btn-small' "class": 'btn-mini'
}, },
submit: { submit: {
label: 'Launch', label: 'Launch',
icon: 'icon-rocket', icon: 'icon-rocket',
mode: 'all', mode: 'all',
"class": 'btn-small btn-success', "class": 'btn-mini btn-success',
ngClick: 'submitJob(\{\{ job_template.id \}\})', ngClick: 'submitJob(\{\{ job_template.id \}\})',
awToolTip: 'Start a job using this template' awToolTip: 'Start a job using this template'
}, },
@@ -60,7 +60,7 @@ angular.module('JobTemplatesListDefinition', [])
label: 'Delete', label: 'Delete',
ngClick: "deleteJobTemplate(\{\{ job_template.id \}\},'\{\{ job_template.name \}\}')", ngClick: "deleteJobTemplate(\{\{ job_template.id \}\},'\{\{ job_template.name \}\}')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-danger btn-small', "class": 'btn-danger btn-mini',
awToolTip: 'Delete template' awToolTip: 'Delete template'
} }
} }

View File

@@ -57,7 +57,7 @@ angular.module('JobsListDefinition', [])
actions: { actions: {
refresh: { refresh: {
label: 'Refresh', label: 'Refresh',
"class": 'btn-success btn-small', "class": 'btn-success btn-mini',
ngClick: "refreshJob(\{\{ job.id \}\})", ngClick: "refreshJob(\{\{ job.id \}\})",
icon: 'icon-refresh', icon: 'icon-refresh',
awToolTip: 'Refresh the page', awToolTip: 'Refresh the page',
@@ -70,7 +70,7 @@ angular.module('JobsListDefinition', [])
label: 'Hosts', label: 'Hosts',
icon: 'icon-th-large', icon: 'icon-th-large',
ngClick: "viewSummary(\{{ job.id \}\}, '\{\{ job.name \}\}')", ngClick: "viewSummary(\{{ job.id \}\}, '\{\{ job.name \}\}')",
"class": 'btn btn-small', "class": 'btn btn-mini',
awToolTip: 'View host summary', awToolTip: 'View host summary',
ngDisabled: "job.status == 'new'" ngDisabled: "job.status == 'new'"
}, },
@@ -79,7 +79,7 @@ angular.module('JobsListDefinition', [])
icon: 'icon-list-ul', icon: 'icon-list-ul',
mode: 'all', mode: 'all',
ngClick: "viewEvents(\{{ job.id \}\}, '\{\{ job.name \}\}')", ngClick: "viewEvents(\{{ job.id \}\}, '\{\{ job.name \}\}')",
"class": 'btn btn-small', "class": 'btn btn-mini',
awToolTip: 'View events', awToolTip: 'View events',
ngDisabled: "job.status == 'new'" ngDisabled: "job.status == 'new'"
}, },
@@ -87,21 +87,21 @@ angular.module('JobsListDefinition', [])
label: 'Details', label: 'Details',
icon: 'icon-zoom-in', icon: 'icon-zoom-in',
ngClick: "editJob(\{\{ job.id \}\}, '\{\{ job.name \}\}')", ngClick: "editJob(\{\{ job.id \}\}, '\{\{ job.name \}\}')",
"class": 'btn btn-small', "class": 'btn btn-mini',
awToolTip: 'View job details' awToolTip: 'View job details'
}, },
rerun: { rerun: {
icon: 'icon-retweet', icon: 'icon-retweet',
mode: 'all', mode: 'all',
ngClick: "submitJob(\{\{ job.id \}\}, '\{\{ job.summary_fields.job_template.name \}\}' )", ngClick: "submitJob(\{\{ job.id \}\}, '\{\{ job.summary_fields.job_template.name \}\}' )",
"class": 'btn-success btn-small', "class": 'btn-success btn-mini',
awToolTip: 'Re-run this job' awToolTip: 'Re-run this job'
}, },
cancel: { cancel: {
icon: 'icon-minus-sign', icon: 'icon-minus-sign',
mode: 'all', mode: 'all',
ngClick: 'deleteJob(\{\{ job.id \}\})', ngClick: 'deleteJob(\{\{ job.id \}\})',
"class": 'btn-danger btn-small', "class": 'btn-danger btn-mini',
awToolTip: 'Cancel job', awToolTip: 'Cancel job',
ngShow: "job.status == 'pending' || job.status == 'running'" ngShow: "job.status == 'pending' || job.status == 'running'"
}, },
@@ -109,7 +109,7 @@ angular.module('JobsListDefinition', [])
icon: 'icon-trash', icon: 'icon-trash',
mode: 'all', mode: 'all',
ngClick: 'deleteJob(\{\{ job.id \}\})', ngClick: 'deleteJob(\{\{ job.id \}\})',
"class": 'btn-danger btn-small', "class": 'btn-danger btn-mini',
awToolTip: 'Delete this job', awToolTip: 'Delete this job',
ngShow: "job.status != 'pending' && job.status != 'running'" ngShow: "job.status != 'pending' && job.status != 'running'"
} }

View File

@@ -33,7 +33,7 @@ angular.module('OrganizationListDefinition', [])
icon: 'icon-plus', icon: 'icon-plus',
mode: 'all', // One of: edit, select, all mode: 'all', // One of: edit, select, all
ngClick: 'addOrganization()', ngClick: 'addOrganization()',
"class": 'btn-success btn-small', "class": 'btn-success btn-mini',
awToolTip: 'Create a new organization' awToolTip: 'Create a new organization'
} }
}, },
@@ -43,7 +43,7 @@ angular.module('OrganizationListDefinition', [])
label: 'Edit', label: 'Edit',
ngClick: "editOrganization(\{\{ organization.id \}\})", ngClick: "editOrganization(\{\{ organization.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
"class": 'btn-small', "class": 'btn-mini',
awToolTip: 'View/Edit organization' awToolTip: 'View/Edit organization'
}, },
@@ -51,7 +51,7 @@ angular.module('OrganizationListDefinition', [])
label: 'Delete', label: 'Delete',
ngClick: "deleteOrganization(\{\{ organization.id \}\},'\{\{ organization.name \}\}')", ngClick: "deleteOrganization(\{\{ organization.id \}\},'\{\{ organization.name \}\}')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-small btn-danger', "class": 'btn-mini btn-danger',
awToolTip: 'Delete organization' awToolTip: 'Delete organization'
} }
} }

View File

@@ -47,7 +47,7 @@ angular.module('PermissionListDefinition', [])
label: 'Create New', label: 'Create New',
mode: 'all', // One of: edit, select, all mode: 'all', // One of: edit, select, all
ngClick: 'addPermission()', ngClick: 'addPermission()',
"class": 'btn-success btn-small', "class": 'btn-success btn-mini',
awToolTip: 'Add a new permission' awToolTip: 'Add a new permission'
} }
}, },
@@ -57,7 +57,7 @@ angular.module('PermissionListDefinition', [])
label: 'Edit', label: 'Edit',
ngClick: "editPermission(\{\{ permission.id \}\})", ngClick: "editPermission(\{\{ permission.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
"class": 'btn-small', "class": 'btn-mini',
awToolTip: 'View/Edit permission' awToolTip: 'View/Edit permission'
}, },
@@ -65,7 +65,7 @@ angular.module('PermissionListDefinition', [])
label: 'Delete', label: 'Delete',
ngClick: "deletePermission(\{\{ permission.id \}\},'\{\{ permission.name \}\}')", ngClick: "deletePermission(\{\{ permission.id \}\},'\{\{ permission.name \}\}')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-small btn-danger', "class": 'btn-mini btn-danger',
awToolTip: 'Delete permission' awToolTip: 'Delete permission'
} }
} }

View File

@@ -35,7 +35,7 @@ angular.module('ProjectsListDefinition', [])
icon: 'icon-plus', icon: 'icon-plus',
mode: 'all', // One of: edit, select, all mode: 'all', // One of: edit, select, all
ngClick: 'addProject()', ngClick: 'addProject()',
"class": 'btn-success btn-small', "class": 'btn-success btn-mini',
awToolTip: 'Create a new project' awToolTip: 'Create a new project'
} }
}, },
@@ -45,7 +45,7 @@ angular.module('ProjectsListDefinition', [])
label: 'Edit', label: 'Edit',
ngClick: "editProject(\{\{ project.id \}\})", ngClick: "editProject(\{\{ project.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
"class": 'btn-small', "class": 'btn-mini',
awToolTip: 'View/edit project' awToolTip: 'View/edit project'
}, },
@@ -53,7 +53,7 @@ angular.module('ProjectsListDefinition', [])
label: 'Delete', label: 'Delete',
ngClick: "deleteProject(\{\{ project.id \}\},'\{\{ project.name \}\}')", ngClick: "deleteProject(\{\{ project.id \}\},'\{\{ project.name \}\}')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-small btn-danger', "class": 'btn-mini btn-danger',
awToolTip: 'Delete project' awToolTip: 'Delete project'
} }
} }

View File

@@ -40,7 +40,7 @@ angular.module('TeamsListDefinition', [])
icon: 'icon-plus', icon: 'icon-plus',
mode: 'all', // One of: edit, select, all mode: 'all', // One of: edit, select, all
ngClick: 'addTeam()', ngClick: 'addTeam()',
"class": 'btn-small btn-success', "class": 'btn-mini btn-success',
awToolTip: 'Create a new team' awToolTip: 'Create a new team'
} }
}, },
@@ -50,7 +50,7 @@ angular.module('TeamsListDefinition', [])
label: 'Edit', label: 'Edit',
ngClick: "editTeam(\{\{ team.id \}\})", ngClick: "editTeam(\{\{ team.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
"class": 'btn-small', "class": 'btn-mini',
awToolTip: 'View/Edit team' awToolTip: 'View/Edit team'
}, },
@@ -58,7 +58,7 @@ angular.module('TeamsListDefinition', [])
label: 'Delete', label: 'Delete',
ngClick: "deleteTeam(\{\{ team.id \}\},'\{\{ team.name \}\}')", ngClick: "deleteTeam(\{\{ team.id \}\},'\{\{ team.name \}\}')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-small btn-danger', "class": 'btn-mini btn-danger',
awToolTip: 'Delete team' awToolTip: 'Delete team'
} }
} }

View File

@@ -40,7 +40,7 @@ angular.module('UserListDefinition', [])
mode: 'all', // One of: edit, select, all mode: 'all', // One of: edit, select, all
ngClick: 'addUser()', ngClick: 'addUser()',
basePaths: ['organizations','users'], // base path must be in list, or action not available basePaths: ['organizations','users'], // base path must be in list, or action not available
"class": 'btn-success btn-small', "class": 'btn-success btn-mini',
awToolTip: 'Create a new user' awToolTip: 'Create a new user'
} }
}, },
@@ -50,7 +50,7 @@ angular.module('UserListDefinition', [])
label: 'Edit', label: 'Edit',
ngClick: "editUser(\{\{ user.id \}\})", ngClick: "editUser(\{\{ user.id \}\})",
icon: 'icon-edit', icon: 'icon-edit',
"class": 'btn-small', "class": 'btn-mini',
awToolTip: 'View/Edit user' awToolTip: 'View/Edit user'
}, },
@@ -58,7 +58,7 @@ angular.module('UserListDefinition', [])
label: 'Delete', label: 'Delete',
ngClick: "deleteUser(\{\{ user.id \}\},'\{\{ user.username \}\}')", ngClick: "deleteUser(\{\{ user.id \}\},'\{\{ user.username \}\}')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-small btn-danger', "class": 'btn-mini btn-danger',
awToolTip: 'Delete user' awToolTip: 'Delete user'
} }
} }

View File

@@ -209,18 +209,21 @@ angular.module('AWDirectives', ['RestServices'])
content: attrs.awPopOver, trigger: 'manual', html: true, container: container }); content: attrs.awPopOver, trigger: 'manual', html: true, container: container });
$(element).click(function() { $(element).click(function() {
var me = $(this).attr('id'); var me = $(this).attr('id');
var e = $(this);
$('.help-link, .help-link-white').each( function(index) { $('.help-link, .help-link-white').each( function(index) {
if (me != $(this).attr('id')) { if (me != $(this).attr('id')) {
$(this).popover('hide'); $(this).popover('hide');
} }
else {
$(this).popover('toggle');
}
}); });
$('.popover').each(function(index) {
// remove lingering popover <div>. Seems to be a bug in TB3 RC1
$(this).remove();
});
$(this).popover('toggle');
}); });
$(document).bind('keydown', function(e) { $(document).bind('keydown', function(e) {
if (e.keyCode === 27) { if (e.keyCode === 27) {
$(element).popover('hide'); $(element).popover('destroy');
} }
}); });
} }

View File

@@ -72,14 +72,14 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
if (options.modal) { if (options.modal) {
this.scope.formHeader = (options.mode == 'add') ? form.addTitle : form.editTitle; //Default title for default modal 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 this.scope.formModalInfo = false //Disable info button for default modal
$('.popover').remove(); //remove any lingering pop-overs $('.popover').popover('hide'); //remove any lingering pop-overs
if (options.modal_selector) { if (options.modal_selector) {
$(options.modal_selector).removeClass('skinny-modal'); //Used in job_events to remove white space $(options.modal_selector).removeClass('skinny-modal'); //Used in job_events to remove white space
$(options.modal_selector).modal({ backdrop: 'static', keyboard: false }); $(options.modal_selector).modal({ show: true, backdrop: 'static', keyboard: false });
} }
else { else {
$('#form-modal').removeClass('skinny-modal'); //Used in job_events to remove white space //$('#form-modal').removeClass('skinny-modal'); //Used in job_events to remove white space
$('#form-modal').modal({ backdrop: 'static', keyboard: false }); $('#form-modal').modal({ show: true, backdrop: 'static', keyboard: false });
} }
} }
return this.scope; return this.scope;
@@ -212,7 +212,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
var html = ''; var html = '';
for (var i=0; i < btn.position.length; i++) { for (var i=0; i < btn.position.length; i++) {
if (btn.position[i].indexOf(topOrBottom) >= 0) { if (btn.position[i].indexOf(topOrBottom) >= 0) {
html += "<button "; html += "<button type=\"button\" ";
html += "class=\"btn"; html += "class=\"btn";
html += (btn['class']) ? " " + btn['class'] : ""; html += (btn['class']) ? " " + btn['class'] : "";
if (btn.position[i] == 'top-right' || btn.position[i] == 'bottom-right') { if (btn.position[i] == 'top-right' || btn.position[i] == 'bottom-right') {
@@ -228,22 +228,65 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
return html; return html;
}, },
buildField: function(fld, field, options) { buildField: function(fld, field, options, form) {
var html=''; function getFieldWidth() {
var x;
if (form.formFieldSize) {
x = form.formFieldSize;
}
else if (field.xtraWide) {
x = "col-lg-10";
}
else if (field.column) {
x = "col-lg-8";
}
else if (!form.formFieldSize && options.modal) {
x = "col-lg-10";
}
else {
x = "col-lg-6";
}
return x;
}
//Assuming horizontal form for now. This will need to be more flexible later. function getLabelWidth() {
var x;
if (form.formLabelSize) {
x = form.formLabelSize;
}
else if (field.column) {
x = "col-lg-4";
}
else if (!form.formLabelSize && options.modal) {
x = "col-lg-2";
}
else {
x = "col-lg-2";
}
return x;
}
//text fields var html = '';
if (field.type == 'text' || field.type == 'password' || field.type == 'email') {
if ( (! field.readonly) || (field.readonly && options.mode == 'edit') ) { if (field.type == 'hidden') {
html += "<div class=\"control-group\"" if ( (options.mode == 'edit' && field.includeOnEdit) ||
html += (field.ngShow) ? this.attr(field,'ngShow') : ""; (options.mode == 'add' && field.includeOnAdd) ) {
html += (field.ngHide) ? this.attr(field,'ngHide') : ""; html += "<input type=\"hidden\" ng-model=\"" + fld + "\" name=\"" + fld + "\" />";
html += ">\n"; }
}
if ( (! field.readonly) || (field.readonly && options.mode == 'edit') ) {
html += "<div class=\"form-group\" ";
html += (field.ngShow) ? this.attr(field,'ngShow') : "";
html += (field.ngHide) ? this.attr(field,'ngHide') : "";
html += ">\n";
//text fields
if (field.type == 'text' || field.type == 'password' || field.type == 'email') {
html += "<label "; html += "<label ";
html += (field.labelNGClass) ? "ng-class=\"" + field.labelNGClass + "\" " : ""; html += (field.labelNGClass) ? "ng-class=\"" + field.labelNGClass + "\" " : "";
html += "class=\"control-label"; html += "class=\"control-label " + getLabelWidth();
html += (field.labelClass) ? " " + field.labelClass : ""; html += (field.labelClass) ? " " + field.labelClass : "";
html += "\" for=\"" + fld + '">'; html += "\" for=\"" + fld + '">';
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : ""; html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
@@ -251,8 +294,9 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
html += field.label + '</label>' + "\n"; html += field.label + '</label>' + "\n";
html += "<div "; html += "<div ";
html += (field.controlNGClass) ? "ng-class=\"" + field.controlNGClass + "\" " : ""; html += (field.controlNGClass) ? "ng-class=\"" + field.controlNGClass + "\" " : "";
html += "class=\"controls\">\n"; html += "class=\"" + getFieldWidth() + "\">\n";
html += (field.clear || field.genMD5) ? "<div class=\"input-append\">\n" : ""; html += (field.clear || field.genMD5) ? "<div class=\"input-group\">\n" : "";
if (field.control === null || field.control === undefined || field.control) { if (field.control === null || field.control === undefined || field.control) {
html += "<input "; html += "<input ";
html += this.attr(field,'type'); html += this.attr(field,'type');
@@ -260,7 +304,9 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
html += 'name="' + fld + '" '; html += 'name="' + fld + '" ';
html += (field.ngChange) ? this.attr(field,'ngChange') : ""; html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.id) ? this.attr(field,'id') : ""; html += (field.id) ? this.attr(field,'id') : "";
html += (field['class']) ? this.attr(field, 'class') : ""; html += "class=\"form-control";
html += (field['class']) ? " " + this.attr(field, 'class') : "";
html += "\" ";
html += (field.placeholder) ? this.attr(field,'placeholder') : ""; html += (field.placeholder) ? this.attr(field,'placeholder') : "";
html += (options.mode == 'edit' && field.editRequired) ? "required " : ""; html += (options.mode == 'edit' && field.editRequired) ? "required " : "";
html += (options.mode == 'add' && field.addRequired) ? "required " : ""; html += (options.mode == 'add' && field.addRequired) ? "required " : "";
@@ -270,310 +316,288 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
html += (field.ask) ? "ng-disabled=\"" + fld + "_ask\" " : ""; html += (field.ask) ? "ng-disabled=\"" + fld + "_ask\" " : "";
html += (field.autocomplete !== undefined) ? this.attr(field, 'autocomplete') : ""; html += (field.autocomplete !== undefined) ? this.attr(field, 'autocomplete') : "";
html += (field.awRequiredWhen) ? "data-awrequired-init=\"" + field.awRequiredWhen.init + "\" aw-required-when=\"" + html += (field.awRequiredWhen) ? "data-awrequired-init=\"" + field.awRequiredWhen.init + "\" aw-required-when=\"" +
field.awRequiredWhen.variable + "\" " : ""; field.awRequiredWhen.variable + "\" " : "";
html += (field.associated && this.form.fields[field.associated].ask) ? "ng-disabled=\"" + field.associated + "_ask\" " : ""; html += (field.associated && this.form.fields[field.associated].ask) ? "ng-disabled=\"" + field.associated + "_ask\" " : "";
html += "/>"; html += " >\n";
if (field.clear) { }
html += " \n<button class=\"btn\" ng-click=\"clear('" + fld + "','" + field.associated + "')\" " +
"aw-tool-tip=\"Clear " + field.label + "\" id=\"" + fld + "-clear-btn\"><i class=\"icon-undo\"></i></button>\n"; if (field.clear) {
html += "</div>\n"; html += "<span class=\"input-group-btn\"><button type=\"button\" class=\"btn\" ng-click=\"clear('" + fld + "','" + field.associated + "')\" " +
} "aw-tool-tip=\"Clear " + field.label + "\" id=\"" + fld + "-clear-btn\"><i class=\"icon-undo\"></i></button>\n";
if (field.genMD5) {
html += " \n<button class=\"btn\" ng-click=\"genMD5('" + fld + "')\" " +
"aw-tool-tip=\"Generate " + field.label + "\" data-placement=\"top\" id=\"" + fld + "-gen-btn\"><i class=\"icon-repeat\"></i></button>\n";
/*html += " \n<button style=\"margin-left: 10px;\" class=\"btn\" ng-click=\"selectAll('" + fld + "')\" " +
"aw-tool-tip=\"Select " + field.label + " for copy\" data-placement=\"top\" id=\"" + fld + "-copy-btn\"><i class=\"icon-copy\"></i></button>\n";*/
html += "</div>\n";
}
if (field.ask) { if (field.ask) {
html += " \n<label class=\"checkbox inline ask-checkbox\"><input type=\"checkbox\" ng-model=\"" + html += "<label class=\"checkbox-inline ask-checkbox\"><input type=\"checkbox\" ng-model=\"" +
fld + "_ask\" ng-change=\"ask('" + fld + "','" + field.associated + "')\" /> Ask at runtime?</label>"; fld + "_ask\" ng-change=\"ask('" + fld + "','" + field.associated + "')\" > Ask at runtime?</label>";
} }
html += "<br />\n"; html += "</span>\n</div>\n";
// Add error messages
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ||
field.awRequiredWhen ) {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</span>\n";
}
if (field.type == "email") {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.email\">A valid email address is required!</span>\n";
}
if (field.awPassMatch) {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld +
".$error.awpassmatch\">Must match Password value</span>\n";
}
html += "<span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span>\n";
}
html += "</div>\n";
html += "</div>\n";
}
}
//textarea fields
if (field.type == 'textarea') {
if ( (! field.readonly) || (field.readonly && options.mode == 'edit') ) {
html += "<div class=\"control-group\""
html += (field.ngShow) ? this.attr(field,'ngShow') : "";
html += ">\n";
if (field.label !== false) {
html += "<label class=\"control-label\" for=\"" + fld + '">';
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
html += field.label + '</label>' + "\n";
html += "<div class=\"controls\">\n";
} }
// Variable editing if (field.genMD5) {
if (fld == "variables" || fld == "extra_vars" || fld == 'inventory_variables') { html += "<span class=\"input-group-btn\"><button type=\"button\" class=\"btn\" ng-click=\"genMD5('" + fld + "')\" " +
html += "<div class=\"parse-selection\">Parse as: " + "aw-tool-tip=\"Generate " + field.label + "\" data-placement=\"top\" id=\"" + fld + "-gen-btn\"><i class=\"icon-repeat\">" +
"<label class=\"radio inline\"><input type=\"radio\" ng-model=\""; "</i></button></span>\n</div>\n";
html += (this.form.parseTypeName) ? this.form.parseTypeName : 'parseType';
html += "\" value=\"yaml\"> YAML</label>\n";
html += "<label class=\"radio inline\"><input type=\"radio\" ng-model=\"";
html += (this.form.parseTypeName) ? this.form.parseTypeName : 'parseType';
html += "\" value=\"json\"> JSON</label></div>\n";
} }
html += "<textarea ";
html += (field.rows) ? this.attr(field, 'rows') : "";
html += "ng-model=\"" + fld + '" ';
html += 'name="' + fld + '" ';
html += (field['class']) ? this.attr(field,'class') : "";
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.id) ? this.attr(field,'id') : "";
html += (field.placeholder) ? this.attr(field,'placeholder') : "";
html += (options.mode == 'edit' && field.editRequired) ? "required " : "";
html += (options.mode == 'add' && field.addRequired) ? "required " : "";
html += (field.readonly || field.showonly) ? "readonly " : "";
html += "></textarea><br />\n";
// Add error messages // Add error messages
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ) { if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ||
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " + field.awRequiredWhen ) {
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</span>\n"; html += "<div class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</div>\n";
} }
html += "<span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span>\n"; if (field.type == "email") {
if (field.label !== false) { html += "<div class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
html += "</div>\n"; this.form.name + '_form.' + fld + ".$error.email\">A valid email address is required!</div>\n";
} }
if (field.awPassMatch) {
html += "<div class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld +
".$error.awpassmatch\">Must match Password value</div>\n";
}
html += "<div class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></div>\n";
html += "</div>\n"; html += "</div>\n";
} }
//textarea fields
if (field.type == 'textarea') {
if (field.label !== false) {
html += "<label class=\"control-label " + getLabelWidth() + "\" for=\"" + fld + '">';
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
html += field.label + '</label>' + "\n";
html += "<div ";
html += (field.controlNGClass) ? "ng-class=\"" + field.controlNGClass + "\" " : "";
html += "class=\"" + getFieldWidth() + "\">\n";
}
// Variable editing
if (fld == "variables" || fld == "extra_vars" || fld == 'inventory_variables') {
html += "<div class=\"parse-selection\">Parse as: " +
"<input type=\"radio\" ng-model=\"";
html += (this.form.parseTypeName) ? this.form.parseTypeName : 'parseType';
html += "\" value=\"yaml\"> <span class=\"parse-label\">YAML</span>\n";
html += "<input type=\"radio\" ng-model=\"";
html += (this.form.parseTypeName) ? this.form.parseTypeName : 'parseType';
html += "\" value=\"json\"> <span class=\"parse-label\">JSON</span>\n</div>\n";
}
html += "<textarea ";
html += (field.rows) ? this.attr(field, 'rows') : "";
html += "ng-model=\"" + fld + '" ';
html += 'name="' + fld + '" ';
html += "class=\"form-control";
html += (field['class']) ? " " + field['class'] : "";
html += "\" ";
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.id) ? this.attr(field,'id') : "";
html += (field.placeholder) ? this.attr(field,'placeholder') : "";
html += (options.mode == 'edit' && field.editRequired) ? "required " : "";
html += (options.mode == 'add' && field.addRequired) ? "required " : "";
html += (field.readonly || field.showonly) ? "readonly " : "";
html += "></textarea>\n";
// Add error messages
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ) {
html += "<div class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</div>\n";
}
html += "<div class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></div>\n";
if (field.label !== false) {
html += "</div>\n";
}
}
//select field
if (field.type == 'select') {
html += "<label class=\"control-label " + getLabelWidth() + "\" for=\"" + fld + '">';
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
html += field.label + '</label>' + "\n";
html += "<div ";
html += (field.controlNGClass) ? "ng-class=\"" + field.controlNGClass + "\" " : "";
html += "class=\"" + getFieldWidth() + "\">\n";
html += "<select ";
html += "ng-model=\"" + fld + '" ';
html += 'name="' + fld + '" ';
html += "class=\"form-control";
html += (field['class']) ? " " + field['class'] : "";
html += "\" ";
html += this.attr(field, 'ngOptions');
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.id) ? this.attr(field,'id') : "";
html += (options.mode == 'edit' && field.editRequired) ? "required " : "";
html += (options.mode == 'add' && field.addRequired) ? "required " : "";
html += (field.readonly) ? "readonly " : "";
html += ">\n";
html += "<option value=\"\">Choose " + field.label + "</option>\n";
html += "</select>\n";
// Add error messages
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ) {
html += "<div class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</div>\n";
}
html += "<div class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></div>\n";
html += "</div>\n";
}
//number field
if (field.type == 'number') {
html += "<label class=\"control-label " + getLabelWidth() + "\" for=\"" + fld + '">';
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
html += field.label + '</label>' + "\n";
html += "<div ";
html += (field.controlNGClass) ? "ng-class=\"" + field.controlNGClass + "\" " : "";
html += "class=\"" + getFieldWidth() + "\">\n";
// Use 'text' rather than 'number' so that our integer directive works correctly
html += (field.slider) ? "<div class=\"slider\" id=\"" + fld + "-slider\"></div>\n" : "";
html += "<input type=\"";
html += (field.spinner) ? "spinner" : "text";
html += "\" value=\"" + field['default'] + "\" ";
html += "class=\"form-control";
html += (field['class']) ? " " + field['class'] : "";
html += "\" ";
html += (field.slider) ? "ng-slider=\"" + fld + "\" " : "";
html += (field.spinner) ? "ng-spinner=\"" + fld + "\" " : "";
html += "ng-model=\"" + fld + '" ';
html += 'name="' + fld + '" ';
html += (field.min || field.min == 0) ? this.attr(field, 'min') : "";
html += (field.max) ? this.attr(field, 'max') : "";
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.slider) ? "id=\"" + fld + "-number\"" : (field.id) ? this.attr(field,'id') : "";
html += (options.mode == 'edit' && field.editRequired) ? "required " : "";
html += (options.mode == 'add' && field.addRequired) ? "required " : "";
html += (field.readonly) ? "readonly " : "";
html += (field.integer) ? "integer " : "";
html += (field.disabled) ? "data-disabled=\"true\" " : "";
html += " >\n";
// Add error messages
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ) {
html += "<div class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</div>\n";
}
if (field.integer) {
html += "<div class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$error.integer\">Must be an integer value</div>\n";
}
if (field.min || field.max) {
html += "<div class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$error.min || " +
this.form.name + '_form.' + fld + ".$error.max\">Must be in range " + field.min + " to " +
field.max + "</div>\n";
}
html += "<div class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></div>\n";
html += "</div>\n";
}
//checkbox
if (field.type == 'checkbox') {
html += "<label class=\"control-label " + getLabelWidth() + "\" > </label>\n";
html += "<div ";
html += (field.controlNGClass) ? "ng-class=\"" + field.controlNGClass + "\" " : "";
html += "class=\"" + getFieldWidth() + "\">\n";
html += "<label class=\"checkbox-inline\">";
html += "<input type=\"checkbox\" ";
html += this.attr(field,'type');
html += "ng-model=\"" + fld + '" ';
html += "name=\"" + fld + '" ';
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.id) ? this.attr(field,'id') : "";
html += this.attr(field,'trueValue');
html += this.attr(field,'falseValue');
html += (field.checked) ? "checked " : "";
html += (field.readonly) ? "disabled " : "";
html += " > " + field.label + "\n";
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
html += "</label>\n";
html += "<div class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></div>\n";
html += "</div>\n";
}
//radio
if (field.type == 'radio') {
html += "<label class=\"control-label " + getLabelWidth() + "\" for=\"" + fld + '">';
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
html += field.label + '</label>' + "\n";
html += "<div ";
html += (field.controlNGClass) ? "ng-class=\"" + field.controlNGClass + "\" " : "";
html += "class=\"" + getFieldWidth() + "\">\n";
for (var i=0; i < field.options.length; i++) {
html += "<label class=\"radio-inline\" ";
html += (field.options[i].ngShow) ? this.attr(field.options[i],'ngShow') : "";
html += ">";
html += "<input type=\"radio\" ";
html += "name=\"" + fld + "\" ";
html += "value=\"" + field.options[i].value + "\" ";
html += "ng-model=\"" + fld + "\" ";
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.readonly) ? "disabled " : "";
html += (options.mode == 'edit' && field.editRequired) ? "required " : "";
html += (options.mode == 'add' && field.addRequired) ? "required " : "";
html += " > " + field.options[i].label + "\n";
html += "</label>\n";
}
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ) {
html += "<div class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</div>\n";
}
html += "<div class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></div>\n";
html += "</div>\n";
}
//lookup type fields
if (field.type == 'lookup' && (field.excludeMode == undefined || field.excludeMode != options.mode)) {
html += "<label class=\"control-label " + getLabelWidth() + "\" for=\"" + fld + '">';
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
html += field.label + '</label>' + "\n";
html += "<div ";
html += (field.controlNGClass) ? "ng-class=\"" + field.controlNGClass + "\" " : "";
html += "class=\"" + getFieldWidth() + "\">\n";
html += "<div class=\"input-group\">\n";
html += "<span class=\"input-group-btn\">\n";
html += "<button type=\"button\" class=\"lookup-btn btn\" " + this.attr(field,'ngClick') + "><i class=\"icon-search\"></i></button>\n";
html += "</span>\n";
html += "<input type=\"text\" class=\"form-control input-medium\" ";
html += "ng-model=\"" + field.sourceModel + '_' + field.sourceField + "\" ";
html += "name=\"" + field.sourceModel + '_' + field.sourceField + "\" ";
html += "class=\"form-control\" ";
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.id) ? this.attr(field,'id') : "";
html += (field.placeholder) ? this.attr(field,'placeholder') : "";
html += (options.mode == 'edit' && field.editRequired) ? "required " : "";
html += (field.awRequiredWhen) ? "data-awrequired-init=\"" + field.awRequiredWhen.init + "\" aw-required-when=\"" +
field.awRequiredWhen.variable + "\" " : "";
html += " awlookup >\n";
html += "</div>\n";
// Add error messages
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ||
field.awRequiredWhen ) {
html += "<div class=\"error\" ng-show=\"" + this.form.name + '_form.' +
field.sourceModel + '_' + field.sourceField + ".$dirty && " +
this.form.name + '_form.' + field.sourceModel + '_' + field.sourceField +
".$error.required\">A value is required!</div>\n";
}
html += "<div class=\"error\" ng-show=\"" + this.form.name + '_form.' +
field.sourceModel + '_' + field.sourceField + ".$dirty && " +
this.form.name + '_form.' + field.sourceModel + '_' + field.sourceField +
".$error.awlookup\">Value not found</div>\n";
html += "<div class=\"error api-error\" ng-bind=\"" + field.sourceModel + '_' + field.sourceField +
"_api_error\"></div>\n";
html += "</div>\n";
}
//custom fields
if (field.type == 'custom') {
html += "<label class=\"control-label " + getLabelWidth();
html += (field.labelClass) ? " " + field.labelClass : "";
html += "\" for=\"" + fld + '">';
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
html += (field.icon) ? this.icon(field.icon) : "";
html += (field.label) ? field.label : '';
html += '</label>' + "\n";
html += "<div ";
html += (field.controlNGClass) ? "ng-class=\"" + field.controlNGClass + "\" " : "";
html += "class=\"" + getFieldWidth() + "\">\n";
html += field.control;
html += "</div>\n";
}
html += "</div>\n";
} }
//select field
if (field.type == 'select') {
if ( (! field.readonly) || (field.readonly && options.mode == 'edit') ) {
html += "<div class=\"control-group\""
html += (field.ngShow) ? this.attr(field,'ngShow') : "";
html += ">\n";
html += "<label class=\"control-label\" for=\"" + fld + '">';
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
html += field.label + '</label>' + "\n";
html += "<div class=\"controls\">\n";
html += "<select ";
html += "ng-model=\"" + fld + '" ';
html += 'name="' + fld + '" ';
//html += "ng-options=\"item.label for item in " + fld + "_options\" ";
html += this.attr(field, 'ngOptions');
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.id) ? this.attr(field,'id') : "";
html += (options.mode == 'edit' && field.editRequired) ? "required " : "";
html += (options.mode == 'add' && field.addRequired) ? "required " : "";
html += (field.readonly) ? "readonly " : "";
html += ">\n";
html += "<option value=\"\">Choose " + field.label + "</option>\n";
html += "</select><br />\n";
// Add error messages
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ) {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</span>\n";
}
html += "<span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span>\n";
html += "</div>\n";
html += "</div>\n";
}
}
//number field
if (field.type == 'number') {
if ( (! field.readonly) || (field.readonly && options.mode == 'edit') ) {
html += "<div class=\"control-group\""
html += (field.ngShow) ? this.attr(field,'ngShow') : "";
html += ">\n";
html += "<label class=\"control-label\" for=\"" + fld + '">';
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
html += field.label + '</label>' + "\n";
html += "<div class=\"controls\">\n";
// Use 'text' rather than 'number' so that our integer directive works correctly
html += (field.slider) ? "<div class=\"slider\" id=\"" + fld + "-slider\"></div>\n" : "";
html += "<input type=\"";
html += (field.spinner) ? "spinner" : "text";
html += "\" value=\"" + field['default'] + "\" ";
html += (field['class']) ? this.attr(field, 'class') : "";
html += (field.slider) ? "ng-slider=\"" + fld + "\" " : "";
html += (field.spinner) ? "ng-spinner=\"" + fld + "\" " : "";
html += "ng-model=\"" + fld + '" ';
html += 'name="' + fld + '" ';
html += (field.min || field.min == 0) ? this.attr(field, 'min') : "";
html += (field.max) ? this.attr(field, 'max') : "";
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.slider) ? "id=\"" + fld + "-number\"" : (field.id) ? this.attr(field,'id') : "";
html += (options.mode == 'edit' && field.editRequired) ? "required " : "";
html += (options.mode == 'add' && field.addRequired) ? "required " : "";
html += (field.readonly) ? "readonly " : "";
html += (field.integer) ? "integer " : "";
html += (field.disabled) ? "data-disabled=\"true\" " : "";
html += "/>\n";
html += "<br />\n";
// Add error messages
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ) {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</span>\n";
}
if (field.integer) {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$error.integer\">Must be an integer value</span>\n";
}
if (field.min || field.max) {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$error.min || " +
this.form.name + '_form.' + fld + ".$error.max\">Must be in range " + field.min + " to " +
field.max + "</span>\n";
}
html += "<span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span>\n";
html += "</div>\n";
html += "</div>\n";
}
}
//checkbox
if (field.type == 'checkbox') {
if ( (! field.readonly) || (field.readonly && options.mode == 'edit') ) {
html += "<div class=\"control-group\" "
html += (field.ngShow) ? this.attr(field,'ngShow') : "";
html += ">\n";
html += "<div class=\"controls\">\n";
html += "<label class=\"checkbox inline\">";
html += "<input ";
html += this.attr(field,'type');
html += "ng-model=\"" + fld + '" ';
html += "name=\"" + fld + '" ';
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.id) ? this.attr(field,'id') : "";
html += this.attr(field,'trueValue');
html += this.attr(field,'falseValue');
html += (field.checked) ? "checked " : "";
html += (field.readonly) ? "disabled " : "";
html += " /> " + field.label + "\n";
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
html += "</label>\n";
html += "<span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span>\n";
html += "</div>\n";
html += "</div>\n";
}
}
//radio
if (field.type == 'radio') {
if ( (! field.readonly) || (field.readonly && options.mode == 'edit') ) {
html += "<div class=\"control-group\" "
html += (field.ngShow) ? this.attr(field,'ngShow') : "";
html += ">\n";
html += "<label class=\"control-label\" for=\"" + fld + '">';
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
html += field.label + '</label>' + "\n";
html += "<div class=\"controls\">\n";
for (var i=0; i < field.options.length; i++) {
html += "<label class=\"radio inline\" ";
html += (field.options[i].ngShow) ? this.attr(field.options[i],'ngShow') : "";
html += ">";
html += "<input type=\"radio\" ";
html += "name=\"" + fld + "\" ";
html += "value=\"" + field.options[i].value + "\" ";
html += "ng-model=\"" + fld + "\" ";
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.readonly) ? "disabled " : "";
html += (options.mode == 'edit' && field.editRequired) ? "required " : "";
html += (options.mode == 'add' && field.addRequired) ? "required " : "";
html += " /> " + field.options[i].label + "\n";
html += "</label>\n";
}
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ) {
html += "<p><span class=\"error\" ng-show=\"" + this.form.name + '_form.' + fld + ".$dirty && " +
this.form.name + '_form.' + fld + ".$error.required\">A value is required!</span></p>\n";
}
html += "<p><span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span></p>\n";
html += "</div>\n";
html += "</div>\n";
}
}
if (field.type == 'hidden') {
if ( (options.mode == 'edit' && field.includeOnEdit) ||
(options.mode == 'add' && field.includeOnAdd) ) {
html += "<input type=\"hidden\" ng-model=\"" + fld + "\" name=\"" + fld + "\" />";
}
}
//lookup type fields
if (field.type == 'lookup' && (field.excludeMode == undefined || field.excludeMode != options.mode)) {
html += "<div class=\"control-group\""
html += (field.ngShow) ? this.attr(field,'ngShow') : "";
html += ">\n";
html += "<label class=\"control-label\" for=\"" + fld + '">';
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
html += field.label + '</label>' + "\n";
html += "<div class=\"controls\">\n";
html += "<div class=\"input-prepend\">\n";
html += "<button class=\"lookup-btn btn\" " + this.attr(field,'ngClick') + "><i class=\"icon-search\"></i></button>\n";
html += "<input class=\"input-medium\" type=\"text\" ";
html += "ng-model=\"" + field.sourceModel + '_' + field.sourceField + "\" ";
html += "name=\"" + field.sourceModel + '_' + field.sourceField + "\" ";
html += (field.ngChange) ? this.attr(field,'ngChange') : "";
html += (field.id) ? this.attr(field,'id') : "";
html += (field.placeholder) ? this.attr(field,'placeholder') : "";
html += (options.mode == 'edit' && field.editRequired) ? "required " : "";
html += (field.awRequiredWhen) ? "data-awrequired-init=\"" + field.awRequiredWhen.init + "\" aw-required-when=\"" +
field.awRequiredWhen.variable + "\" " : "";
html += " awlookup />\n";
html += "</div><br />\n";
// Add error messages
if ( (options.mode == 'add' && field.addRequired) || (options.mode == 'edit' && field.editRequired) ||
field.awRequiredWhen ) {
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' +
field.sourceModel + '_' + field.sourceField + ".$dirty && " +
this.form.name + '_form.' + field.sourceModel + '_' + field.sourceField +
".$error.required\">A value is required!</span>\n";
}
html += "<span class=\"error\" ng-show=\"" + this.form.name + '_form.' +
field.sourceModel + '_' + field.sourceField + ".$dirty && " +
this.form.name + '_form.' + field.sourceModel + '_' + field.sourceField +
".$error.awlookup\">Value not found</span>\n";
html += "<span class=\"error api-error\" ng-bind=\"" + field.sourceModel + '_' + field.sourceField +
"_api_error\"></span>\n";
html += "</div>\n";
html += "</div>\n";
}
//text fields
if (field.type == 'custom') {
if ( (! field.readonly) || (field.readonly && options.mode == 'edit') ) {
html += "<div class=\"control-group\""
html += (field.ngShow) ? this.attr(field,'ngShow') : "";
html += ">\n";
html += "<label class=\"control-label";
html += (field.labelClass) ? " " + field.labelClass : "";
html += "\" for=\"" + fld + '">';
html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : "";
html += (field.icon) ? this.icon(field.icon) : "";
html += (field.label) ? field.label : '';
html += '</label>' + "\n";
html += "<div class=\"controls\">\n";
html += field.control;
html += "</div>\n";
html += "</div>\n";
}
}
return html; return html;
}, },
@@ -588,8 +612,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
//Breadcrumbs //Breadcrumbs
html += "<div class=\"nav-path\">\n"; html += "<div class=\"nav-path\">\n";
html += "<ul class=\"breadcrumb\">\n"; html += "<ul class=\"breadcrumb\">\n";
html += "<li ng-repeat=\"crumb in breadcrumbs\"><a href=\"{{ '#' + crumb.path }}\">{{ crumb.title | capitalize }}</a> " + html += "<li ng-repeat=\"crumb in breadcrumbs\"><a href=\"{{ '#' + crumb.path }}\">{{ crumb.title | capitalize }}</a></li>\n";
"<span class=\"divider\">/</span></li>\n";
html += "<li class=\"active\">"; html += "<li class=\"active\">";
if (options.mode == 'edit') { if (options.mode == 'edit') {
html += this.form.editTitle; html += this.form.editTitle;
@@ -608,7 +631,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
var act; var act;
for (action in this.form.statusActions) { for (action in this.form.statusActions) {
act = this.form.statusActions[action]; act = this.form.statusActions[action];
html += "<button " + this.attr(act, 'ngClick') + "class=\"btn btn-small"; html += "<button type=\"button\" " + this.attr(act, 'ngClick') + "class=\"btn btn-small";
html += (act['class']) ? " " + act['class'] : ""; html += (act['class']) ? " " + act['class'] : "";
html += "\" "; html += "\" ";
html += (act.awToolTip) ? this.attr(act,'awToolTip') : ""; html += (act.awToolTip) ? this.attr(act,'awToolTip') : "";
@@ -623,7 +646,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
html += "<div class=\"form-horizontal status-fields\">\n"; html += "<div class=\"form-horizontal status-fields\">\n";
for (var fld in this.form.statusFields) { for (var fld in this.form.statusFields) {
field = this.form.statusFields[fld]; field = this.form.statusFields[fld];
html += this.buildField(fld, field, options); html += this.buildField(fld, field, options, this.form);
} }
html += "</div><!-- status fields -->\n"; html += "</div><!-- status fields -->\n";
html += "</div><!-- well -->\n"; html += "</div><!-- well -->\n";
@@ -672,24 +695,24 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
var field; var field;
if (this.form.twoColumns) { if (this.form.twoColumns) {
html += "<div class=\"row-fluid\">\n"; html += "<div class=\"row\">\n";
html += "<div class=\"span6\">\n"; html += "<div class=\"col-lg-6\">\n";
for (var fld in this.form.fields) { for (var fld in this.form.fields) {
field = this.form.fields[fld]; field = this.form.fields[fld];
if (field.column == 1) { if (field.column == 1) {
html += this.buildField(fld, field, options); html += this.buildField(fld, field, options, this.form);
} }
} }
html += "</div><!-- column 1 -->\n"; html += "</div><!-- column 1 -->\n";
html += "<div class=\"span6\">\n"; html += "<div class=\"col-lg-6\">\n";
for (var fld in this.form.fields) { for (var fld in this.form.fields) {
field = this.form.fields[fld]; field = this.form.fields[fld];
if (field.column == 2) { if (field.column == 2) {
html += this.buildField(fld, field, options); html += this.buildField(fld, field, options, this.form);
} }
} }
html += "</div><!-- column 2 -->\n"; html += "</div><!-- column 2 -->\n";
html += "</div><!-- inner row -->\n"; html += "</div>\n";
} }
else { else {
// original, single-column form // original, single-column form
@@ -720,8 +743,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
html += "<div" + sectionShow + ">\n"; html += "<div" + sectionShow + ">\n";
section = field.section; section = field.section;
} }
html += this.buildField(fld, field, options, this.form);
html += this.buildField(fld, field, options);
} }
if (section !== '') { if (section !== '') {
html += "</div>\n</div>\n"; html += "</div>\n</div>\n";
@@ -734,46 +756,51 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
//buttons //buttons
if (!this.modal) { if (!this.modal) {
if (this.has('buttons')) { if (this.has('buttons')) {
html += (this.form.twoColumns) ? "<hr />" : ""; if (this.form.twoColumns) {
html += "<div class=\"control-group\">\n"; html += "<div class=\"row\">\n";
html += "<div class=\"controls buttons\">\n"; html += "<div class=\"col-lg-12\">\n";
} html += "<hr />\n";
for (var btn in this.form.buttons) { }
var button = this.form.buttons[btn]; html += "<div class=\"form-group buttons\">\n";
//button html += "<label class=\"col-lg-2 control-label\"> </label>\n";
html += "<button "; html += "<div class=\"controls col-lg-6\">\n";
html += "class=\"btn btn-small"; for (var btn in this.form.buttons) {
html += (button['class']) ? " " + button['class'] : ""; var button = this.form.buttons[btn];
html += "\" "; //button
if (button.ngClick) { html += "<button type=\"button\" ";
html += this.attr(button,'ngClick'); html += "class=\"btn btn-small";
} html += (button['class']) ? " " + button['class'] : "";
html += "\" ";
if (button.ngDisabled) { if (button.ngClick) {
if (btn !== 'reset') { html += this.attr(button,'ngClick');
html += "ng-disabled=\"" + this.form.name + "_form.$pristine || " + this.form.name + "_form.$invalid";
html += (this.form.allowReadonly) ? " || " + this.form.name + "ReadOnly == true" : "";
html += "\" ";
} }
else { if (button.ngDisabled) {
html += "ng-disabled=\"" + this.form.name + "_form.$pristine"; if (btn !== 'reset') {
html += (this.form.allowReadonly) ? " || " + this.form.name + "ReadOnly == true" : ""; html += "ng-disabled=\"" + this.form.name + "_form.$pristine || " + this.form.name + "_form.$invalid";
html += "\" "; html += (this.form.allowReadonly) ? " || " + this.form.name + "ReadOnly == true" : "";
html += "\" ";
}
else {
html += "ng-disabled=\"" + this.form.name + "_form.$pristine";
html += (this.form.allowReadonly) ? " || " + this.form.name + "ReadOnly == true" : "";
html += "\" ";
}
} }
} html += ">";
if (button.icon) {
html += ">"; html += this.icon(button.icon);
if (button.icon) { }
html += this.icon(button.icon); html += button.label + "</button>\n";
} }
html += button.label + "</button>\n";
}
if (this.has('buttons')) {
html += "</div>\n"; html += "</div>\n";
html += "</div>\n"; html += "</div>\n";
if (this.form.twoColumns) {
html += "</div>\n";
html += "</div>\n";
}
} }
html += "</form>\n";
} }
html += "</form>\n";
if ( this.has('well') ) { if ( this.has('well') ) {
html += "</div>\n"; html += "</div>\n";
@@ -812,7 +839,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
html += "<form class=\"form-horizontal\" name=\"" + this.form.name + '_items_form" id="' + this.form.name + '_items_form" novalidate>' + "\n"; html += "<form class=\"form-horizontal\" name=\"" + this.form.name + '_items_form" id="' + this.form.name + '_items_form" novalidate>' + "\n";
for (var fld in this.form.items[itm].fields) { for (var fld in this.form.items[itm].fields) {
var field = this.form.items[itm].fields[fld]; var field = this.form.items[itm].fields[fld];
html += this.buildField(fld, field, options); html += this.buildField(fld, field, options, this.form);
} }
html += "</form>\n"; html += "</form>\n";
html += "<ul class=\"pager\">\n"; html += "<ul class=\"pager\">\n";
@@ -855,22 +882,22 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
*/ */
html = "<div id=\"" + this.form.name + "-collapse-2\" data-open=\"true\" class=\"jqui-accordion\">\n"; html = "<div id=\"" + this.form.name + "-collapse-2\" data-open=\"true\" class=\"jqui-accordion\">\n";
html += "<h3>Inventory Content<h3>\n"; html += "<h3>Inventory Content<h3>\n";
html += "<div>\n"; html += "<div class=\"row\">\n";
for (var itm in form.related) { for (var itm in form.related) {
if (form.related[itm].type == 'tree') { if (form.related[itm].type == 'tree') {
html += "<div class=\"span5\">"; html += "<div class=\"col-lg-5\">";
html += "<div class=\"inventory-buttons\">"; html += "<div class=\"inventory-buttons\">";
html += "<button ng-click=\"editGroup()\" ng-hide=\"groupEditHide\" id=\"inv-group-edit\" class=\"btn btn-pad btn-mini\" " + html += "<button ng-click=\"editGroup()\" ng-hide=\"groupEditHide\" id=\"inv-group-edit\" class=\"btn btn-mini\" " +
"aw-tool-tip=\"Edit the selected group\" data-placement=\"bottom\">" + "aw-tool-tip=\"Edit the selected group\" data-placement=\"bottom\">" +
"<i class=\"icon-edit\"></i> Edit Group</button>"; "<i class=\"icon-edit\"></i> Edit</button>";
html += "<button ng-click=\"addGroup()\" ng-hide=\"groupAddHide\" id=\"inv-group-add\" " + html += "<button ng-click=\"addGroup()\" ng-hide=\"groupAddHide\" id=\"inv-group-add\" " +
"class=\"btn btn-mini btn-success\" aw-tool-tip=\"Add a new group\" " + "class=\"btn btn-mini btn-success\" aw-tool-tip=\"Add a new group\" " +
"data-placement=\"bottom\"><i class=\"icon-plus\"></i> Add Group</button>"; "data-placement=\"bottom\"><i class=\"icon-plus\"></i> Add</button>";
html += "<button ng-click=\"deleteGroup()\" ng-hide=\"groupDeleteHide\" id=\"inv-group-delete\" " + html += "<button ng-click=\"deleteGroup()\" ng-hide=\"groupDeleteHide\" id=\"inv-group-delete\" " +
"aw-tool-tip=\"Delete the selected group\" data-placement=\"bottom\" " + "aw-tool-tip=\"Delete the selected group\" data-placement=\"bottom\" " +
"class=\"btn btn-mini btn-danger\">" + "class=\"btn btn-mini btn-danger\">" +
"<i class=\"icon-trash\"></i> Delete Group</button>"; "<i class=\"icon-trash\"></i> Delete</button>";
html += "</div>\n"; html += "</div>\n";
html += "<div id=\"tree-view\"></div>\n"; html += "<div id=\"tree-view\"></div>\n";
html += "<div class=\" inventory-filter\">"; html += "<div class=\" inventory-filter\">";
@@ -880,15 +907,15 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
html += "</div>\n"; html += "</div>\n";
} }
else { else {
html += "<div id=\"group-view\" class=\"span7\">\n"; html += "<div id=\"group-view\" class=\"col-lg-7\">\n";
html += "<div id=\"hosts-well\" class=\"well\">\n"; html += "<div id=\"hosts-well\" class=\"well\">\n";
html += "<div id=\"hosts-title\" ng-bind-html-unsafe=\"" + form.related[itm].title + "\"></div>\n"; html += "<div id=\"hosts-title\" ng-bind-html-unsafe=\"" + form.related[itm].title + "\"></div>\n";
html += SearchWidget({ iterator: form.related[itm].iterator, template: form.related[itm], mini: true }); html += SearchWidget({ iterator: form.related[itm].iterator, template: form.related[itm], mini: true, size: 'col-lg-6'});
// Add actions(s) // Add actions(s)
html += "<div class=\"list-actions\">\n"; html += "<div class=\"list-actions\">\n";
for (var action in form.related[itm].actions) { for (var action in form.related[itm].actions) {
html += "<button class=\"btn btn-mini "; html += "<button type=\"button\" class=\"btn btn-mini ";
html += (form.related[itm].actions[action]['class']) ? form.related[itm].actions[action]['class'] : "btn-success"; html += (form.related[itm].actions[action]['class']) ? form.related[itm].actions[action]['class'] : "btn-success";
html += "\" "; html += "\" ";
html += (form.related[itm]['actions'][action].id) ? this.attr(form.related[itm]['actions'][action],'id') : ""; html += (form.related[itm]['actions'][action].id) ? this.attr(form.related[itm]['actions'][action],'id') : "";
@@ -1041,7 +1068,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
html += "<div class=\"list-actions\">\n"; html += "<div class=\"list-actions\">\n";
for (var act in form.related[itm].actions) { for (var act in form.related[itm].actions) {
var action = form.related[itm].actions[act]; var action = form.related[itm].actions[act];
html += "<button class=\"btn btn-small "; html += "<button type=\"button\" class=\"btn btn-mini ";
html += (form.related[itm].actions[act]['class']) ? form.related[itm].actions[act]['class'] : "btn-success"; html += (form.related[itm].actions[act]['class']) ? form.related[itm].actions[act]['class'] : "btn-success";
html += "\" "; html += "\" ";
html += this.attr(action,'ngClick'); html += this.attr(action,'ngClick');
@@ -1102,7 +1129,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies'])
html += "<td class=\"actions\">"; html += "<td class=\"actions\">";
for (act in form.related[itm].fieldActions) { for (act in form.related[itm].fieldActions) {
var action = form.related[itm].fieldActions[act]; var action = form.related[itm].fieldActions[act];
html += "<button class=\"btn btn-small"; html += "<button type=\"button\" class=\"btn btn-mini";
html += (action['class']) ? " " + action['class'] : ""; html += (action['class']) ? " " + action['class'] : "";
html += "\" " + this.attr(action,'ngClick'); html += "\" " + this.attr(action,'ngClick');
html += (action.awToolTip) ? this.attr(action,'awToolTip') : ""; html += (action.awToolTip) ? this.attr(action,'awToolTip') : "";

View File

@@ -49,7 +49,7 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
break; break;
case 'awPopOver': case 'awPopOver':
// construct the entire help link // construct the entire help link
result = "<a id=\"awp-" + fld + "\" href=\"\" aw-pop-over=\"" + value + "\" "; result = "<a id=\"awp-" + fld + "\" href=\"\" aw-pop-over=\'" + value + "\' ";
result += (obj.dataTitle) ? "data-title=\"" + obj['dataTitle'].replace(/[\'\"]/g, '&quot;') + "\" " : ""; result += (obj.dataTitle) ? "data-title=\"" + obj['dataTitle'].replace(/[\'\"]/g, '&quot;') + "\" " : "";
result += (obj.dataPlacement) ? "data-placement=\"" + obj['dataPlacement'].replace(/[\'\"]/g, '&quot;') + "\" " : ""; result += (obj.dataPlacement) ? "data-placement=\"" + obj['dataPlacement'].replace(/[\'\"]/g, '&quot;') + "\" " : "";
result += (obj.dataContainer) ? "data-container=\"" + obj['dataContainer'].replace(/[\'\"]/g, '&quot;') + "\" " : ""; result += (obj.dataContainer) ? "data-container=\"" + obj['dataContainer'].replace(/[\'\"]/g, '&quot;') + "\" " : "";
@@ -193,12 +193,14 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
var label = (params.label) ? params.label : null; var label = (params.label) ? params.label : null;
var html= ''; var html= '';
html += "<div class=\"search-widget\">\n"; html += "<div class=\"search-widget ";
html += (params.size) ? params.size : "col-lg-4";
html += "\">\n";
html += (label) ? "<label>" + label +"</label>" : ""; html += (label) ? "<label>" + label +"</label>" : "";
html += "<div class=\"input-prepend input-append\">\n"; html += "<div class=\"input-group\">\n";
html += "<div class=\"btn-group\">\n"; html += "<div class=\"input-group-btn\">\n";
html += "<button class=\"btn "; 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 += "dropdown-toggle\" data-toggle=\"dropdown\">\n";
html += "<span ng-bind=\"" + iterator + "SearchFieldLabel\"></span>\n"; html += "<span ng-bind=\"" + iterator + "SearchFieldLabel\"></span>\n";
html += "<span class=\"caret\"></span>\n"; html += "<span class=\"caret\"></span>\n";
@@ -217,17 +219,17 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += "<select ng-show=\"" + iterator + "SelectShow\" ng-model=\""+ iterator + "SearchSelectValue\" ng-change=\"search('" + iterator + "')\" "; 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 += "ng-options=\"c.name for c in " + iterator + "SearchSelectOpts\" class=\"search-select";
html += (useMini) ? " field-mini-height" : ""; html += (useMini) ? " input-mini" : " input-small";
html += "\"></select>\n"; html += "\"></select>\n";
html += "<input ng-hide=\"" + iterator + "SelectShow || " + iterator + "InputHide\" class=\"input-medium"; html += "<input type=\"text\" ng-hide=\"" + iterator + "SelectShow || " + iterator + "InputHide\" class=\"form-control ";
html += (useMini) ? " field-mini-height" : ""; html += (useMini) ? " input-mini" : " input-small";
html += "\" ng-model=\"" + iterator + "SearchValue\" ng-change=\"search('" + iterator + html += "\" ng-model=\"" + iterator + "SearchValue\" ng-change=\"search('" + iterator +
"')\" placeholder=\"Search\" type=\"text\" >\n"; "')\" placeholder=\"Search\" type=\"text\" >\n";
html += "<div class=\"btn-group\">\n"; html += "<div class=\"input-group-btn\">\n";
html += "<button ng-hide=\"" + iterator + "SelectShow || " + iterator + "HideSearchType || " + iterator + "InputHide\" class=\"btn "; html += "<button type=\"button\" ng-hide=\"" + iterator + "SelectShow || " + iterator + "HideSearchType || " + iterator + "InputHide\" class=\"btn ";
html += (useMini) ? "btn-mini " : "btn-small"; html += (useMini) ? "btn-mini " : "btn-small ";
html += "dropdown-toggle\" data-toggle=\"dropdown\">\n"; html += "dropdown-toggle\" data-toggle=\"dropdown\">\n";
html += "<span ng-bind=\"" + iterator + "SearchTypeLabel\"></span>\n"; html += "<span ng-bind=\"" + iterator + "SearchTypeLabel\"></span>\n";
html += "<span class=\"caret\"></span>\n"; html += "<span class=\"caret\"></span>\n";

View File

@@ -20,7 +20,6 @@ angular.module('License', ['RestServices', 'Utilities', 'FormGenerator', 'Prompt
name: 'license', name: 'license',
well: false, well: false,
forceListeners: true, forceListeners: true,
'class': 'horizontal-narrow',
fields: { fields: {
license_status: { license_status: {
label: 'Status', label: 'Status',

View File

@@ -32,7 +32,7 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
button: function(btn) { button: function(btn) {
// pass in button object, get back html // pass in button object, get back html
var html = ''; var html = '';
html += "<button " + this.attr(btn, 'ngClick') + "class=\"btn"; html += "<button type=\"button\" " + this.attr(btn, 'ngClick') + "class=\"btn";
html += (btn['class']) ? " " + btn['class'] : " btn-small"; html += (btn['class']) ? " " + btn['class'] : " btn-small";
html += (btn['awPopOver']) ? " help-link-white" : ""; html += (btn['awPopOver']) ? " help-link-white" : "";
html += "\" "; html += "\" ";
@@ -88,7 +88,7 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
if (options.mode == 'lookup') { if (options.mode == 'lookup') {
// options should include {hdr: <dialog header>, action: <function...> } // options should include {hdr: <dialog header>, action: <function...> }
this.scope.lookupHeader = options.hdr; this.scope.lookupHeader = options.hdr;
$('.popover').remove(); //remove any lingering pop-overs $('.popover').popover('hide'); //remove any lingering pop-overs
$('#lookup-modal').modal({ backdrop: 'static', keyboard: false }); $('#lookup-modal').modal({ backdrop: 'static', keyboard: false });
} }
@@ -107,8 +107,7 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
//Breadcrumbs //Breadcrumbs
html += "<div class=\"nav-path\">\n"; html += "<div class=\"nav-path\">\n";
html += "<ul class=\"breadcrumb\">\n"; html += "<ul class=\"breadcrumb\">\n";
html += "<li ng-repeat=\"crumb in breadcrumbs\"><a href=\"{{ '#' + crumb.path }}\">{{ crumb.title | capitalize }}</a> " + html += "<li ng-repeat=\"crumb in breadcrumbs\"><a href=\"{{ '#' + crumb.path }}\">{{ crumb.title | capitalize }}</a></li>\n";
"<span class=\"divider\">/</span></li>\n";
html += "<li class=\"active\">"; html += "<li class=\"active\">";
if (options.mode == 'select') { if (options.mode == 'select') {
html += list.selectTitle; html += list.selectTitle;
@@ -131,7 +130,7 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
} }
if (options.mode == 'lookup' || options.id != undefined) { if (options.mode == 'lookup' || options.id != undefined) {
html += SearchWidget({ iterator: list.iterator, template: list, mini: true }); html += SearchWidget({ iterator: list.iterator, template: list, mini: true , size: 'col-lg-7' });
} }
else { else {
html += SearchWidget({ iterator: list.iterator, template: list, mini: false }); html += SearchWidget({ iterator: list.iterator, template: list, mini: false });

View File

@@ -30,13 +30,13 @@ angular.module('Utilities',[])
.factory('Alert', ['$rootScope', '$location', function($rootScope, $location) { .factory('Alert', ['$rootScope', '$location', function($rootScope, $location) {
return function(hdr, msg, cls, action, secondAlert, disableButtons) { return function(hdr, msg, cls, action, secondAlert, disableButtons) {
// Pass in the header and message you want displayed on TB modal dialog found in index.html. // Pass in the header and message you want displayed on TB modal dialog found in index.html.
// Assumes an #id of 'alert-modal'. Pass in an optional TB alert class (i.e. alert-error, alert-success, // Assumes an #id of 'alert-modal'. Pass in an optional TB alert class (i.e. alert-danger, alert-success,
// alert-info...). Pass an optional function(){}, if you want a specific action to occur when user // alert-info...). Pass an optional function(){}, if you want a specific action to occur when user
// clicks 'OK' button. Set secondAlert to true, when a second dialog is needed. // clicks 'OK' button. Set secondAlert to true, when a second dialog is needed.
if (secondAlert) { if (secondAlert) {
$rootScope.alertHeader2 = hdr; $rootScope.alertHeader2 = hdr;
$rootScope.alertBody2 = msg; $rootScope.alertBody2 = msg;
$rootScope.alertClass2 = (cls) ? cls : 'alert-error'; //default alert class is alert-error $rootScope.alertClass2 = (cls) ? cls : 'alert-danger'; //default alert class is alert-danger
$('#alert-modal2').modal({ show: true, keyboard: true , backdrop: 'static' }); $('#alert-modal2').modal({ show: true, keyboard: true , backdrop: 'static' });
$rootScope.disableButtons2 = (disableButtons) ? true : false; $rootScope.disableButtons2 = (disableButtons) ? true : false;
if (action) { if (action) {
@@ -48,7 +48,7 @@ angular.module('Utilities',[])
else { else {
$rootScope.alertHeader = hdr; $rootScope.alertHeader = hdr;
$rootScope.alertBody = msg; $rootScope.alertBody = msg;
$rootScope.alertClass = (cls) ? cls : 'alert-error'; //default alert class is alert-error $rootScope.alertClass = (cls) ? cls : 'alert-danger'; //default alert class is alert-danger
$('#alert-modal').modal({ show: true, keyboard: true , backdrop: 'static' }); $('#alert-modal').modal({ show: true, keyboard: true , backdrop: 'static' });
$rootScope.disableButtons = (disableButtons) ? true : false; $rootScope.disableButtons = (disableButtons) ? true : false;
if (action) { if (action) {

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,36 +1,34 @@
<div class="row-fluid"> <div id="login-modal" class="modal hide">
<div class="span12"> <div class="modal-dialog">
<div class="modal-content">
<div id="login-modal" class="modal hide"> <div class="modal-header login-header">
<div class="modal-header login-header"> <img ng-src="{{ AWXLoginLogo }}" />
<img ng-src="{{ AWXLoginLogo }}" /> </div>
</div> <div class="modal-body">
<div class="modal-body"> <div class="login-alert" ng-show="(sessionExpired == false)">Welcome to AnsibleWorks AWX! &nbsp;Please sign in.</div>
<div class="login-alert" ng-show="(sessionExpired == false)">Welcome to AnsibleWorks AWX! &nbsp;Please sign in.</div> <div class="login-alert" ng-show="(sessionExpired == true)">Your session timed out due to inactivity. Please sign in.</div>
<div class="login-alert" ng-show="(sessionExpired == true)">Your session timed out due to inactivity. Please sign in.</div> <form id="login-form" name="loginForm" class="form-horizontal" autocomplete="off" novalidate >
<form id="login-form" name="loginForm" class="form-horizontal" autocomplete="off" novalidate > <div class="control-group">
<div class="control-group"> <label class="control-label">Username:</label>
<label class="control-label">Username:</label> <div class="controls">
<div class="controls"> <input type="text" name="login_username" ng-model="login_username" id="login-username" autocomplete="off" required><br />
<input type="text" name="login_username" ng-model="login_username" id="login-username" autocomplete="off" required><br /> <span class="error" ng-show="loginForm.login_username.$dirty && loginForm.login_username.$error.required">A value is required!</span>
<span class="error" ng-show="loginForm.login_username.$dirty && loginForm.login_username.$error.required">A value is required!</span> <span class="error api-error" ng-bind="usernameError"></span>
<span class="error api-error" ng-bind="usernameError"></span> </div>
</div> </div>
</div> <div class="control-group">
<div class="control-group"> <label class="control-label">Password:</label>
<label class="control-label">Password:</label> <div class="controls">
<div class="controls"> <input type="password" name="login_password" id="login-password" ng-model="login_password" required autocomplete="off"><br />
<input type="password" name="login_password" id="login-password" ng-model="login_password" required autocomplete="off"><br /> <span class="error" ng-show="loginForm.login_password.$dirty && loginForm.login_password.$error.required">A value is required!</span>
<span class="error" ng-show="loginForm.login_password.$dirty && loginForm.login_password.$error.required">A value is required!</span> <span class="error api-error" ng-bind="passwordError"></span>
<span class="error api-error" ng-bind="passwordError"></span> </div>
</div> </div>
</div> </form>
</form> </div>
</div> <div class="modal-footer">
<div class="modal-footer"> <button ng-click="systemLogin(login_username, login_password)" id="login-button" class="btn btn-primary"><i class="icon-signin"></i> Sign In</button>
<button ng-click="systemLogin(login_username, login_password)" id="login-button" class="btn btn-primary"><i class="icon-signin"></i> Sign In</button> </div>
</div> </div><!-- modal-content -->
</div><!-- modal --> </div><!-- modal-dialog -->
</div><!-- modal -->
</div><!-- span -->
</div><!-- row -->

View File

@@ -6,13 +6,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="{{ STATIC_URL }}css/custom-theme/jquery-ui-1.10.3.custom.css" /> <link rel="stylesheet" href="{{ STATIC_URL }}css/custom-theme/jquery-ui-1.10.3.custom.css" />
<link rel="stylesheet" href="{{ STATIC_URL }}css/bootstrap.min.css" /> <link rel="stylesheet" href="{{ STATIC_URL }}css/bootstrap.min.css" />
<link rel="stylesheet" href="{{ STATIC_URL }}css/bootstrap-responsive.min.css" />
<link rel="stylesheet" href="{{ STATIC_URL }}css/font-awesome.min.css" /> <link rel="stylesheet" href="{{ STATIC_URL }}css/font-awesome.min.css" />
<link rel="stylesheet" href="{{ STATIC_URL }}css/ansible-ui.css" /> <link rel="stylesheet" href="{{ STATIC_URL }}css/ansible-ui.css" />
<link rel="shortcut icon" href="{{ STATIC_URL }}img/favicon.ico" /> <link rel="shortcut icon" href="{{ STATIC_URL }}img/favicon.ico" />
<script>
var $staticURL = "{{ STATIC_URL }}";
</script>
<script src="{{ STATIC_URL }}js/config.js"></script> <script src="{{ STATIC_URL }}js/config.js"></script>
<script src="{{ STATIC_URL }}lib/angular/angular.js"></script> <script src="{{ STATIC_URL }}lib/angular/angular.js"></script>
<script src="{{ STATIC_URL }}lib/angular/angular-resource.js"></script> <script src="{{ STATIC_URL }}lib/angular/angular-resource.js"></script>
@@ -98,30 +95,31 @@
<body> <body>
<div class="navbar navbar-inverse navbar-fixed-top"> <div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner"> <div class="container">
<div class="container">
<a class="brand" href="#organizations"><img class="logo" src="{{ STATIC_URL }}img/logo.png" /></a> <a class="navbar-brand" href="#organizations"><img class="logo" src="{{ STATIC_URL }}img/logo.png" /></a>
<ul class="nav pull-right">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-responsive-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<div class="nav-collapse collapse navbar-responsive-collapse">
<ul class="nav navbar-nav pull-right">
<li ng-show="current_user.username != null && current_user.username != undefined"> <li ng-show="current_user.username != null && current_user.username != undefined">
<a href="" ng-click="viewCurrentUser()" ng-bind="'Hello! ' + current_user.username"></a></li> <a href="" ng-click="viewCurrentUser()" ng-bind="'Hello! ' + current_user.username"></a></li>
<li ng-show="userLoggedIn == true"><a href="" ng-click="viewLicense()">View License</a></li> <li ng-show="userLoggedIn == true"><a href="" ng-click="viewLicense()">View License</a></li>
<li ng-show="userLoggedIn == true"><a href="#/logout">Logout</a></li> <li ng-show="userLoggedIn == true"><a href="#/logout">Logout</a></li>
</ul> </ul>
</div><!-- container --> </div><!-- nav-collapse -->
</div><!-- navbar-inner --> </div><!-- container -->
</div><!-- navbar --> </div><!-- navbar -->
<div class="container-fluid"> <div class="container main-container">
<div class="row-fluid"> <div class="row">
<div class="span12"> <div class="col-lg-12">
</div><!-- span12 -->
</div><!-- row -->
<div class="row-fluid">
<div class="span12">
<ul class="nav nav-tabs"> <ul class="nav nav-tabs">
<li class="active"><a href="#organizations" data-toggle="tab">Organizations</a></li> <li class="active"><a href="#organizations" data-toggle="tab">Organizations</a></li>
<li><a href="#users" data-toggle="tab">Users</a></li> <li><a href="#users" data-toggle="tab">Users</a></li>
@@ -133,113 +131,184 @@
<li><a href="#jobs" data-toggle="tab">Jobs</a></li> <li><a href="#jobs" data-toggle="tab">Jobs</a></li>
</ul> </ul>
<div class="tab-content" ng-cloak> <div class="tab-content">
<div ng-view id="main-view"></div> <div ng-view id="main-view"></div>
</div> </div>
</div> </div>
</div> </div>
<!-- login modal -->
<div id="login-modal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header login-header">
<img src="{{ STATIC_URL }}img/AWX_logo.png" />
</div>
<div class="modal-body">
<div class="login-alert" ng-show="(sessionExpired == false)">Welcome to AnsibleWorks AWX! &nbsp;Please sign in.</div>
<div class="login-alert" ng-show="(sessionExpired == true)">Your session timed out due to inactivity. Please sign in.</div>
<form id="login-form" name="loginForm" class="form-horizontal" autocomplete="off" novalidate >
<div class="form-group">
<label class="control-label col-lg-3">Username</label>
<div class="col-lg-8">
<input type="text" name="login_username" class="form-control" ng-model="login_username"
id="login-username" autocomplete="off" required>
<div class="error" ng-show="loginForm.login_username.$dirty && loginForm.login_username.$error.required">
A value is required!
</div>
<div class="error api-error" ng-bind="usernameError"></div>
</div>
</div>
<div class="form-group">
<label class="control-label col-lg-3">Password</label>
<div class="col-lg-8">
<input type="password" name="login_password" id="login-password" class="form-control"
ng-model="login_password" required autocomplete="off">
<div class="error" ng-show="loginForm.login_password.$dirty && loginForm.login_password.$error.required">
A value is required!
</div>
<div class="error api-error" ng-bind="passwordError"></div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button ng-click="systemLogin(login_username, login_password)" id="login-button" class="btn btn-primary"><i class="icon-signin"></i> Sign In</button>
</div>
</div><!-- modal-content -->
</div><!-- modal-dialog -->
</div><!-- modal -->
<!-- Password Dialog --> <!-- Password Dialog -->
<div id="password-modal" class="modal hide"> <div id="password-modal" class="modal fade">
<div class="modal-header"> <div class="modal-dialog">
<button type="button" class="close" ng-click="cancelJob()" aria-hidden="true">&times;</button> <div class="modal-content">
<h3>Password Required</h3> <div class="modal-header">
</div> <button type="button" class="close" ng-click="cancelJob()" aria-hidden="true">&times;</button>
<div class="modal-body" id="password-body"> <h3>Password Required</h3>
</div> </div>
<div class="modal-footer"> <div class="modal-body" id="password-body">
<a href="#" ng-click="cancelJob()" class="btn">Cancel</a> </div>
<a href="" ng-click="startJob()" class="btn btn-primary" ng-disabled="password_form.$pristine || password_form.$invalid">Continue</a> <div class="modal-footer">
</div> <a href="#" ng-click="cancelJob()" class="btn btn-default">Cancel</a>
</div> <a href="" ng-click="startJob()" class="btn btn-primary" ng-disabled="password_form.$pristine || password_form.$invalid">Continue</a>
</div>
</div><!-- modal-content -->
</div><!-- modal-dialog -->
</div><!-- modal -->
<!-- Lookup dialog. Use for attribute selection --> <!-- Lookup dialog. Use for attribute selection -->
<div id="lookup-modal" class="modal hide"> <div id="lookup-modal" class="modal fade">
<div class="modal-header"> <div class="modal-dialog">
<button type="button" class="close" data-target="#lookup-modal" <div class="modal-content">
data-dismiss="modal" aria-hidden="true">&times;</button> <div class="modal-header">
<h3 ng-bind="lookupHeader"></h3> <button type="button" class="close" data-target="#lookup-modal"
</div> data-dismiss="modal" aria-hidden="true">&times;</button>
<div class="modal-body" id="lookup-modal-body"></div> <h3 ng-bind="lookupHeader"></h3>
<div class="modal-footer"> </div>
<a href="#" data-target="#lookup-modal" data-dismiss="modal" class="btn">Cancel</a> <div class="modal-body" id="lookup-modal-body"></div>
<a href="" ng-click="selectAction()" class="btn btn-primary">Select</a> <div class="modal-footer">
</div> <a href="#" data-target="#lookup-modal" data-dismiss="modal" class="btn btn-default">Cancel</a>
</div> <a href="" ng-click="selectAction()" class="btn btn-primary">Select</a>
</div>
</div><!-- modal-content -->
</div><!-- modal-dialog -->
</div><!-- modal -->
<!-- Generic Form dialog --> <!-- Generic Form dialog -->
<div id="form-modal" class="modal hide"> <div id="form-modal" class="modal fade">
<div class="modal-header"> <div class="modal-dialog">
<button type="button" class="close" data-target="#alert-modal" <div class="modal-content">
data-dismiss="modal" aria-hidden="true">&times;</button> <div class="modal-header">
<h3 ng-bind="formModalHeader"></h3> <button type="button" class="close" data-target="#alert-modal"
</div> data-dismiss="modal" aria-hidden="true">&times;</button>
<div class="modal-body" id="form-modal-body"></div> <h3 ng-bind="formModalHeader"></h3>
<div class="modal-footer"> </div>
<a href="" ng-show="formModalInfo !== undefined && formModalInfo != ''" ng-click="formModalInfoAction()" <div class="modal-body" id="form-modal-body"></div>
class="btn btn-small pull-left"><i class="icon-zoom-in"></i> <span ng-bind="formModalInfo"></span></a> <div class="modal-footer">
<a href="#" ng-show="formModalCancelShow" data-target="#form-modal" data-dismiss="modal" class="btn btn">Cancel</a> <button ng-show="formModalInfo !== undefined && formModalInfo != ''" ng-click="formModalInfoAction()"
<a href="" ng-bind="formModalActionLabel" ng-click="formModalAction()" class="btn btn-primary"></a> class="btn btn-mini pull-left"><i class="icon-zoom-in"></i> <span ng-bind="formModalInfo"></span></button>
</div> <a href="#" ng-show="formModalCancelShow" data-target="#form-modal" data-dismiss="modal" class="btn btn-default">Cancel</a>
</div> <a href="" ng-bind="formModalActionLabel" ng-click="formModalAction()" class="btn btn-primary"></a>
</div>
</div><!-- modal-content -->
</div><!-- modal-dialog -->
</div><!-- modal -->
<div id="form-modal2" class="modal hide"> <div id="form-modal2" class="modal fade">
<div class="modal-header"> <div class="modal-dialog">
<button type="button" class="close" data-target="#alert-modal" <div class="modal-content">
data-dismiss="modal" aria-hidden="true">&times;</button> <div class="modal-header">
<h3 ng-bind="formModal2Header"></h3> <button type="button" class="close" data-target="#alert-modal"
</div> data-dismiss="modal" aria-hidden="true">&times;</button>
<div class="modal-body" id="form-modal2-body"></div> <h3 ng-bind="formModal2Header"></h3>
<div class="modal-footer"> </div>
<a href="" ng-bind="formModal2Info" ng-show="formModal2Info !== undefined && formModal2Info != ''" ng-click="formModal2InfoAction()" <div class="modal-body" id="form-modal2-body"></div>
class="btn btn-small pull-left"><i class="icon-zoom-in"></i> <span ng-bind="formModal2Info"></span></a> <div class="modal-footer">
<a href="#" ng-show="formModal2CancelShow" data-target="#form-modal2" data-dismiss="modal" class="btn btn">Cancel</a> <a href="" ng-bind="formModal2Info" ng-show="formModal2Info !== undefined && formModal2Info != ''" ng-click="formModal2InfoAction()"
<a href="" ng-bind="formModal2ActionLabel" ng-click="formModal2Action()" class="btn btn-primary"></a> class="btn btn-small pull-left"><i class="icon-zoom-in"></i> <span ng-bind="formModal2Info"></span></a>
</div> <a href="#" ng-show="formModal2CancelShow" data-target="#form-modal2" data-dismiss="modal" class="btn btn-default">Cancel</a>
</div> <a href="" ng-bind="formModal2ActionLabel" ng-click="formModal2Action()" class="btn btn-primary"></a>
</div>
</div><!-- modal-content -->
</div><!-- modal-dialog -->
</div><!-- modal -->
<!-- Confirmation Dialog --> <!-- Confirmation Dialog -->
<div id="prompt-modal" class="modal hide"> <div id="prompt-modal" class="modal fade">
<div class="modal-header"> <div class="modal-dialog">
<button type="button" class="close" data-target="#prompt-modal" <div class="modal-content">
data-dismiss="modal" aria-hidden="true">&times;</button> <div class="modal-header">
<h3 ng-bind="promptHeader" id="prompt-header"></h3> <button type="button" class="close" data-target="#prompt-modal"
</div> data-dismiss="modal" aria-hidden="true">&times;</button>
<div class="modal-body" ng-bind-html-unsafe="promptBody" id="prompt-body"> <h3 ng-bind="promptHeader" id="prompt-header"></h3>
</div> </div>
<div class="modal-footer"> <div class="modal-body" ng-bind-html-unsafe="promptBody" id="prompt-body">
<a href="#" data-target="#prompt-modal" data-dismiss="modal" class="btn">No</a> </div>
<a href="" ng-class="promptActionBtnClass" ng-click="promptAction()" id="prompt-action-btn" class="btn">Yes</a> <div class="modal-footer">
</div> <a href="#" data-target="#prompt-modal" data-dismiss="modal" class="btn btn-default">No</a>
</div> <a href="" ng-class="promptActionBtnClass" ng-click="promptAction()" id="prompt-action-btn" class="btn btn-primary">Yes</a>
</div>
</div><!-- modal-content -->
</div><!-- modal-dialog -->
</div><!-- modal -->
<!-- Alerts/error handling dialogs --> <!-- Alerts/error handling dialogs -->
<div id="alert-modal" class="modal hide"> <div id="alert-modal" class="modal fade">
<div class="modal-header"> <div class="modal-dialog">
<button type="button" class="close" ng-hide="disableButtons" data-target="#alert-modal" <div class="modal-content">
data-dismiss="modal" class="modal" aria-hidden="true">&times;</button> <div class="modal-header">
<h3 ng-bind="alertHeader"></h3> <button type="button" class="close" ng-hide="disableButtons" data-target="#alert-modal"
</div> data-dismiss="modal" class="modal" aria-hidden="true">&times;</button>
<div class="modal-body"> <h3 ng-bind="alertHeader"></h3>
<div class="alert" ng-class="alertClass" ng-bind-html-unsafe="alertBody"></div> </div>
</div> <div class="modal-body">
<div class="modal-footer"> <div class="alert" ng-class="alertClass" ng-bind-html-unsafe="alertBody"></div>
<a href="#" ng-hide="disableButtons" data-target="#form-modal" data-dismiss="modal" class="btn">OK</a> </div>
</div> <div class="modal-footer">
</div> <a href="#" ng-hide="disableButtons" data-target="#form-modal" data-dismiss="modal" class="btn btn-default">OK</a>
<div id="alert-modal2" class="modal hide"> </div>
<div class="modal-header"> </div><!-- modal-content -->
<button type="button" class="close" data-target="#alert-modal2" </div><!-- modal-dialog -->
data-dismiss="modal" ng-hide="disableButtons2" aria-hidden="true">&times;</button> </div><!-- modal -->
<h3 ng-bind="alertHeader2"></h3>
</div> <div id="alert-modal2" class="modal fade">
<div class="modal-body"> <div class="modal-dialog">
<div class="alert" ng-class="alertClass2" ng-bind-html-unsafe="alertBody2"></div> <div class="modal-content">
</div> <div class="modal-header">
<div class="modal-footer"> <button type="button" class="close" data-target="#alert-modal2"
<a href="#" ng-hide="disableButtons2" data-target="#form-modal2" data-dismiss="modal" class="btn">OK</a> data-dismiss="modal" ng-hide="disableButtons2" aria-hidden="true">&times;</button>
</div> <h3 ng-bind="alertHeader2"></h3>
</div> </div>
<div class="modal-body">
<div class="alert" ng-class="alertClass2" ng-bind-html-unsafe="alertBody2"></div>
</div>
<div class="modal-footer">
<a href="#" ng-hide="disableButtons2" data-target="#form-modal2" data-dismiss="modal" class="btn btn-default">OK</a>
</div>
</div><!-- modal-content -->
</div><!-- modal-dialog -->
</div><!-- modal -->
</div><!-- container --> </div><!-- container -->
@@ -270,7 +339,7 @@
<script src="{{ STATIC_URL }}lib/md5/jquery.md5.js"></script> <script src="{{ STATIC_URL }}lib/md5/jquery.md5.js"></script>
<script> <script>
$('a[data-toggle="tab"]').on('show', function (e) { $('a[data-toggle="tab"]').on('show.bs.tab', function (e) {
var url = $(e.target).text(); var url = $(e.target).text();
var regx = new RegExp('/\#\/' + url.toLowerCase().replace(/ /g,'_') + '/'); var regx = new RegExp('/\#\/' + url.toLowerCase().replace(/ /g,'_') + '/');
var loc = window.location.toString(); var loc = window.location.toString();