diff --git a/awx/ui/static/js/controllers/Organizations.js b/awx/ui/static/js/controllers/Organizations.js index 13528e51ab..ae940fa77e 100644 --- a/awx/ui/static/js/controllers/Organizations.js +++ b/awx/ui/static/js/controllers/Organizations.js @@ -93,17 +93,18 @@ function OrganizationsAdd ($scope, $rootScope, $compile, $location, $log, $route //scope. // Inject dynamic view - var form = GenerateForm; - var scope = form.inject(OrganizationForm, {mode: 'add', related: false}); + var generator = GenerateForm; + var form = OrganizationForm; + var scope = generator.inject(form, {mode: 'add', related: false}); var base = $location.path().replace(/^\//,'').split('/')[0]; var defaultUrl = GetBasePath('organizations'); - form.reset(); + generator.reset(); LoadBreadCrumbs(); // Save scope.formSave = function() { - form.clearApiErrors(); + generator.clearApiErrors(); Wait('start'); var url = GetBasePath(base); url += (base != 'organizations') ? $routeParams['project_id'] + '/organizations/' : ''; @@ -121,9 +122,8 @@ function OrganizationsAdd ($scope, $rootScope, $compile, $location, $log, $route } }) .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, OrganizationForm, - { hdr: 'Error!', msg: 'Failed to add new organization. Post returned status: ' + status }); + ProcessErrors(scope, data, status, form, + { hdr: 'Error!', msg: 'Failed to add new organization. Post returned status: ' + status }); }); }; diff --git a/awx/ui/static/js/controllers/Permissions.js b/awx/ui/static/js/controllers/Permissions.js index 5787fa1ab5..5bacac093a 100644 --- a/awx/ui/static/js/controllers/Permissions.js +++ b/awx/ui/static/js/controllers/Permissions.js @@ -1,3 +1,14 @@ +/************************************ + * Copyright (c) 2014 AnsibleWorks, Inc. + * + * + * Permissions.js + * + * Controller functions for Permissions model. + * + */ + +'use strict'; function PermissionsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, PermissionList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less index f15948cbb5..1e02a23c0f 100644 --- a/awx/ui/static/less/ansible-ui.less +++ b/awx/ui/static/less/ansible-ui.less @@ -479,14 +479,14 @@ dd { padding-right: 10px; } -/* 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); -} +/* Outline required fields in Red when there is an error */ + .form-control.ng-dirty.ng-invalid, .form-control.ng-dirty.ng-invalid: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 */ diff --git a/awx/ui/static/lib/ansible/AuthService.js b/awx/ui/static/lib/ansible/AuthService.js index f4c2672c15..13b3bd7a6f 100644 --- a/awx/ui/static/lib/ansible/AuthService.js +++ b/awx/ui/static/lib/ansible/AuthService.js @@ -6,6 +6,8 @@ * User authentication functions */ +'use strict'; + angular.module('AuthService', ['ngCookies', 'Utilities']) .factory('Authorization', ['$http', '$rootScope', '$location', '$cookieStore', 'GetBasePath', function($http, $rootScope, $location, $cookieStore, GetBasePath) { diff --git a/awx/ui/static/lib/ansible/InventoryTree.js b/awx/ui/static/lib/ansible/InventoryTree.js index 13cfe384af..da621d0a7d 100644 --- a/awx/ui/static/lib/ansible/InventoryTree.js +++ b/awx/ui/static/lib/ansible/InventoryTree.js @@ -9,6 +9,8 @@ * */ +'use strict'; + angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'PromptDialog']) .factory('SortNodes', [ function() { diff --git a/awx/ui/static/lib/ansible/RestServices.js b/awx/ui/static/lib/ansible/RestServices.js index d88b2b7214..cf9588793f 100644 --- a/awx/ui/static/lib/ansible/RestServices.js +++ b/awx/ui/static/lib/ansible/RestServices.js @@ -4,6 +4,9 @@ * Generic accessor for Ansible Commander services * */ + + 'use strict'; + angular.module('RestServices',['ngCookies','AuthService']) .factory('Rest', ['$http','$rootScope','$cookieStore', '$q', 'Authorization', function($http, $rootScope, $cookieStore, $q, Authorization) { diff --git a/awx/ui/static/lib/ansible/Timer.js b/awx/ui/static/lib/ansible/Timer.js index 88a36f7f31..cfc2d4ecdd 100644 --- a/awx/ui/static/lib/ansible/Timer.js +++ b/awx/ui/static/lib/ansible/Timer.js @@ -7,6 +7,9 @@ * duration set in config.js * */ + +'use strict'; + angular.module('TimerService', ['ngCookies', 'Utilities']) .factory('Timer', ['$rootScope', '$cookieStore', '$location', 'GetBasePath', 'Empty', function($rootScope, $cookieStore, $location, GetBasePath, Empty) { diff --git a/awx/ui/static/lib/ansible/Utilities.js b/awx/ui/static/lib/ansible/Utilities.js index 8136478c19..64b8d9e5dd 100644 --- a/awx/ui/static/lib/ansible/Utilities.js +++ b/awx/ui/static/lib/ansible/Utilities.js @@ -5,6 +5,9 @@ * Utility functions * */ + +'use strict'; + angular.module('Utilities',['RestServices', 'Utilities']) .factory('ClearScope', [ function() { @@ -137,6 +140,7 @@ angular.module('Utilities',['RestServices', 'Utilities']) if (form.fields[field].realName) { if (data[form.fields[field].realName]) { scope[field + '_api_error'] = data[form.fields[field]][0]; + scope[form.name + '_form'][form.fields[field].realName].$setValidity('apiError', false); fieldErrors = true; } } @@ -144,12 +148,15 @@ angular.module('Utilities',['RestServices', 'Utilities']) if (data[field]) { scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '_api_error'] = data[field][0]; + scope[form.name + '_form'][form.fields[field].sourceModel + '_' + form.fields[field].sourceField].$setValidity('apiError', false); fieldErrors = true; } } else { if (data[field]) { + console.log('setting api error: ' + form.name + '_form.' + field); scope[field + '_api_error'] = data[field][0]; + scope[form.name + '_form'][field].$setValidity('apiError', false); fieldErrors = true; } } diff --git a/awx/ui/static/lib/ansible/api-loader.js b/awx/ui/static/lib/ansible/api-loader.js index b6066c8695..668f5535da 100644 --- a/awx/ui/static/lib/ansible/api-loader.js +++ b/awx/ui/static/lib/ansible/api-loader.js @@ -7,6 +7,8 @@ * */ +'use strict'; + angular.module('ApiLoader', ['ngCookies']) .factory('LoadBasePaths', ['$http', '$rootScope', '$cookieStore', 'ProcessErrors', function($http, $rootScope, $cookieStore, ProcessErrors) { diff --git a/awx/ui/static/lib/ansible/directives.js b/awx/ui/static/lib/ansible/directives.js index 5c17cff42a..0225526dfc 100644 --- a/awx/ui/static/lib/ansible/directives.js +++ b/awx/ui/static/lib/ansible/directives.js @@ -5,8 +5,9 @@ * */ -var INTEGER_REGEXP = /^\-?\d*$/; +'use strict'; +var INTEGER_REGEXP = /^\-?\d*$/; angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'JobsHelper']) // awpassmatch: Add to password_confirm field. Will test if value @@ -108,7 +109,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Job function checkIt () { var viewValue = elm.val(); var txt, label; - validity = true; + var validity = true; if ( scope[attrs.awRequiredWhen] && (elm.attr('required') == null || elm.attr('required') == undefined) ) { $(elm).attr('required','required'); if ($(elm).hasClass('lookup')) { diff --git a/awx/ui/static/lib/ansible/filters.js b/awx/ui/static/lib/ansible/filters.js index 1aa7252f45..7e4ff4845d 100644 --- a/awx/ui/static/lib/ansible/filters.js +++ b/awx/ui/static/lib/ansible/filters.js @@ -4,21 +4,22 @@ * Custom filters * */ - + +'use strict'; + angular.module('AWFilters', []) // // capitalize -capitalize the first letter of each word // - .filter('capitalize', function() { + .filter('capitalize', [ function() { return function(input) { if (input) { var values = input.replace(/\_/g,' ').split(" "); var result = ""; - for (i = 0; i < values.length; i++){ + for (var i = 0; i < values.length; i++){ result += values[i].charAt(0).toUpperCase() + values[i].substr(1) + ' '; } - result = result.trim(); - return result; + return result.trim(); } } - }); \ No newline at end of file + }]); \ No newline at end of file diff --git a/awx/ui/static/lib/ansible/form-generator.js b/awx/ui/static/lib/ansible/form-generator.js index 3817f34686..8c251f586a 100644 --- a/awx/ui/static/lib/ansible/form-generator.js +++ b/awx/ui/static/lib/ansible/form-generator.js @@ -8,6 +8,8 @@ * */ +'use strict'; + angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) .factory('GenerateForm', ['$rootScope', '$location', '$cookieStore', '$compile', 'SearchWidget', 'PaginateWidget', 'Attr', 'Icon', 'Column', 'NavigationLink', 'HelpCollapse', 'Button', 'DropDown', 'Empty', 'SelectIcon', @@ -195,7 +197,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) }, applyDefaults: function() { - for (fld in this.form.fields) { + for (var fld in this.form.fields) { if (this.form.fields[fld]['default'] || this.form.fields[fld]['default'] == 0) { if (this.form.fields[fld].type == 'select' && this.scope[fld + '_options']) { this.scope[fld] = this.scope[fld + '_options'][this.form.fields[fld]['default']]; @@ -223,23 +225,27 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) if (f.type == 'checkbox_group') { for (var i=0; i < f.fields.length; i++) { - scope[f.name] = ''; - scope[f.name + '_api_error'] = ''; + scope[f.fields[i].name] = ''; + scope[f.fields[i].name + '_api_error'] = ''; + scope[form.name + '_form'][f.fields[i].name].$setValidity('apiError', true); } } else { scope[fld] = ''; - scope[fld + '_api_error'] = ''; + scope[fld + '_api_error'] = ''; } if (f.sourceModel) { scope[f.sourceModel + '_' + f.sourceField] = ''; scope[f.sourceModel + '_' + f.sourceField + '_api_error'] = ''; + scope[form.name + '_form'][f.sourceModel + '_' + f.sourceField].$setValidity('apiError', true); } if (f.type == 'lookup' && scope[form.name + '_form'][f.sourceModel + '_' + f.sourceField]) { scope[form.name + '_form'][f.sourceModel + '_' + f.sourceField].$setPristine(); + scope[form.name + '_form'][f.sourceModel + '_' + f.sourceField].$setValidity('apiError', true); } if (scope[form.name + '_form'][fld]) { scope[form.name + '_form'][fld].$setPristine(); + scope[form.name + '_form'][fld].$setValidity('apiError', true); } if (f.chkPass && scope[form.name + '_form'][fld]) { scope[form.name + '_form'][fld].$setValidity('complexity', true); @@ -528,19 +534,6 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) //text fields if (field.type == 'text' || field.type == 'password' || field.type == 'email') { - //html += "
'; - //html += (field.icon) ? this.icon(field.icon) : ""; - //html += "" + field.label + '' + "\n"; - //html += (field.awPopOver && field.awPopOverRight) ? this.attr(field, 'awPopOver', fld) : ""; - //html += "
\n"; html += label(); @@ -665,26 +658,6 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) //textarea fields if (field.type == 'textarea') { - - /*if (field.label !== false) { - html += "
"; - html += field.label + '' + "\n"; - html += (field.awPopOver && field.awPopOverRight) ? this.attr(field, 'awPopOver', fld) : ""; - html += "
\n"; - html += "
'; - html += field.label + '' + "\n"; - html += "
\n"; - html += "
'; - html += (field.awPopOver) ? this.attr(field, 'awPopOver', fld) : ""; - html += field.label + '' + "\n"; - html += "
\n" : ""; - */ html += label(); @@ -880,17 +827,6 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) //checkbox if (field.type == 'checkbox') { - //html += "
'; - html += field.label + '' + "\n"; - html += "
\n"; - html += "
\n"; - for (action in this.form.actions) { + var html = "
\n"; + for (var action in this.form.actions) { if (this.form.actions[action].mode == 'all' || this.form.actions[action].mode == options.mode) { html += this.button({ btn: this.form.actions[action], action: action, toolbar: true }); } @@ -1090,24 +1011,10 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) return html; }, - /* - activityCrumbs: function() { - // Breadcrumbs for activity stream widget - // Make the links clickable using ng-click function so we can first remove the stream widget. - html = ''; - html += "
\n"; - html += "\n
\n"; - return html; - }, - */ breadCrumbs: function(options, navigation) { - var html = ''; + var html = ''; html += "
\n"; html += "
    \n"; html += "
  • {{ crumb.title | capitalize }}
  • \n"; @@ -1190,7 +1097,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) if (this.form.statusActions) { html += "
    \n"; var act; - for (action in this.form.statusActions) { + for (var action in this.form.statusActions) { act = this.form.statusActions[action]; html += this.button({ btn: act, action: action, toolbar: true }); } @@ -1241,7 +1148,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) html += (options.mode == 'edit') ? this.form.editTitle : this.form.addTitle; if (this.has('titleActions')) { html += "
    \n"; - for (btn in this.form.titleActions) { + for (var btn in this.form.titleActions) { html += this.button({ btn: this.form.titleActions[btn], action: btn, toolbar: true }); } html += "
    \n"; @@ -1442,7 +1349,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) } if ((!this.modal && this.form.items)) { - for (itm in this.form.items) { + for (var itm in this.form.items) { html += "
    \n"; html += SearchWidget({ iterator: this.form.items[itm].iterator, template: this.form.items[itm], mini: false, label: 'Filter Events'}); html += "
    Viewing" + " \{\{ " + this.form.items[itm].iterator + "Page + 1 \}\} of " + @@ -1485,7 +1392,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) // var idx = 1; var form = this.form; - html = "
    \n"; + var html = "
    \n"; for (var itm in form.related) { if (form.related[itm].type == 'collection') { html += "

    " + form.related[itm].title + "

    \n"; @@ -1561,7 +1468,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) // Row level actions html += ""; - for (act in form.related[itm].fieldActions) { + for (var act in form.related[itm].fieldActions) { var fAction = form.related[itm].fieldActions[act]; html += "\n"; html += "
      \n"; - html += "
    • {{ crumb.title | capitalize }}
    • \n"; + html += "
    • \{\{ crumb.title \| capitalize \}\}
    • \n"; if (list.navigationLinks) { var navigation = list.navigationLinks; diff --git a/awx/ui/static/lib/ansible/list-generator.js b/awx/ui/static/lib/ansible/list-generator.js index ff375d5433..d8f30762f1 100644 --- a/awx/ui/static/lib/ansible/list-generator.js +++ b/awx/ui/static/lib/ansible/list-generator.js @@ -7,6 +7,8 @@ * */ +'use strict'; + angular.module('ListGenerator', ['GeneratorHelpers']) .factory('GenerateList', [ '$location', '$compile', '$rootScope', 'SearchWidget', 'PaginateWidget', 'Attr', 'Icon', 'Column', 'DropDown', 'NavigationLink', 'Button', 'SelectIcon', 'Breadcrumbs', @@ -124,7 +126,7 @@ angular.module('ListGenerator', ['GeneratorHelpers']) // before navigation html += "
      \n"; html += "\n
      \n"; @@ -190,7 +192,7 @@ angular.module('ListGenerator', ['GeneratorHelpers']) html += "
      \n"; // Add toolbar buttons or 'actions' - for (action in list.actions) { + for (var action in list.actions) { if (list.actions[action].mode == 'all' || list.actions[action].mode == options.mode) { if ( (list.actions[action].basePaths == undefined) || (list.actions[action].basePaths && list.actions[action].basePaths.indexOf(base) > -1) ) { @@ -341,7 +343,7 @@ angular.module('ListGenerator', ['GeneratorHelpers']) html += (fAction.awPopOver) ? "aw-pop-over=\"" + fAction.awPopOver + "\" " : ""; html += (fAction.dataPlacement) ? Attr(fAction, 'dataPlacement') : ""; html += (fAction.dataTitle) ? Attr(fAction, 'dataTitle') : ""; - for (itm in fAction) { + for (var itm in fAction) { if (itm != 'ngHref' && itm != 'href' && itm != 'label' && itm != 'icon' && itm != 'class' && itm != 'iconClass' && itm != "dataPlacement" && itm != "awPopOver" && itm != "dataTitle") { html += Attr(fAction, itm); diff --git a/awx/ui/static/lib/ansible/prompt-dialog.js b/awx/ui/static/lib/ansible/prompt-dialog.js index 4cc6e306ec..f5891796c0 100644 --- a/awx/ui/static/lib/ansible/prompt-dialog.js +++ b/awx/ui/static/lib/ansible/prompt-dialog.js @@ -14,6 +14,8 @@ * } */ +'use strict'; + angular.module('PromptDialog', ['Utilities']) .factory('Prompt', ['$rootScope', '$compile', 'Alert', function($rootScope, $compile, Alert) { return function(params) {