diff --git a/awx/ui/static/js/controllers/Admins.js b/awx/ui/static/js/controllers/Admins.js index 223551f601..798db73940 100644 --- a/awx/ui/static/js/controllers/Admins.js +++ b/awx/ui/static/js/controllers/Admins.js @@ -3,33 +3,49 @@ * * * Admins.js - * + * * Controller functions for ading Admins to an Organization. * */ 'use strict'; -function AdminsList ($scope, $rootScope, $location, $log, $routeParams, Rest, - Alert, AdminList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, - ReturnToCaller,GetBasePath, SelectionInit) -{ - var list = AdminList; - var defaultUrl = GetBasePath('organizations') + $routeParams.organization_id + '/users/' ; - var view = GenerateList; - var mode = 'select'; - var scope = view.inject(AdminList, { mode: mode }); // Inject our view +function AdminsList($scope, $rootScope, $location, $log, $routeParams, Rest, + Alert, AdminList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, + ReturnToCaller, GetBasePath, SelectionInit) { - var url = GetBasePath('organizations') + $routeParams.organization_id + '/admins/'; - SelectionInit({ scope: scope, list: list, url: url, returnToCaller: 1 }); + var list = AdminList, + defaultUrl = GetBasePath('organizations') + $routeParams.organization_id + '/users/', + view = GenerateList, + mode = 'select', + scope = view.inject(AdminList, { mode: mode }), + url = GetBasePath('organizations') + $routeParams.organization_id + '/admins/'; + + SelectionInit({ + scope: scope, + list: list, + url: url, + returnToCaller: 1 + }); + + SearchInit({ + scope: scope, + set: 'admins', + list: list, + url: defaultUrl + }); + + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl + }); - SearchInit({ scope: scope, set: 'admins', list: list, url: defaultUrl }); - PaginateInit({ scope: scope, list: list, url: defaultUrl }); scope.search(list.iterator); LoadBreadCrumbs(); } -AdminsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'AdminList', 'GenerateList', - 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'GetBasePath', 'SelectionInit']; - +AdminsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'AdminList', 'GenerateList', + 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'GetBasePath', 'SelectionInit' +]; \ No newline at end of file diff --git a/awx/ui/static/js/controllers/Authentication.js b/awx/ui/static/js/controllers/Authentication.js index ca102a4fbf..2ee4bd7f6b 100644 --- a/awx/ui/static/js/controllers/Authentication.js +++ b/awx/ui/static/js/controllers/Authentication.js @@ -8,139 +8,145 @@ * */ + /* globals console:false */ + 'use strict'; -function Authenticate($cookieStore, $window, $scope, $rootScope, $location, Authorization, ToggleClass, Alert, Wait, - Timer, Empty) -{ - var setLoginFocus = function() { - $('#login-username').focus(); - }; +function Authenticate($cookieStore, $window, $scope, $rootScope, $location, Authorization, ToggleClass, Alert, Wait, + Timer, Empty) { + + var setLoginFocus, lastPath, sessionExpired, scope; - var sessionExpired = (Empty($rootScope.sessionExpired)) ? $cookieStore.get('sessionExpired') : $rootScope.sessionExpired; - - var lastPath = function() { - return (Empty($rootScope.lastPath)) ? $cookieStore.get('lastPath') : $rootScope.lastPath; - } + setLoginFocus = function () { + $('#login-username').focus(); + }; - if ($AnsibleConfig.debug_mode && console) { - console.log('User session expired: ' + sessionExpired); - console.log('Last URL: ' + lastPath()); - } - - // Hide any lingering modal dialogs - $('.modal[aria-hidden=false]').each( function() { - if ($(this).attr('id') !== 'login-modal') { - $(this).modal('hide'); - } - }); + sessionExpired = (Empty($rootScope.sessionExpired)) ? $cookieStore.get('sessionExpired') : $rootScope.sessionExpired; - // Just in case, make sure the wait widget is not active - Wait('stop'); - - // Display the login dialog - $('#login-modal').modal({ show: true, keyboard: false, backdrop: 'static' }); - - // Set focus to username field - $('#login-modal').on('shown.bs.modal', function() { - setLoginFocus(); - }); + lastPath = function () { + return (Empty($rootScope.lastPath)) ? $cookieStore.get('lastPath') : $rootScope.lastPath; + }; - 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 ($AnsibleConfig.debug_mode && console) { + console.log('User session expired: ' + sessionExpired); + console.log('Last URL: ' + lastPath()); + } - if ($location.path() == '/logout') { - //if logout request, clear AuthToken and user session data - Authorization.logout(); - } - - $rootScope.userLoggedIn = false; //hide the logout link. if you got here, you're logged out. - $cookieStore.put('userLoggedIn', false); //gets set back to true by Authorization.setToken(). + // Hide any lingering modal dialogs + $('.modal[aria-hidden=false]').each(function () { + if ($(this).attr('id') !== 'login-modal') { + $(this).modal('hide'); + } + }); - $('#login-password').bind('keypress', function(e) { - var code = (e.keyCode ? e.keyCode : e.which); - if (code == 13) { - $('#login-button').click(); - } - }); - - scope.reset = function() { - $('#login-form input').each( function(index) { $(this).val(''); }); - }; + // Just in case, make sure the wait widget is not active + Wait('stop'); - // Call the API to get an auth token - scope.systemLogin = function(username, password) { - $('.api-error').empty(); - var token; - if (username == null || username == undefined || username == '' || - password == null || password == undefined || password == '' ) { - Alert('Error!', 'Please provide a username and password before attempting to login.', 'alert-danger', setLoginFocus); - } - else { - Wait('start'); - Authorization.retrieveToken(username, password) - .success( function(data, status, headers, config) { - $('#login-modal').modal('hide'); - token = data.token; - Authorization.setToken(data.token, data.expires); - $rootScope.sessionTimer = Timer.init(); - // Get all the profile/access info regarding the logged in user - Authorization.getUser() - .success(function(data, status, headers, config) { - Authorization.setUserInfo(data); - $rootScope['user_is_superuser'] = data.results[0].is_superuser; - Authorization.getLicense() - .success(function(data, status, headers, config) { - Authorization.setLicense(data['license_info']); - if (lastPath()) { - // Go back to most recent navigation path - $location.path(lastPath()); - } - else { - $location.url('/home?login=true'); - } - }) - .error(function(data, status, headers, config) { - Wait('stop'); - Alert('Error', 'Failed to access user information. GET returned status: ' + status, 'alert-danger', setLoginFocus); - }); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - Alert('Error', 'Failed to access license information. GET returned status: ' + status, 'alert-danger', setLoginFocus); - }); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - if ( data.non_field_errors && data.non_field_errors.length == 0 ) { - // show field specific errors returned by the API - for (var key in data) { - scope[key + 'Error'] = data[key][0]; + // Display the login dialog + $('#login-modal').modal({ + show: true, + keyboard: false, + backdrop: 'static' + }); + + // Set focus to username field + $('#login-modal').on('shown.bs.modal', function () { + setLoginFocus(); + }); + + 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 logout request, clear AuthToken and user session data + Authorization.logout(); + } + + $rootScope.userLoggedIn = false; //hide the logout link. if you got here, you're logged out. + $cookieStore.put('userLoggedIn', false); //gets set back to true by Authorization.setToken(). + + $('#login-password').bind('keypress', function (e) { + var code = (e.keyCode ? e.keyCode : e.which); + if (code === 13) { + $('#login-button').click(); + } + }); + + scope.reset = function () { + $('#login-form input').each(function () { + $(this).val(''); + }); + }; + + // Call the API to get an auth token + scope.systemLogin = function (username, password) { + $('.api-error').empty(); + var token; + if (Empty(username) || Empty(password)) { + Alert('Error!', 'Please provide a username and password before attempting to login.', 'alert-danger', setLoginFocus); + } else { + Wait('start'); + Authorization.retrieveToken(username, password) + .success(function (data, status) { + $('#login-modal').modal('hide'); + token = data.token; + Authorization.setToken(data.token, data.expires); + $rootScope.sessionTimer = Timer.init(); + // Get all the profile/access info regarding the logged in user + Authorization.getUser() + .success(function (data) { + Authorization.setUserInfo(data); + $rootScope.user_is_superuser = data.results[0].is_superuser; + Authorization.getLicense() + .success(function (data) { + Authorization.setLicense(data.license_info); + if (lastPath()) { + // Go back to most recent navigation path + $location.path(lastPath()); + } else { + $location.url('/home?login=true'); + } + }) + .error(function () { + Wait('stop'); + Alert('Error', 'Failed to access user information. GET returned status: ' + status, 'alert-danger', setLoginFocus); + }); + }) + .error(function (data, status) { + Wait('stop'); + Alert('Error', 'Failed to access license information. GET returned status: ' + status, 'alert-danger', setLoginFocus); + }); + }) + .error(function (data, status) { + var hdr, msg, key; + Wait('stop'); + if (data.non_field_errors && data.non_field_errors.length === 0) { + // show field specific errors returned by the API + for (key in data) { + scope[key + 'Error'] = data[key][0]; + } + } else { + if (data.non_field_errors && data.non_field_errors.length > 0) { + hdr = 'Error'; + msg = data.non_field_errors[0]; + } else { + hdr = 'Error'; + msg = 'The login attempt failed with a status of: ' + status; + } + scope.reset(); + Alert(hdr, msg, 'alert-danger', setLoginFocus); } - } - else { - var hdr, msg; - if ( data.non_field_errors && data.non_field_errors.length > 0 ) { - hdr = 'Error'; - msg = data.non_field_errors[0]; - } - else { - hdr = 'Error'; - msg = 'The login attempt failed with a status of: ' + status; - } - scope.reset(); - Alert(hdr, msg, 'alert-danger', setLoginFocus); - } - }); - } - } + }); + } + }; } Authenticate.$inject = ['$cookieStore', '$window', '$scope', '$rootScope', '$location', 'Authorization', 'ToggleClass', 'Alert', 'Wait', - 'Timer', 'Empty']; + 'Timer', 'Empty' +]; diff --git a/awx/ui/static/js/controllers/Credentials.js b/awx/ui/static/js/controllers/Credentials.js index a8bbedc751..ef4a636035 100644 --- a/awx/ui/static/js/controllers/Credentials.js +++ b/awx/ui/static/js/controllers/Credentials.js @@ -3,72 +3,80 @@ * * * Credentials.js - * + * * Controller functions for the Credential model. * */ - 'use strict'; -function CredentialsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, CredentialList, - GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, - ClearScope, ProcessErrors, GetBasePath, SelectionInit, GetChoices, Wait, Stream) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. +function CredentialsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, CredentialList, + GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, + ClearScope, ProcessErrors, GetBasePath, SelectionInit, GetChoices, Wait, Stream) { + + ClearScope('htmlTemplate'); + Wait('start'); - var list = CredentialList; - var defaultUrl = GetBasePath('credentials'); - var view = GenerateList; - var base = $location.path().replace(/^\//,'').split('/')[0]; - var mode = (base == 'credentials') ? 'edit' : 'select'; // if base path 'credentials', we're here to add/edit - var scope = view.inject(list, { mode: mode }); // Inject our view + var list = CredentialList, + defaultUrl = GetBasePath('credentials'), + view = GenerateList, + base = $location.path().replace(/^\//, '').split('/')[0], + mode = (base === 'credentials') ? 'edit' : 'select', // if base path 'credentials', we're here to add/edit + scope = view.inject(list, { mode: mode }), + url; + scope.selected = []; scope.credentialLoading = true; - - var url = GetBasePath(base); - url += (base == 'users') ? $routeParams.user_id + '/credentials/' : $routeParams.team_id + '/credentials/'; - SelectionInit({ scope: scope, list: list, url: url, returnToCaller: 1 }); - + url = GetBasePath(base) + ( (base === 'users') ? $routeParams.user_id + '/credentials/' : $routeParams.team_id + '/credentials/' ); + + SelectionInit({ + scope: scope, + list: list, + url: url, + returnToCaller: 1 + }); + if (scope.removePostRefresh) { - scope.removePostRefresh(); + scope.removePostRefresh(); } - scope.removePostRefresh = scope.$on('PostRefresh', function() { + scope.removePostRefresh = scope.$on('PostRefresh', function () { // Cleanup after a delete + var i, j; + Wait('stop'); $('#prompt-modal').off(); list.fields.kind.searchOptions = scope.credential_kind_options; - + // Translate the kind value - for(var i=0; i < scope.credentials.length; i++) { - /* - if (scope.credentials[i].summary_fields.user) { - scope.credentials[i].user_username = scope.credentials[i].summary_fields.user.username; - } - if (scope.credentials[i].summary_fields.team) { - scope.credentials[i].team_name = scope.credentials[i].summary_fields.team.name; - } - */ - for (var j=0; j < scope.credential_kind_options.length; j++) { - if (scope.credential_kind_options[j].value == scope.credentials[i].kind) { - scope.credentials[i].kind = scope.credential_kind_options[j].label - break; - } - } + for (i = 0; i < scope.credentials.length; i++) { + for (j = 0; j < scope.credential_kind_options.length; j++) { + if (scope.credential_kind_options[j].value === scope.credentials[i].kind) { + scope.credentials[i].kind = scope.credential_kind_options[j].label; + break; + } + } } - }); + }); if (scope.removeChoicesReady) { - scope.removeChoicesReady(); + scope.removeChoicesReady(); } - scope.removeChoicesReady = scope.$on('choicesReadyCredential', function() { - SearchInit({ scope: scope, set: 'credentials', list: list, url: defaultUrl }); - PaginateInit({ scope: scope, list: list, url: defaultUrl }); - scope.search(list.iterator); + scope.removeChoicesReady = scope.$on('choicesReadyCredential', function () { + SearchInit({ + scope: scope, + set: 'credentials', + list: list, + url: defaultUrl }); + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl + }); + scope.search(list.iterator); + }); // Load the list of options for Kind GetChoices({ @@ -77,434 +85,499 @@ function CredentialsList ($scope, $rootScope, $location, $log, $routeParams, Res field: 'kind', variable: 'credential_kind_options', callback: 'choicesReadyCredential' - }); + }); LoadBreadCrumbs(); - scope.showActivity = function() { Stream({ scope: scope }); } - - scope.addCredential = function() { - $location.path($location.path() + '/add'); - } + scope.showActivity = function () { + Stream({ + scope: scope + }); + }; - scope.editCredential = function(id) { - $location.path($location.path() + '/' + id); - } - - scope.deleteCredential = function(id, name) { - - var action = function() { - $('#prompt-modal').on('hidden.bs.modal', function(){ Wait('start'); }); - $('#prompt-modal').modal('hide'); - var url = defaultUrl + id + '/'; - Rest.setUrl(url); - Rest.destroy() - .success( function(data, status, headers, config) { - scope.search(list.iterator); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); - }); - }; + scope.addCredential = function () { + $location.path($location.path() + '/add'); + }; - Prompt({ hdr: 'Delete', - body: 'Are you sure you want to delete ' + name + '?', - action: action + scope.editCredential = function (id) { + $location.path($location.path() + '/' + id); + }; + + scope.deleteCredential = function (id, name) { + + var action = function () { + $('#prompt-modal').on('hidden.bs.modal', function () { + Wait('start'); + }); + $('#prompt-modal').modal('hide'); + var url = defaultUrl + id + '/'; + Rest.setUrl(url); + Rest.destroy() + .success(function (data, status, headers, config) { + scope.search(list.iterator); + }) + .error(function (data, status, headers, config) { + Wait('stop'); + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status + }); }); - } + }; + + Prompt({ + hdr: 'Delete', + body: 'Are you sure you want to delete ' + name + '?', + action: action + }); + }; } -CredentialsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'CredentialList', 'GenerateList', - 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', - 'GetBasePath', 'SelectionInit', 'GetChoices', 'Wait', 'Stream' ]; +CredentialsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'CredentialList', 'GenerateList', + 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', + 'GetBasePath', 'SelectionInit', 'GetChoices', 'Wait', 'Stream' +]; -function CredentialsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, - GenerateList, SearchInit, PaginateInit, LookUpInit, UserList, TeamList, GetBasePath, - GetChoices, Empty, KindChange, OwnerChange, FormSave, DebugForm) -{ - ClearScope('tree-form'); - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. +function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm, + GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, + GenerateList, SearchInit, PaginateInit, LookUpInit, UserList, TeamList, GetBasePath, + GetChoices, Empty, KindChange, OwnerChange, FormSave, DebugForm) { + ClearScope('tree-form'); + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. - // Inject dynamic view - var defaultUrl = GetBasePath('credentials'); - var form = CredentialForm; - var generator = GenerateForm; - var scope = generator.inject(form, {mode: 'add', related: false}); - var base = $location.path().replace(/^\//,'').split('/')[0]; - var defaultUrl = GetBasePath('credentials'); - generator.reset(); - LoadBreadCrumbs(); + // Inject dynamic view + var form = CredentialForm, + generator = GenerateForm, + scope = generator.inject(form, { mode: 'add', related: false }), + base = $location.path().replace(/^\//, '').split('/')[0], + defaultUrl = GetBasePath('credentials'), + url; + + generator.reset(); + LoadBreadCrumbs(); - // Load the list of options for Kind - GetChoices({ + // Load the list of options for Kind + GetChoices({ scope: scope, url: defaultUrl, field: 'kind', variable: 'credential_kind_options' + }); + + LookUpInit({ + scope: scope, + form: form, + current_item: (!Empty($routeParams.user_id)) ? $routeParams.user_id : null, + list: UserList, + field: 'user' + }); + + LookUpInit({ + scope: scope, + form: form, + current_item: (!Empty($routeParams.team_id)) ? $routeParams.team_id : null, + list: TeamList, + field: 'team' + }); + + if (!Empty($routeParams.user_id)) { + // Get the username based on incoming route + scope.owner = 'user'; + scope.user = $routeParams.user_id; + OwnerChange({ + scope: scope + }); + url = GetBasePath('users') + $routeParams.user_id + '/'; + Rest.setUrl(url); + Rest.get() + .success(function (data, status, headers, config) { + scope.user_username = data.username; + }) + .error(function (data, status, headers, config) { + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve user. GET status: ' + status + }); + }); + } else if (!Empty($routeParams.team_id)) { + // Get the username based on incoming route + scope.owner = 'team'; + scope.team = $routeParams.team_id; + OwnerChange({ + scope: scope + }); + url = GetBasePath('teams') + $routeParams.team_id + '/'; + Rest.setUrl(url); + Rest.get() + .success(function (data, status, headers, config) { + scope.team_name = data.name; + }) + .error(function (data, status, headers, config) { + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve team. GET status: ' + status + }); + }); + } else { + // default type of owner to a user + scope.owner = 'user'; + OwnerChange({ + scope: scope + }); + } + + // Handle Kind change + scope.kindChange = function () { + KindChange({ + scope: scope, + form: form, + reset: true + }); + }; + + // Save + scope.formSave = function () { + generator.clearApiErrors(); + FormSave({ + scope: scope, + mode: 'add' + }); + }; + + // Handle Owner change + scope.ownerChange = function () { + OwnerChange({ + scope: scope + }); + }; + + // Reset defaults + scope.formReset = function () { + generator.reset(); + //DebugForm({ form: CredentialForm, scope: scope }); + }; + + // Password change + scope.clearPWConfirm = function (fld) { + // If password value changes, make sure password_confirm must be re-entered + scope[fld] = ''; + scope[form.name + '_form'][fld].$setValidity('awpassmatch', false); + }; + + // Respond to 'Ask at runtime?' checkbox + scope.ask = function (fld, associated) { + if (scope[fld + '_ask']) { + scope[fld] = 'ASK'; + scope[associated] = ''; + scope[form.name + '_form'][associated].$setValidity('awpassmatch', true); + } else { + scope[fld] = ''; + scope[associated] = ''; + scope[form.name + '_form'][associated].$setValidity('awpassmatch', true); + } + }; + + // Click clear button + scope.clear = function (fld, associated) { + scope[fld] = ''; + scope[associated] = ''; + scope[form.name + '_form'][associated].$setValidity('awpassmatch', true); + scope[form.name + '_form'].$setDirty(); + }; + +} + +CredentialsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'CredentialForm', 'GenerateForm', + 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList', + 'SearchInit', 'PaginateInit', 'LookUpInit', 'UserList', 'TeamList', 'GetBasePath', 'GetChoices', 'Empty', + 'KindChange', 'OwnerChange', 'FormSave', 'DebugForm' +]; + + +function CredentialsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm, + GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, + RelatedPaginateInit, ReturnToCaller, ClearScope, Prompt, GetBasePath, GetChoices, + KindChange, UserList, TeamList, LookUpInit, Empty, OwnerChange, FormSave, Stream, + Wait +) { + + ClearScope('htmlTemplate'); + + var defaultUrl = GetBasePath('credentials'), + generator = GenerateForm, + form = CredentialForm, + scope = generator.inject(form, { mode: 'edit', related: true }), + base = $location.path().replace(/^\//, '').split('/')[0], + master = {}, + id = $routeParams.credential_id; + + generator.reset(); + scope.id = id; + + function setAskCheckboxes() { + var fld, i; + for (fld in form.fields) { + if (form.fields[fld].type === 'password' && scope[fld] === 'ASK') { + // turn on 'ask' checkbox for password fields with value of 'ASK' + $("#" + fld + "-clear-btn").attr("disabled", "disabled"); + scope[fld + '_ask'] = true; + } else { + scope[fld + '_ask'] = false; + $("#" + fld + "-clear-btn").removeAttr("disabled"); + } + master[fld + '_ask'] = scope[fld + '_ask']; + } + + // Set kind field to the correct option + for (i = 0; i < scope.credential_kind_options.length; i++) { + if (scope.kind === scope.credential_kind_options[i].value) { + scope.kind = scope.credential_kind_options[i]; + break; + } + } + } + + if (scope.removeCredentialLoaded) { + scope.removeCredentialLoaded(); + } + scope.removeCredentialLoaded = scope.$on('credentialLoaded', function () { + LookUpInit({ + scope: scope, + form: form, + current_item: (!Empty($scope.user_id)) ? scope.user_id : null, + list: UserList, + field: 'user' }); - LookUpInit({ - scope: scope, - form: form, - current_item: (!Empty($routeParams.user_id)) ? $routeParams.user_id : null, - list: UserList, - field: 'user' - }); + LookUpInit({ + scope: scope, + form: form, + current_item: (!Empty($scope.team_id)) ? scope.team_id : null, + list: TeamList, + field: 'team' + }); - LookUpInit({ - scope: scope, - form: form, - current_item: (!Empty($routeParams.team_id)) ? $routeParams.team_id : null, - list: TeamList, - field: 'team' - }); + setAskCheckboxes(); + KindChange({ + scope: scope, + form: form, + reset: false + }); + OwnerChange({ + scope: scope + }); + Wait('stop'); + }); - if (!Empty($routeParams.user_id)) { - // Get the username based on incoming route - scope['owner'] = 'user'; - scope['user'] = $routeParams.user_id; - OwnerChange({ scope: scope }); - var url = GetBasePath('users') + $routeParams.user_id + '/'; - Rest.setUrl(url); - Rest.get() - .success( function(data, status, headers, config) { - scope['user_username'] = data.username; - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to retrieve user. GET status: ' + status }); - }); - } - else if (!Empty($routeParams.team_id)) { - // Get the username based on incoming route - scope['owner'] = 'team'; - scope['team'] = $routeParams.team_id; - OwnerChange({ scope: scope }); - var url = GetBasePath('teams') + $routeParams.team_id + '/'; - Rest.setUrl(url); - Rest.get() - .success( function(data, status, headers, config) { - scope['team_name'] = data.name; - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to retrieve team. GET status: ' + status }); - }); - } - else { - // default type of owner to a user - scope['owner'] = 'user'; - OwnerChange({ scope: scope }); - } - - // Handle Kind change - scope.kindChange = function () { - KindChange({ scope: scope, form: form, reset: true }); - } - - // Save - scope.formSave = function() { generator.clearApiErrors(); FormSave({ scope: scope, mode: 'add' }) }; - - // Handle Owner change - scope.ownerChange = function() { - OwnerChange({ scope: scope }); - } - - // Reset defaults - scope.formReset = function() { - generator.reset(); - //DebugForm({ form: CredentialForm, scope: scope }); - }; - - // Password change - scope.clearPWConfirm = function(fld) { - // If password value changes, make sure password_confirm must be re-entered - scope[fld] = ''; - scope[form.name + '_form'][fld].$setValidity('awpassmatch', false); - } - - // Respond to 'Ask at runtime?' checkbox - scope.ask = function(fld, associated) { - if (scope[fld + '_ask']) { - scope[fld] = 'ASK'; - scope[associated] = ''; - scope[form.name + '_form'][associated].$setValidity('awpassmatch', true); - } - else { - scope[fld] = ''; - scope[associated] = ''; - scope[form.name + '_form'][associated].$setValidity('awpassmatch', true); - } - } - - // Click clear button - scope.clear = function(fld, associated) { - scope[fld] = ''; - scope[associated] = ''; - scope[form.name + '_form'][associated].$setValidity('awpassmatch', true); - scope[form.name + '_form'].$setDirty(); - } - -} - -CredentialsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'CredentialForm', 'GenerateForm', - 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList', - 'SearchInit', 'PaginateInit', 'LookUpInit', 'UserList', 'TeamList', 'GetBasePath', 'GetChoices', 'Empty', - 'KindChange', 'OwnerChange', 'FormSave', 'DebugForm']; - - -function CredentialsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, - RelatedPaginateInit, ReturnToCaller, ClearScope, Prompt, GetBasePath, GetChoices, - KindChange, UserList, TeamList, LookUpInit, Empty, OwnerChange, FormSave, Stream, - Wait - ) -{ - ClearScope('tree-form'); - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. - - var defaultUrl=GetBasePath('credentials'); - var generator = GenerateForm; - var form = CredentialForm; - var scope = generator.inject(form, {mode: 'edit', related: true}); - generator.reset(); - var base = $location.path().replace(/^\//,'').split('/')[0]; - var defaultUrl = GetBasePath('credentials'); - - var master = {}; - var id = $routeParams.credential_id; - scope['id'] = id; - - var relatedSets = {}; - - function setAskCheckboxes() { - for (var fld in form.fields) { - if (form.fields[fld].type == 'password' && scope[fld] == 'ASK') { - // turn on 'ask' checkbox for password fields with value of 'ASK' - $("#" + fld + "-clear-btn").attr("disabled","disabled"); - scope[fld + '_ask'] = true; - } - else { - scope[fld + '_ask'] = false; - $("#" + fld + "-clear-btn").removeAttr("disabled"); - } - master[fld + '_ask'] = scope[fld + '_ask']; - } - - // Set kind field to the correct option - for (var i=0; i < scope['credential_kind_options'].length; i++) { - if (scope['kind'] == scope['credential_kind_options'][i].value) { - scope['kind'] = scope['credential_kind_options'][i]; - break; - } - } - } - - if (scope.removeCredentialLoaded) { - scope.removeCredentialLoaded(); - } - scope.removeCredentialLoaded = scope.$on('credentialLoaded', function() { - LookUpInit({ - scope: scope, - form: form, - current_item: (!Empty($scope['user_id'])) ? scope['user_id'] : null, - list: UserList, - field: 'user' - }); - - LookUpInit({ - scope: scope, - form: form, - current_item: (!Empty($scope['team_id'])) ? scope['team_id'] : null, - list: TeamList, - field: 'team' - }); - - setAskCheckboxes(); - KindChange({ scope: scope, form: form, reset: false }); - OwnerChange({ scope: scope }); - Wait('stop'); - }); - - if (scope.removeChoicesReady) { - scope.removeChoicesReady(); - } - scope.removeChoicesReady = scope.$on('choicesReadyCredential', function() { - // Retrieve detail record and prepopulate the form - Rest.setUrl(defaultUrl + ':id/'); - Rest.get({ params: {id: id} }) - .success( function(data, status, headers, config) { - LoadBreadCrumbs({ path: '/credentials/' + id, title: data.name }); - for (var fld in form.fields) { - if (data[fld] !== null && data[fld] !== undefined) { - scope[fld] = data[fld]; - master[fld] = scope[fld]; - } - if (form.fields[fld].type == 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) { - scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = - data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; - master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = - scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField]; - } - } - - if (!Empty(scope['user'])) { - scope['owner'] = 'user'; - } - else { - scope['owner'] = 'team'; - } - master['owner'] = scope['owner']; - - for (var i=0; i < scope.credential_kind_options.length; i++) { - if (scope.credential_kind_options[i].value == data.kind) { - scope.kind = scope.credential_kind_options[i]; - break; - } - } - master['kind'] = scope['kind']; - - switch (data.kind) { - case 'aws': - scope['access_key'] = data.username; - scope['secret_key'] = data.password; - master['access_key'] = scope['access_key']; - master['secret_key'] = scope['secret_key']; - break; - case 'ssh': - scope['ssh_password'] = data.password; - master['ssh_password'] = scope['ssh_password']; - break; - case 'rax': - scope['api_key'] = data['password']; - master['api_key'] = scope['api_key']; - break; - } - - scope.$emit('credentialLoaded'); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to retrieve Credential: ' + $routeParams.id + '. GET status: ' + status }); - }); - }); - - Wait('start'); - - GetChoices({ - scope: scope, - url: defaultUrl, - field: 'kind', - variable: 'credential_kind_options', - callback: 'choicesReadyCredential' - }); - - scope.showActivity = function() { Stream({ scope: scope }); } - - // Save changes to the parent - scope.formSave = function() { generator.clearApiErrors(); FormSave({ scope: scope, mode: 'edit' }) }; - - // Handle Owner change - scope.ownerChange = function() { - OwnerChange({ scope: scope }); - } - - // Handle Kind change - scope.kindChange = function () { - KindChange({ scope: scope, form: form, reset: true }); - } - - // Cancel - scope.formReset = function() { - generator.reset(); - for (var fld in master) { - scope[fld] = master[fld]; - } - setAskCheckboxes(); - KindChange({ scope: scope, form: form, reset: false }); - OwnerChange({ scope: scope }); - }; - - // Related set: Add button - scope.add = function(set) { - $rootScope.flashMessage = null; - $location.path('/' + base + '/' + $routeParams.id + '/' + set + '/add'); - }; - - // Related set: Edit button - scope.edit = function(set, id, name) { - $rootScope.flashMessage = null; - $location.path('/' + base + '/' + $routeParams.id + '/' + set + '/' + id); - }; - - // Related set: Delete button - scope['delete'] = function(set, itm_id, name, title) { - $rootScope.flashMessage = null; - - var action = function() { - var url = defaultUrl + id + '/' + set + '/'; - Rest.setUrl(url); - Rest.post({ id: itm_id, disassociate: 1 }) - .success( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); - scope.search(form.related[set].iterator); - }) - .error( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status }); - }); - }; - - Prompt({ hdr: 'Delete', - body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?', - action: action + if (scope.removeChoicesReady) { + scope.removeChoicesReady(); + } + scope.removeChoicesReady = scope.$on('choicesReadyCredential', function () { + // Retrieve detail record and prepopulate the form + Rest.setUrl(defaultUrl + ':id/'); + Rest.get({ + params: { + id: id + } + }) + .success(function (data) { + + var i, fld; + + LoadBreadCrumbs({ + path: '/credentials/' + id, + title: data.name }); - - } - // Password change - scope.clearPWConfirm = function(fld) { - // If password value changes, make sure password_confirm must be re-entered - scope[fld] = ''; - scope[form.name + '_form'][fld].$setValidity('awpassmatch', false); - } - - // Respond to 'Ask at runtime?' checkbox - scope.ask = function(fld, associated) { - if (scope[fld + '_ask']) { - $("#" + fld + "-clear-btn").attr("disabled","disabled"); - scope[fld] = 'ASK'; - scope[associated] = ''; - scope[form.name + '_form'][associated].$setValidity('awpassmatch', true); - } - else { - $("#" + fld + "-clear-btn").removeAttr("disabled"); - scope[fld] = ''; - scope[associated] = ''; - scope[form.name + '_form'][associated].$setValidity('awpassmatch', true); - } - } + for (fld in form.fields) { + if (data[fld] !== null && data[fld] !== undefined) { + scope[fld] = data[fld]; + master[fld] = scope[fld]; + } + if (form.fields[fld].type === 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) { + scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = + data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; + master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = + scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField]; + } + } - scope.clear = function(fld, associated) { - scope[fld] = ''; - scope[associated] = ''; - scope[form.name + '_form'][associated].$setValidity('awpassmatch', true); - scope[form.name + '_form'].$setDirty(); - } + if (!Empty(scope.user)) { + scope.owner = 'user'; + } else { + scope.owner = 'team'; + } + master.owner = scope.owner; + + for (i = 0; i < scope.credential_kind_options.length; i++) { + if (scope.credential_kind_options[i].value === data.kind) { + scope.kind = scope.credential_kind_options[i]; + break; + } + } + master.kind = scope.kind; + + switch (data.kind) { + case 'aws': + scope.access_key = data.username; + scope.secret_key = data.password; + master.access_key = scope.access_key; + master.secret_key = scope.secret_key; + break; + case 'ssh': + scope.ssh_password = data.password; + master.ssh_password = scope.ssh_password; + break; + case 'rax': + scope.api_key = data.password; + master.api_key = scope.api_key; + break; + } + + scope.$emit('credentialLoaded'); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, form, { + hdr: 'Error!', + msg: 'Failed to retrieve Credential: ' + $routeParams.id + '. GET status: ' + status + }); + }); + }); + + Wait('start'); + + GetChoices({ + scope: scope, + url: defaultUrl, + field: 'kind', + variable: 'credential_kind_options', + callback: 'choicesReadyCredential' + }); + + scope.showActivity = function () { + Stream({ + scope: scope + }); + }; + + // Save changes to the parent + scope.formSave = function () { + generator.clearApiErrors(); + FormSave({ + scope: scope, + mode: 'edit' + }); + }; + + // Handle Owner change + scope.ownerChange = function () { + OwnerChange({ + scope: scope + }); + }; + + // Handle Kind change + scope.kindChange = function () { + KindChange({ + scope: scope, + form: form, + reset: true + }); + }; + + // Cancel + scope.formReset = function () { + generator.reset(); + for (var fld in master) { + scope[fld] = master[fld]; + } + setAskCheckboxes(); + KindChange({ + scope: scope, + form: form, + reset: false + }); + OwnerChange({ + scope: scope + }); + }; + + // Related set: Add button + scope.add = function (set) { + $rootScope.flashMessage = null; + $location.path('/' + base + '/' + $routeParams.id + '/' + set + '/add'); + }; + + // Related set: Edit button + scope.edit = function (set, id) { + $rootScope.flashMessage = null; + $location.path('/' + base + '/' + $routeParams.id + '/' + set + '/' + id); + }; + + // Related set: Delete button + scope['delete'] = function (set, itm_id, name, title) { + $rootScope.flashMessage = null; + + var action = function () { + var url = defaultUrl + id + '/' + set + '/'; + Rest.setUrl(url); + Rest.post({ + id: itm_id, + disassociate: 1 + }) + .success(function () { + $('#prompt-modal').modal('hide'); + scope.search(form.related[set].iterator); + }) + .error(function (data, status) { + $('#prompt-modal').modal('hide'); + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Call to ' + url + ' failed. POST returned status: ' + status + }); + }); + }; + + Prompt({ + hdr: 'Delete', + body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?', + action: action + }); + + }; + + // Password change + scope.clearPWConfirm = function (fld) { + // If password value changes, make sure password_confirm must be re-entered + scope[fld] = ''; + scope[form.name + '_form'][fld].$setValidity('awpassmatch', false); + }; + + // Respond to 'Ask at runtime?' checkbox + scope.ask = function (fld, associated) { + if (scope[fld + '_ask']) { + $("#" + fld + "-clear-btn").attr("disabled", "disabled"); + scope[fld] = 'ASK'; + scope[associated] = ''; + scope[form.name + '_form'][associated].$setValidity('awpassmatch', true); + } else { + $("#" + fld + "-clear-btn").removeAttr("disabled"); + scope[fld] = ''; + scope[associated] = ''; + scope[form.name + '_form'][associated].$setValidity('awpassmatch', true); + } + }; + + scope.clear = function (fld, associated) { + scope[fld] = ''; + scope[associated] = ''; + scope[form.name + '_form'][associated].$setValidity('awpassmatch', true); + scope[form.name + '_form'].$setDirty(); + }; } -CredentialsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'CredentialForm', - 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', - 'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'Prompt', 'GetBasePath', 'GetChoices', - 'KindChange', 'UserList', 'TeamList', 'LookUpInit', 'Empty', 'OwnerChange', 'FormSave', 'Stream', - 'Wait']; - +CredentialsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'CredentialForm', + 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit', + 'ReturnToCaller', 'ClearScope', 'Prompt', 'GetBasePath', 'GetChoices', 'KindChange', 'UserList', 'TeamList', 'LookUpInit', + 'Empty', 'OwnerChange', 'FormSave', 'Stream', 'Wait' +]; \ No newline at end of file diff --git a/awx/ui/static/js/controllers/Home.js b/awx/ui/static/js/controllers/Home.js index 2851d17631..66b97e22ab 100644 --- a/awx/ui/static/js/controllers/Home.js +++ b/awx/ui/static/js/controllers/Home.js @@ -3,43 +3,55 @@ * * * Home.js - * + * * Controller functions for Home tab * */ 'use strict'; -function Home ($scope, $compile, $routeParams, $rootScope, $location, Wait, ObjectCount, JobStatus, InventorySyncStatus, SCMSyncStatus, +function Home($scope, $compile, $routeParams, $rootScope, $location, Wait, ObjectCount, JobStatus, InventorySyncStatus, SCMSyncStatus, ClearScope, Stream, Rest, GetBasePath, ProcessErrors, Button) { - - ClearScope('home'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. - + + ClearScope('home'); + + var buttons, html, e, waitCount, loadedCount; + // Add buttons to the top of the Home page. We're using lib/ansible/generator_helpers.js-> Buttons() // to build buttons dynamically and insure all styling and icons match the rest of the application. - var buttons = { + buttons = { refresh: { mode: 'all', awToolTip: "Refresh the page", ngClick: "refresh()" - }, + }, stream: { ngClick: "showActivity()", awToolTip: "View Activity Stream", mode: 'all' - } - }; - var html = Button({ btn: buttons.refresh, action: 'refresh', toolbar: true }); - html += Button({ btn: buttons.stream, action: 'stream', toolbar: true }); - var e = angular.element(document.getElementById('home-list-actions')); + } + }; + + html = Button({ + btn: buttons.refresh, + action: 'refresh', + toolbar: true + }); + + html += Button({ + btn: buttons.stream, + action: 'stream', + toolbar: true + }); + + e = angular.element(document.getElementById('home-list-actions')); e.html(html); $compile(e)($scope); - var waitCount = 4; - var loadedCount = 0; - - if (!$routeParams['login']) { + waitCount = 4; + loadedCount = 0; + + if (!$routeParams.login) { // If we're not logging in, start the Wait widget. Otherwise, it's already running. Wait('start'); } @@ -47,297 +59,366 @@ function Home ($scope, $compile, $routeParams, $rootScope, $location, Wait, Obje if ($scope.removeWidgetLoaded) { $scope.removeWidgetLoaded(); } - $scope.removeWidgetLoaded = $scope.$on('WidgetLoaded', function() { + $scope.removeWidgetLoaded = $scope.$on('WidgetLoaded', function () { // Once all the widgets report back 'loaded', turn off Wait widget - loadedCount++; - if ( loadedCount == waitCount ) { + loadedCount++; + if (loadedCount === waitCount) { Wait('stop'); } - }); + }); if ($scope.removeDashboardReady) { $scope.removeDashboardReady(); } - $scope.removeDashboardReady = $scope.$on('dashboardReady', function(e, data) { - JobStatus({ scope: $scope, target: 'container1', dashboard: data}); - InventorySyncStatus({ scope: $scope, target: 'container2', dashboard: data}); - SCMSyncStatus({ scope: $scope, target: 'container4', dashboard: data}); - ObjectCount({ scope: $scope, target: 'container3', dashboard: data}); + $scope.removeDashboardReady = $scope.$on('dashboardReady', function (e, data) { + JobStatus({ + scope: $scope, + target: 'container1', + dashboard: data }); - - $scope.showActivity = function() { Stream({ scope: $scope }); } + InventorySyncStatus({ + scope: $scope, + target: 'container2', + dashboard: data + }); + SCMSyncStatus({ + scope: $scope, + target: 'container4', + dashboard: data + }); + ObjectCount({ + scope: $scope, + target: 'container3', + dashboard: data + }); + }); - $scope.refresh = function() { + $scope.showActivity = function () { + Stream({ + scope: $scope + }); + }; + + $scope.refresh = function () { Wait('start'); loadedCount = 0; Rest.setUrl(GetBasePath('dashboard')); Rest.get() - .success( function(data, status, headers, config) { + .success(function (data) { $scope.$emit('dashboardReady', data); }) - .error ( function(data, status, headers, config) { + .error(function (data, status) { Wait('stop'); - ProcessErrors($scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to get dashboard: ' + status }); - }) - } - + ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get dashboard: ' + status }); + }); + }; + $scope.refresh(); - - } -Home.$inject=['$scope', '$compile', '$routeParams', '$rootScope', '$location', 'Wait', 'ObjectCount', 'JobStatus', 'InventorySyncStatus', - 'SCMSyncStatus', 'ClearScope', 'Stream', 'Rest', 'GetBasePath', 'ProcessErrors', 'Button']; +} + +Home.$inject = ['$scope', '$compile', '$routeParams', '$rootScope', '$location', 'Wait', 'ObjectCount', 'JobStatus', 'InventorySyncStatus', + 'SCMSyncStatus', 'ClearScope', 'Stream', 'Rest', 'GetBasePath', 'ProcessErrors', 'Button' +]; -function HomeGroups ($location, $routeParams, HomeGroupList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, +function HomeGroups($location, $routeParams, HomeGroupList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GetBasePath, SearchInit, PaginateInit, FormatDate, GetHostsStatusMsg, GetSyncStatusMsg, ViewUpdateStatus, Stream, GroupsEdit, Wait, Alert, Rest, Empty, InventoryUpdate, Find) { - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. - var generator = GenerateList; - var list = HomeGroupList; - var defaultUrl=GetBasePath('groups'); - - var scope = generator.inject(list, { mode: 'edit' }); - var base = $location.path().replace(/^\//,'').split('/')[0]; + var generator = GenerateList, + list = HomeGroupList, + defaultUrl = GetBasePath('groups'), + scope = generator.inject(list, { mode: 'edit' }), + opt; if (scope.removePostRefresh) { scope.removePostRefresh(); } - scope.removePostRefresh = scope.$on('PostRefresh', function() { - var hosts_status, update_status, last_update, stat; - for (var i=0; i < scope.home_groups.length; i++) { - - scope['home_groups'][i]['inventory_name'] = scope['home_groups'][i]['summary_fields']['inventory']['name']; + scope.removePostRefresh = scope.$on('PostRefresh', function () { + var i, hosts_status, stat; + for (i = 0; i < scope.home_groups.length; i++) { - stat = GetSyncStatusMsg({ + scope.home_groups[i].inventory_name = scope.home_groups[i].summary_fields.inventory.name; + + stat = GetSyncStatusMsg({ status: scope.home_groups[i].summary_fields.inventory_source.status - }); // from helpers/Groups.js - + }); // from helpers/Groups.js + hosts_status = GetHostsStatusMsg({ active_failures: scope.home_groups[i].hosts_with_active_failures, total_hosts: scope.home_groups[i].total_hosts, inventory_id: scope.home_groups[i].inventory, group_id: scope.home_groups[i].id - }); - - scope['home_groups'][i].status_class = stat['class'], - scope['home_groups'][i].status_tooltip = stat['tooltip'], - scope['home_groups'][i].launch_tooltip = stat['launch_tip'], - scope['home_groups'][i].launch_class = stat['launch_class'], - scope['home_groups'][i].hosts_status_tip = hosts_status['tooltip'], - scope['home_groups'][i].show_failures = hosts_status['failures'], - scope['home_groups'][i].hosts_status_class = hosts_status['class'], - - + }); + + scope.home_groups[i].status_class = stat['class']; + scope.home_groups[i].status_tooltip = stat.tooltip; + scope.home_groups[i].launch_tooltip = stat.launch_tip; + scope.home_groups[i].launch_class = stat.launch_class; + scope.home_groups[i].hosts_status_tip = hosts_status.tooltip; + scope.home_groups[i].show_failures = hosts_status.failures; + scope.home_groups[i].hosts_status_class = hosts_status['class']; scope.home_groups[i].status = scope.home_groups[i].summary_fields.inventory_source.status; - scope.home_groups[i].source = (scope.home_groups[i].summary_fields.inventory_source) ? + scope.home_groups[i].source = (scope.home_groups[i].summary_fields.inventory_source) ? scope.home_groups[i].summary_fields.inventory_source.source : null; - } - }); + }); - SearchInit({ scope: scope, set: 'home_groups', list: list, url: defaultUrl }); - PaginateInit({ scope: scope, list: list, url: defaultUrl }); + SearchInit({ + scope: scope, + set: 'home_groups', + list: list, + url: defaultUrl + }); + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl + }); // Process search params - if ($routeParams['name']) { + if ($routeParams.name) { scope[list.iterator + 'InputDisable'] = false; - scope[list.iterator + 'SearchValue'] = $routeParams['name']; + scope[list.iterator + 'SearchValue'] = $routeParams.name; scope[list.iterator + 'SearchField'] = 'name'; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['name'].label; + scope[list.iterator + 'SearchFieldLabel'] = list.fields.name.label; scope[list.iterator + 'SearchSelectValue'] = null; } - if ($routeParams['id']) { + if ($routeParams.id) { scope[list.iterator + 'InputDisable'] = false; - scope[list.iterator + 'SearchValue'] = $routeParams['id']; + scope[list.iterator + 'SearchValue'] = $routeParams.id; scope[list.iterator + 'SearchField'] = 'id'; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['id'].label; + scope[list.iterator + 'SearchFieldLabel'] = list.fields.id.label; scope[list.iterator + 'SearchSelectValue'] = null; } - if ($routeParams['has_active_failures']) { + if ($routeParams.has_active_failures) { scope[list.iterator + 'InputDisable'] = true; - scope[list.iterator + 'SearchValue'] = $routeParams['has_active_failures']; + scope[list.iterator + 'SearchValue'] = $routeParams.has_active_failures; scope[list.iterator + 'SearchField'] = 'has_active_failures'; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['has_active_failures'].label; - scope[list.iterator + 'SearchSelectValue'] = ($routeParams['has_active_failures'] == 'true') ? { value: 1 } : { value: 0 }; + scope[list.iterator + 'SearchFieldLabel'] = list.fields.has_active_failures.label; + scope[list.iterator + 'SearchSelectValue'] = ($routeParams.has_active_failures === 'true') ? { value: 1 } : { value: 0 }; } - if ($routeParams['status'] && !$routeParams['source']) { + if ($routeParams.status && !$routeParams.source) { scope[list.iterator + 'SearchField'] = 'status'; scope[list.iterator + 'SelectShow'] = true; - scope[list.iterator + 'SearchSelectOpts'] = list.fields['status'].searchOptions; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['status'].label.replace(/\/g,' '); - for (var opt in list.fields['status'].searchOptions) { - if (list.fields['status'].searchOptions[opt].value == $routeParams['status']) { - scope[list.iterator + 'SearchSelectValue'] = list.fields['status'].searchOptions[opt]; - break; - } + scope[list.iterator + 'SearchSelectOpts'] = list.fields.status.searchOptions; + scope[list.iterator + 'SearchFieldLabel'] = list.fields.status.label.replace(//g, ' '); + for (opt in list.fields.status.searchOptions) { + if (list.fields.status.searchOptions[opt].value === $routeParams.status) { + scope[list.iterator + 'SearchSelectValue'] = list.fields.status.searchOptions[opt]; + break; + } } } - if ($routeParams['source']) { + if ($routeParams.source) { scope[list.iterator + 'SearchField'] = 'source'; scope[list.iterator + 'SelectShow'] = true; - scope[list.iterator + 'SearchSelectOpts'] = list.fields['source'].searchOptions; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['source'].label.replace(/\/g,' '); - for (var opt in list.fields['source'].searchOptions) { - if (list.fields['source'].searchOptions[opt].value == $routeParams['source']) { - scope[list.iterator + 'SearchSelectValue'] = list.fields['source'].searchOptions[opt]; - break; - } + scope[list.iterator + 'SearchSelectOpts'] = list.fields.source.searchOptions; + scope[list.iterator + 'SearchFieldLabel'] = list.fields.source.label.replace(//g, ' '); + for (opt in list.fields.source.searchOptions) { + if (list.fields.source.searchOptions[opt].value === $routeParams.source) { + scope[list.iterator + 'SearchSelectValue'] = list.fields.source.searchOptions[opt]; + break; + } } - if ($routeParams['status']) { - scope[list.iterator + 'ExtraParms'] = '&inventory_source__status__icontains=' + $routeParams['status']; + if ($routeParams.status) { + scope[list.iterator + 'ExtraParms'] = '&inventory_source__status__icontains=' + $routeParams.status; } } - if ($routeParams['has_external_source']) { + if ($routeParams.has_external_source) { scope[list.iterator + 'SearchField'] = 'has_external_source'; - scope[list.iterator + 'SearchValue'] = list.fields['has_external_source'].searchValue; + scope[list.iterator + 'SearchValue'] = list.fields.has_external_source.searchValue; scope[list.iterator + 'InputDisable'] = true; scope[list.iterator + 'SearchType'] = 'in'; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['has_external_source'].label; + scope[list.iterator + 'SearchFieldLabel'] = list.fields.has_external_source.label; } - - scope.search(list.iterator); - - LoadBreadCrumbs(); - - scope.showActivity = function() { Stream({ scope: scope }); } - scope.editGroup = function(group_id, inventory_id) { - GroupsEdit({ scope: scope, group_id: group_id, inventory_id: inventory_id, groups_reload: false }); - } - - scope.viewUpdateStatus = function(id) { + scope.search(list.iterator); + + LoadBreadCrumbs(); + + scope.showActivity = function () { + Stream({ + scope: scope + }); + }; + + scope.editGroup = function (group_id, inventory_id) { + GroupsEdit({ + scope: scope, + group_id: group_id, + inventory_id: inventory_id, + groups_reload: false + }); + }; + + scope.viewUpdateStatus = function (id) { scope.groups = scope.home_groups; - ViewUpdateStatus({ scope: scope, tree_id: id }) - }; + ViewUpdateStatus({ + scope: scope, + tree_id: id + }); + }; // Launch inventory sync - scope.updateGroup = function(id) { - var group = Find({ list: scope.home_groups, key: 'id', val: id}); + scope.updateGroup = function (id) { + var group = Find({ list: scope.home_groups, key: 'id', val: id }); if (group) { if (Empty(group.source)) { // if no source, do nothing. - } - else if (group.status == 'updating') { + } else if (group.status === 'updating') { Alert('Update in Progress', 'The inventory update process is currently running for group ' + - scope.home_groups[i].name + '. Use the Refresh button to monitor the status.', 'alert-info'); - } - else { + group.name + '. Use the Refresh button to monitor the status.', 'alert-info'); + } else { Wait('start'); Rest.setUrl(group.related.inventory_source); Rest.get() - .success( function(data, status, headers, config) { + .success(function (data) { InventoryUpdate({ - scope: scope, + scope: scope, url: data.related.update, - group_name: data.summary_fields.group.name, + group_name: data.summary_fields.group.name, group_source: data.source, tree_id: group.id, group_id: group.id - }); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to retrieve inventory source: ' + group.related.inventory_source + - ' POST returned status: ' + status }); }); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, null, { hdr: 'Error!', + msg: 'Failed to retrieve inventory source: ' + group.related.inventory_source + ' POST returned status: ' + status + }); + }); } - } } + }; - scope.refresh = function() { scope.search(list.iterator, null, false, true); } + scope.refresh = function () { + scope.search(list.iterator, null, false, true); + }; - } +} -HomeGroups.$inject = [ '$location', '$routeParams', 'HomeGroupList', 'GenerateList', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', +HomeGroups.$inject = ['$location', '$routeParams', 'HomeGroupList', 'GenerateList', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GetBasePath', 'SearchInit', 'PaginateInit', 'FormatDate', 'GetHostsStatusMsg', 'GetSyncStatusMsg', 'ViewUpdateStatus', 'Stream', 'GroupsEdit', 'Wait', 'Alert', 'Rest', 'Empty', 'InventoryUpdate', 'Find' - ]; +]; -function HomeHosts ($location, $routeParams, HomeHostList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, +function HomeHosts($location, $routeParams, HomeHostList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GetBasePath, SearchInit, PaginateInit, FormatDate, SetStatus, ToggleHostEnabled, HostsEdit, Stream, Find, ShowJobSummary) { - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. - var generator = GenerateList; - var list = HomeHostList; - var defaultUrl=GetBasePath('hosts'); - - var scope = generator.inject(list, { mode: 'edit' }); - var base = $location.path().replace(/^\//,'').split('/')[0]; + var generator = GenerateList, + list = HomeHostList, + defaultUrl = GetBasePath('hosts'), + scope = generator.inject(list, { mode: 'edit' }); if (scope.removePostRefresh) { - scope.removePostRefresh(); + scope.removePostRefresh(); } - scope.removePostRefresh = scope.$on('PostRefresh', function() { - for (var i=0; i < scope.hosts.length; i++) { - scope['hosts'][i]['inventory_name'] = scope['hosts'][i]['summary_fields']['inventory']['name']; + scope.removePostRefresh = scope.$on('PostRefresh', function () { + for (var i = 0; i < scope.hosts.length; i++) { + scope.hosts[i].inventory_name = scope.hosts[i].summary_fields.inventory.name; //SetHostStatus(scope['hosts'][i]); - SetStatus({ scope: scope, host: scope['hosts'][i] }); + SetStatus({ + scope: scope, + host: scope.hosts[i] + }); } - }); + }); + + SearchInit({ + scope: scope, + set: 'hosts', + list: list, + url: defaultUrl + }); + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl + }); - SearchInit({ scope: scope, set: 'hosts', list: list, url: defaultUrl }); - PaginateInit({ scope: scope, list: list, url: defaultUrl }); - // Process search params - if ($routeParams['name']) { + if ($routeParams.name) { scope[HomeHostList.iterator + 'InputDisable'] = false; - scope[HomeHostList.iterator + 'SearchValue'] = $routeParams['name']; + scope[HomeHostList.iterator + 'SearchValue'] = $routeParams.name; scope[HomeHostList.iterator + 'SearchField'] = 'name'; - scope[HomeHostList.iterator + 'SearchFieldLabel'] = list.fields['name'].label; + scope[HomeHostList.iterator + 'SearchFieldLabel'] = list.fields.name.label; } - - if ($routeParams['id']) { + + if ($routeParams.id) { scope[HomeHostList.iterator + 'InputDisable'] = false; - scope[HomeHostList.iterator + 'SearchValue'] = $routeParams['id']; + scope[HomeHostList.iterator + 'SearchValue'] = $routeParams.id; scope[HomeHostList.iterator + 'SearchField'] = 'id'; - scope[HomeHostList.iterator + 'SearchFieldLabel'] = list.fields['id'].label; + scope[HomeHostList.iterator + 'SearchFieldLabel'] = list.fields.id.label; scope[HomeHostList.iterator + 'SearchSelectValue'] = null; } - if ($routeParams['has_active_failures']) { + if ($routeParams.has_active_failures) { scope[HomeHostList.iterator + 'InputDisable'] = true; - scope[HomeHostList.iterator + 'SearchValue'] = $routeParams['has_active_failures']; + scope[HomeHostList.iterator + 'SearchValue'] = $routeParams.has_active_failures; scope[HomeHostList.iterator + 'SearchField'] = 'has_active_failures'; - scope[HomeHostList.iterator + 'SearchFieldLabel'] = HomeHostList.fields['has_active_failures'].label; - scope[HomeHostList.iterator + 'SearchSelectValue'] = ($routeParams['has_active_failures'] == 'true') ? { value: 1 } : { value: 0 }; + scope[HomeHostList.iterator + 'SearchFieldLabel'] = HomeHostList.fields.has_active_failures.label; + scope[HomeHostList.iterator + 'SearchSelectValue'] = ($routeParams.has_active_failures === 'true') ? { value: 1 } : { value: 0 }; } - + scope.search(list.iterator); - + LoadBreadCrumbs(); - - scope.showActivity = function() { Stream({ scope: scope }); } - scope.toggle_host_enabled = function(id, sources) { ToggleHostEnabled({ host_id: id, external_source: sources, scope: scope }); } + scope.showActivity = function () { + Stream({ + scope: scope + }); + }; - scope.editHost = function(host_id, host_name) { - var host = Find({ list: scope.hosts, key: 'id', val: host_id }); + scope.toggle_host_enabled = function (id, sources) { + ToggleHostEnabled({ + host_id: id, + external_source: sources, + scope: scope + }); + }; + + scope.editHost = function (host_id) { + var host = Find({ + list: scope.hosts, + key: 'id', + val: host_id + }); if (host) { - HostsEdit({ scope: scope, host_id: host_id, inventory_id: host.inventory, group_id: null, hostsReload: false }); - } + HostsEdit({ + scope: scope, + host_id: host_id, + inventory_id: host.inventory, + group_id: null, + hostsReload: false + }); } + }; - scope.showJobSummary = function(job_id) { - ShowJobSummary({ job_id: job_id }); - } + scope.showJobSummary = function (job_id) { + ShowJobSummary({ + job_id: job_id + }); + }; - } +} -HomeHosts.$inject = [ '$location', '$routeParams', 'HomeHostList', 'GenerateList', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', +HomeHosts.$inject = ['$location', '$routeParams', 'HomeHostList', 'GenerateList', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GetBasePath', 'SearchInit', 'PaginateInit', 'FormatDate', 'SetStatus', 'ToggleHostEnabled', 'HostsEdit', 'Stream', 'Find', 'ShowJobSummary' - ]; +]; \ No newline at end of file diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js index 64de7d27ac..35cf1f183e 100644 --- a/awx/ui/static/js/controllers/Inventories.js +++ b/awx/ui/static/js/controllers/Inventories.js @@ -3,61 +3,78 @@ * * * Inventories.js - * + * * Controller functions for the Inventory model. * */ - + 'use strict'; -function InventoriesList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, InventoryList, - GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, - ClearScope, ProcessErrors, GetBasePath, Wait, Stream, EditInventoryProperties) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. - var list = InventoryList; - var defaultUrl = GetBasePath('inventory'); - var view = GenerateList; - var paths = $location.path().replace(/^\//,'').split('/'); - var mode = (paths[0] == 'inventories') ? 'edit' : 'select'; // if base path 'users', we're here to add/edit users - var scope = view.inject(InventoryList, { mode: mode }); // Inject our view +function InventoriesList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, InventoryList, + GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, + GetBasePath, Wait, Stream, EditInventoryProperties) { + ClearScope('htmlTemplate'); + + var list = InventoryList, + defaultUrl = GetBasePath('inventory'), + view = GenerateList, + paths = $location.path().replace(/^\//, '').split('/'), + mode = (paths[0] === 'inventories') ? 'edit' : 'select', // if base path 'users', we're here to add/edit users + scope = view.inject(InventoryList, { mode: mode }); + $rootScope.flashMessage = null; - SearchInit({ scope: scope, set: 'inventories', list: list, url: defaultUrl }); - PaginateInit({ scope: scope, list: list, url: defaultUrl }); - - if ($routeParams['name']) { + SearchInit({ + scope: scope, + set: 'inventories', + list: list, + url: defaultUrl + }); + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl + }); + + if ($routeParams.name) { scope[InventoryList.iterator + 'InputDisable'] = false; - scope[InventoryList.iterator + 'SearchValue'] = $routeParams['name']; + scope[InventoryList.iterator + 'SearchValue'] = $routeParams.name; scope[InventoryList.iterator + 'SearchField'] = 'name'; - scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields['name'].label; + scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.name.label; scope[InventoryList.iterator + 'SearchSelectValue'] = null; } - if ($routeParams['has_active_failures']) { + if ($routeParams.has_active_failures) { scope[InventoryList.iterator + 'InputDisable'] = true; - scope[InventoryList.iterator + 'SearchValue'] = $routeParams['has_active_failures']; + scope[InventoryList.iterator + 'SearchValue'] = $routeParams.has_active_failures; scope[InventoryList.iterator + 'SearchField'] = 'has_active_failures'; - scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields['has_active_failures'].label; - scope[InventoryList.iterator + 'SearchSelectValue'] = ($routeParams['has_active_failures'] == 'true') ? { value: 1 } : { value: 0 }; + scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.has_active_failures.label; + scope[InventoryList.iterator + 'SearchSelectValue'] = ($routeParams.has_active_failures === 'true') ? { + value: 1 + } : { + value: 0 + }; } - if ($routeParams['has_inventory_sources']) { + if ($routeParams.has_inventory_sources) { scope[InventoryList.iterator + 'InputDisable'] = true; - scope[InventoryList.iterator + 'SearchValue'] = $routeParams['has_inventory_sources']; + scope[InventoryList.iterator + 'SearchValue'] = $routeParams.has_inventory_sources; scope[InventoryList.iterator + 'SearchField'] = 'has_inventory_sources'; - scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields['has_inventory_sources'].label; - scope[InventoryList.iterator + 'SearchSelectValue'] = ($routeParams['has_inventory_sources'] == 'true') ? { value: 1 } : { value: 0 }; + scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.has_inventory_sources.label; + scope[InventoryList.iterator + 'SearchSelectValue'] = ($routeParams.has_inventory_sources === 'true') ? { + value: 1 + } : { + value: 0 + }; } - if ($routeParams['inventory_sources_with_failures']) { + if ($routeParams.inventory_sources_with_failures) { // pass a value of true, however this field actually contains an integer value scope[InventoryList.iterator + 'InputDisable'] = true; - scope[InventoryList.iterator + 'SearchValue'] = $routeParams['inventory_sources_with_failures']; + scope[InventoryList.iterator + 'SearchValue'] = $routeParams.inventory_sources_with_failures; scope[InventoryList.iterator + 'SearchField'] = 'inventory_sources_with_failures'; - scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields['inventory_sources_with_failures'].label; + scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.inventory_sources_with_failures.label; scope[InventoryList.iterator + 'SearchType'] = 'gtzero'; } @@ -66,282 +83,300 @@ function InventoriesList ($scope, $rootScope, $location, $log, $routeParams, Res LoadBreadCrumbs(); if (scope.removePostRefresh) { - scope.removePostRefresh(); + scope.removePostRefresh(); } - scope.removePostRefresh = scope.$on('PostRefresh', function() { + scope.removePostRefresh = scope.$on('PostRefresh', function () { //If we got here by deleting an inventory, stop the spinner and cleanup events Wait('stop'); $('#prompt-modal').off(); - for (var i=0; i < scope.inventories.length; i++) { - + for (var i = 0; i < scope.inventories.length; i++) { + // Set values for Failed Hosts column //scope.inventories[i].failed_hosts = scope.inventories[i].hosts_with_active_failures + ' / ' + scope.inventories[i].total_hosts; - + if (scope.inventories[i].hosts_with_active_failures > 0) { - scope.inventories[i].failed_hosts_tip = scope.inventories[i].hosts_with_active_failures + - ( (scope.inventories[i].hosts_with_active_failures == 1) ? ' host' : ' hosts' ) + ' with job failures. Click to view details.'; - scope.inventories[i].failed_hosts_link = '/#/inventories/' + scope.inventories[i].id + '/'; - scope.inventories[i].failed_hosts_class = 'true'; - } - else { - if (scope.inventories[i].total_hosts == 0) { - // no hosts - scope.inventories[i].failed_hosts_tip = "No hosts defined. Click to add."; - scope.inventories[i].failed_hosts_link = '/#/inventories/' + scope.inventories[i].id + '/'; - scope.inventories[i].failed_hosts_class = 'na'; - } - else { - // many hosts with 0 failures - scope.inventories[i].failed_hosts_tip = scope.inventories[i].total_hosts + - ( (scope.inventories[i].total_hosts > 1) ? ' hosts' : ' host' ) + " with no job failures. Click to view details."; - scope.inventories[i].failed_hosts_link = '/#/inventories/' + scope.inventories[i].id + '/'; - scope.inventories[i].failed_hosts_class = 'false'; - } + scope.inventories[i].failed_hosts_tip = scope.inventories[i].hosts_with_active_failures + + ((scope.inventories[i].hosts_with_active_failures === 1) ? ' host' : ' hosts') + ' with job failures. Click to view details.'; + scope.inventories[i].failed_hosts_link = '/#/inventories/' + scope.inventories[i].id + '/'; + scope.inventories[i].failed_hosts_class = 'true'; + } else { + if (scope.inventories[i].total_hosts === 0) { + // no hosts + scope.inventories[i].failed_hosts_tip = "No hosts defined. Click to add."; + scope.inventories[i].failed_hosts_link = '/#/inventories/' + scope.inventories[i].id + '/'; + scope.inventories[i].failed_hosts_class = 'na'; + } else { + // many hosts with 0 failures + scope.inventories[i].failed_hosts_tip = scope.inventories[i].total_hosts + + ((scope.inventories[i].total_hosts > 1) ? ' hosts' : ' host') + " with no job failures. Click to view details."; + scope.inventories[i].failed_hosts_link = '/#/inventories/' + scope.inventories[i].id + '/'; + scope.inventories[i].failed_hosts_class = 'false'; + } } // Set values for Status column - scope.inventories[i].status = scope.inventories[i].inventory_sources_with_failures + ' / ' + scope.inventories[i].total_inventory_sources; + scope.inventories[i].status = scope.inventories[i].inventory_sources_with_failures + ' / ' + scope.inventories[i].total_inventory_sources; if (scope.inventories[i].inventory_sources_with_failures > 0) { - scope.inventories[i].status_tip = scope.inventories[i].inventory_sources_with_failures + ' cloud ' + - ( (scope.inventories[i].inventory_sources_with_failures == 1) ? 'source' : 'sources' ) + - ' with failures. Click to view details.'; - scope.inventories[i].status_link = '/#/inventories/' + scope.inventories[i].id + '/'; - scope.inventories[i].status_class = 'failed'; - } - else { - if (scope.inventories[i].total_inventory_sources == 0) { - // no groups are reporting a source - scope.inventories[i].status_tip = "Not synced with a cloud source. Click to edit."; - scope.inventories[i].status_link = '/#/inventories/' + scope.inventories[i].id + '/'; - scope.inventories[i].status_class = 'na'; - } - else { - // many hosts with 0 failures - scope.inventories[i].status_tip = scope.inventories[i].total_inventory_sources + - ' cloud ' + ( (scope.inventories[i].total_inventory_sources > 1) ? 'sources' : 'source' ) + - ' with no failures. Click to view details.'; - scope.inventories[i].status_link = '/#/inventories/' + scope.inventories[i].id + '/'; - scope.inventories[i].status_class = 'successful'; - } + scope.inventories[i].status_tip = scope.inventories[i].inventory_sources_with_failures + ' cloud ' + + ((scope.inventories[i].inventory_sources_with_failures === 1) ? 'source' : 'sources') + + ' with failures. Click to view details.'; + scope.inventories[i].status_link = '/#/inventories/' + scope.inventories[i].id + '/'; + scope.inventories[i].status_class = 'failed'; + } else { + if (scope.inventories[i].total_inventory_sources === 0) { + // no groups are reporting a source + scope.inventories[i].status_tip = "Not synced with a cloud source. Click to edit."; + scope.inventories[i].status_link = '/#/inventories/' + scope.inventories[i].id + '/'; + scope.inventories[i].status_class = 'na'; + } else { + // many hosts with 0 failures + scope.inventories[i].status_tip = scope.inventories[i].total_inventory_sources + + ' cloud ' + ((scope.inventories[i].total_inventory_sources > 1) ? 'sources' : 'source') + + ' with no failures. Click to view details.'; + scope.inventories[i].status_link = '/#/inventories/' + scope.inventories[i].id + '/'; + scope.inventories[i].status_class = 'successful'; + } } } - }); + }); if (scope.removeRefreshInventories) { scope.removeRefreshInventories(); } - scope.removeRefreshInventories = scope.$on('RefreshInventories', function() { + scope.removeRefreshInventories = scope.$on('RefreshInventories', function () { // Reflect changes after inventory properties edit completes scope.search(list.iterator); + }); + + scope.showActivity = function () { + Stream({ + scope: scope }); - - scope.showActivity = function() { Stream({ scope: scope }); } + }; - scope.editInventoryProperties = function(inventory_id) { - EditInventoryProperties({ scope: scope, inventory_id: inventory_id }); - } + scope.editInventoryProperties = function (inventory_id) { + EditInventoryProperties({ + scope: scope, + inventory_id: inventory_id + }); + }; - scope.addInventory = function() { + scope.addInventory = function () { $location.path($location.path() + '/add'); - } + }; - scope.editInventory = function(id) { + scope.editInventory = function (id) { $location.path($location.path() + '/' + id); - } - - scope.deleteInventory = function(id, name) { - - var action = function() { + }; + + scope.deleteInventory = function (id, name) { + + var action = function () { var url = defaultUrl + id + '/'; - $('#prompt-modal').on('hidden.bs.modal', function() { + $('#prompt-modal').on('hidden.bs.modal', function () { Wait('start'); - }); + }); $('#prompt-modal').modal('hide'); Rest.setUrl(url); Rest.destroy() - .success( function(data, status, headers, config) { - scope.search(list.iterator); - }) - .error( function(data, status, headers, config) { + .success(function () { + scope.search(list.iterator); + }) + .error(function (data, status) { Wait('stop'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); - }); - }; + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status + }); + }); + }; - Prompt({ hdr: 'Delete', - body: 'Are you sure you want to delete ' + name + '?', - action: action - }); - } - - scope.lookupOrganization = function(organization_id) { + Prompt({ + hdr: 'Delete', + body: 'Are you sure you want to delete ' + name + '?', + action: action + }); + }; + + scope.lookupOrganization = function (organization_id) { Rest.setUrl(GetBasePath('organizations') + organization_id + '/'); Rest.get() - .success( function(data, status, headers, config) { + .success(function (data) { return data.name; - }); - } + }); + }; - // Failed jobs link. Go to the jobs tabs, find all jobs for the inventory and sort by status - scope.viewJobs = function(id) { + // Failed jobs link. Go to the jobs tabs, find all jobs for the inventory and sort by status + scope.viewJobs = function (id) { $location.url('/jobs/?inventory__int=' + id); - } + }; - scope.viewFailedJobs = function(id) { + scope.viewFailedJobs = function (id) { $location.url('/jobs/?inventory__int=' + id + '&status=failed'); + }; +} + +InventoriesList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'InventoryList', 'GenerateList', + 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', + 'GetBasePath', 'Wait', 'Stream', 'EditInventoryProperties' +]; + + +function InventoriesAdd($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm, + GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, + GenerateList, OrganizationList, SearchInit, PaginateInit, LookUpInit, GetBasePath, + ParseTypeChange, Wait) { + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. + + // Inject dynamic view + var defaultUrl = GetBasePath('inventory'), + form = InventoryForm, + generator = GenerateForm, + scope; + + form.well = true; + form.formLabelSize = null; + form.formFieldSize = null; + + scope = generator.inject(form, { + mode: 'add', + related: false + }); + scope.inventoryParseType = 'yaml'; + + generator.reset(); + LoadBreadCrumbs(); + ParseTypeChange(scope, 'inventory_variables', 'inventoryParseType'); + + LookUpInit({ + scope: scope, + form: form, + current_item: ($routeParams.organization_id) ? $routeParams.organization_id : null, + list: OrganizationList, + field: 'organization' + }); + + // Save + scope.formSave = function () { + generator.clearApiErrors(); + Wait('start'); + try { + var fld, json_data, data; + + // Make sure we have valid variable data + if (scope.inventoryParseType === 'json') { + json_data = JSON.parse(scope.inventory_variables); //make sure JSON parses + } else { + json_data = jsyaml.load(scope.inventory_variables); //parse yaml + } + + // Make sure our JSON is actually an object + if (typeof json_data !== 'object') { + throw "failed to return an object!"; + } + + data = {}; + for (fld in form.fields) { + if (fld !== 'inventory_variables') { + if (form.fields[fld].realName) { + data[form.fields[fld].realName] = scope[fld]; + } else { + data[fld] = scope[fld]; + } + } + } + + Rest.setUrl(defaultUrl); + Rest.post(data) + .success(function (data) { + var inventory_id = data.id; + if (scope.inventory_variables) { + Rest.setUrl(data.related.variable_data); + Rest.put(json_data) + .success(function () { + Wait('stop'); + $location.path('/inventories/' + inventory_id + '/'); + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, null, { hdr: 'Error!', + msg: 'Failed to add inventory varaibles. PUT returned status: ' + status + }); + }); + } else { + Wait('stop'); + $location.path('/inventories/' + inventory_id + '/'); + } + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, form, { + hdr: 'Error!', + msg: 'Failed to add new inventory. Post returned status: ' + status + }); + }); + } catch (err) { + Wait('stop'); + Alert("Error", "Error parsing inventory variables. Parser returned: " + err); } + + }; + + // Reset + scope.formReset = function () { + // Defaults + generator.reset(); + }; } -InventoriesList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'InventoryList', 'GenerateList', - 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', - 'GetBasePath', 'Wait', 'Stream', 'EditInventoryProperties']; - - -function InventoriesAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, - GenerateList, OrganizationList, SearchInit, PaginateInit, LookUpInit, GetBasePath, - ParseTypeChange, Wait) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. - - // Inject dynamic view - var defaultUrl = GetBasePath('inventory'); - var form = InventoryForm; - var generator = GenerateForm; - - form.well = true, - form.formLabelSize = null; - form.formFieldSize = null; - - var scope = generator.inject(form, {mode: 'add', related: false}); - scope.inventoryParseType = 'yaml'; - - generator.reset(); - LoadBreadCrumbs(); - ParseTypeChange(scope,'inventory_variables', 'inventoryParseType'); - - LookUpInit({ - scope: scope, - form: form, - current_item: ($routeParams.organization_id) ? $routeParams.organization_id : null, - list: OrganizationList, - field: 'organization' - }); - - // Save - scope.formSave = function() { - generator.clearApiErrors(); - Wait('start'); - try { - // Make sure we have valid variable data - if (scope.inventoryParseType == 'json') { - var json_data = JSON.parse(scope.inventory_variables); //make sure JSON parses - } - else { - var json_data = jsyaml.load(scope.inventory_variables); //parse yaml - } - - // Make sure our JSON is actually an object - if (typeof json_data !== 'object') { - throw "failed to return an object!"; - } - - var data = {} - for (var fld in form.fields) { - if (fld != 'inventory_variables') { - if (form.fields[fld].realName) { - data[form.fields[fld].realName] = scope[fld]; - } - else { - data[fld] = scope[fld]; - } - } - } - - Rest.setUrl(defaultUrl); - Rest.post(data) - .success( function(data, status, headers, config) { - var inventory_id = data.id; - if (scope.inventory_variables) { - Rest.setUrl(data.related.variable_data); - Rest.put(json_data) - .success( function(data, status, headers, config) { - Wait('stop'); - $location.path('/inventories/' + inventory_id + '/'); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to add inventory varaibles. PUT returned status: ' + status }); - }); - } - else { - Wait('stop'); - $location.path('/inventories/' + inventory_id + '/'); - } - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to add new inventory. Post returned status: ' + status }); - }); - } - catch(err) { - Wait('stop'); - Alert("Error", "Error parsing inventory variables. Parser returned: " + err); - } - - }; - - // Reset - scope.formReset = function() { - // Defaults - generator.reset(); - }; -} - -InventoriesAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm', 'GenerateForm', - 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList', - 'OrganizationList', 'SearchInit', 'PaginateInit', 'LookUpInit', 'GetBasePath', 'ParseTypeChange', 'Wait' - ]; +InventoriesAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm', 'GenerateForm', + 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList', + 'OrganizationList', 'SearchInit', 'PaginateInit', 'LookUpInit', 'GetBasePath', 'ParseTypeChange', 'Wait' +]; -function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateList, ClearScope, InventoryGroups, InventoryHosts, BuildTree, Wait, - GetSyncStatusMsg, InjectHosts, HostsReload, GroupsAdd, GroupsEdit, GroupsDelete, Breadcrumbs, LoadBreadCrumbs, Empty, - Rest, ProcessErrors, InventoryUpdate, Alert, ToggleChildren, ViewUpdateStatus, GroupsCancelUpdate, Find, - HostsCreate, EditInventoryProperties, HostsEdit, HostsDelete, ToggleHostEnabled, CopyMoveGroup, CopyMoveHost, - Stream, GetBasePath, ShowJobSummary, ApplyEllipsis, WatchInventoryWindowResize, HelpDialog, InventoryGroupsHelp, - Store) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. +function InventoriesEdit($scope, $location, $routeParams, $compile, GenerateList, ClearScope, InventoryGroups, InventoryHosts, BuildTree, Wait, + GetSyncStatusMsg, InjectHosts, HostsReload, GroupsAdd, GroupsEdit, GroupsDelete, Breadcrumbs, LoadBreadCrumbs, Empty, + Rest, ProcessErrors, InventoryUpdate, Alert, ToggleChildren, ViewUpdateStatus, GroupsCancelUpdate, Find, + HostsCreate, EditInventoryProperties, HostsEdit, HostsDelete, ToggleHostEnabled, CopyMoveGroup, CopyMoveHost, + Stream, GetBasePath, ShowJobSummary, ApplyEllipsis, WatchInventoryWindowResize, HelpDialog, InventoryGroupsHelp, + Store) { + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. + + var generator = GenerateList, + list = InventoryGroups; - var generator = GenerateList; - var list = InventoryGroups; - var base = $location.path().replace(/^\//,'').split('/')[0]; - $scope.inventory_id = $routeParams.inventory_id; - - LoadBreadCrumbs({ path: $location.path(), title: '{{ inventory_name }}' }); + + LoadBreadCrumbs({ + path: $location.path(), + title: '{{ inventory_name }}' + }); // After the tree data loads for the first time, generate the groups and hosts lists if ($scope.removeGroupTreeLoaded) { $scope.removeGroupTreeLoaded(); } - $scope.removeGroupTreeLoaded = $scope.$on('GroupTreeLoaded', function(e, inventory_name, groups) { + $scope.removeGroupTreeLoaded = $scope.$on('GroupTreeLoaded', function (event, inventory_name, groups) { // Add breadcrumbs - var e = angular.element(document.getElementById('breadcrumbs')); + var e, inventoryAutoHelp; + e = angular.element(document.getElementById('breadcrumbs')); e.html(Breadcrumbs({ list: list, mode: 'edit' })); $compile(e)($scope); - + // Add groups view - generator.inject(list, { mode: 'edit', id: 'groups-container', breadCrumbs: false, searchSize: 'col-lg-5 col-md-5 col-sm-5' }); + generator.inject(list, { + mode: 'edit', + id: 'groups-container', + breadCrumbs: false, + searchSize: 'col-lg-5 col-md-5 col-sm-5' + }); $scope.groups = groups; $scope.inventory_name = inventory_name; @@ -352,235 +387,324 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis $scope.groups[0].selected_class = 'selected'; $scope.groups[0].active_class = 'active-row'; $scope.selected_group_name = $scope.groups[0].name; - } - else { + } else { $scope.selected_tree_id = null; $scope.selected_group_id = null; - } + } // Add hosts view $scope.show_failures = false; - InjectHosts({ scope: $scope, inventory_id: $scope.inventory_id, tree_id: $scope.selected_tree_id, group_id: $scope.selected_group_id }); - + InjectHosts({ + scope: $scope, + inventory_id: $scope.inventory_id, + tree_id: $scope.selected_tree_id, + group_id: $scope.selected_group_id + }); + // As the window shrinks and expands, apply ellipsis - setTimeout(function() { + setTimeout(function () { // Hack to keep group name from slipping to a new line - $('#groups_table .name-column').each( function() { - var td_width = $(this).width(); - var level_width = $(this).find('.level').width(); - var level_padding = parseInt($(this).find('.level').css('padding-left').replace(/px/,'')); - var level = level_width + level_padding; - var pct = ( 100 - Math.ceil((level / td_width)*100) ) + '%'; - $(this).find('.group-name').css({ width: pct }); + $('#groups_table .name-column').each(function () { + var td_width, level_width, level_padding, level, pct; + td_width = $(this).width(); + level_width = $(this).find('.level').width(); + level_padding = parseInt($(this).find('.level').css('padding-left').replace(/px/, '')); + level = level_width + level_padding; + pct = (100 - Math.ceil((level / td_width) * 100)) + '%'; + $(this).find('.group-name').css({ + width: pct }); + }); ApplyEllipsis('#groups_table .group-name a'); ApplyEllipsis('#hosts_table .host-name a'); - }, 2500); //give the window time to display + }, 2500); //give the window time to display WatchInventoryWindowResize(); - - var inventoryAutoHelp = Store('inventoryAutoHelp'); + + inventoryAutoHelp = Store('inventoryAutoHelp'); if (inventoryAutoHelp !== 'off' && $scope.autoShowGroupHelp) { - $scope.showGroupHelp({ autoShow: true }); + $scope.showGroupHelp({ + autoShow: true + }); } - }); - + }); + // Called after tree data is reloaded on refresh button click. if ($scope.removeGroupTreeRefreshed) { $scope.removeGroupTreeRefreshed(); } - $scope.removeGroupTreeRefreshed = $scope.$on('GroupTreeRefreshed', function(e, inventory_name, groups) { + $scope.removeGroupTreeRefreshed = $scope.$on('GroupTreeRefreshed', function () { // Reapply ellipsis to groups - setTimeout(function() { ApplyEllipsis('#groups_table .group-name a'); }, 2500); + setTimeout(function () { + ApplyEllipsis('#groups_table .group-name a'); + }, 2500); // Reselect the preveiously selected group node, causing host view to refresh. $scope.showHosts($scope.selected_tree_id, $scope.selected_group_id, false); - }); - + }); + // Group was deleted. Now we need to refresh the group view. if ($scope.removeGroupDeleteCompleted) { $scope.removeGroupDeleteCompleted(); } - $scope.removeGroupDeleteCompleted = $scope.$on('GroupDeleteCompleted', function(e) { + $scope.removeGroupDeleteCompleted = $scope.$on('GroupDeleteCompleted', function () { $scope.selected_tree_id = 1; $scope.selected_group_id = null; - BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: true }); + BuildTree({ + scope: $scope, + inventory_id: $scope.inventory_id, + refresh: true }); + }); // Respond to a group drag-n-drop if ($scope.removeCopMoveGroup) { $scope.removeCopyMoveGroup(); } - $scope.removeCopyMoveGroup = $scope.$on('CopyMoveGroup', function(e, inbound_tree_id, target_tree_id) { - CopyMoveGroup({ scope: $scope, target_tree_id: target_tree_id, inbound_tree_id: inbound_tree_id }); + $scope.removeCopyMoveGroup = $scope.$on('CopyMoveGroup', function (e, inbound_tree_id, target_tree_id) { + CopyMoveGroup({ + scope: $scope, + target_tree_id: target_tree_id, + inbound_tree_id: inbound_tree_id }); + }); // Respond to a host drag-n-drop if ($scope.removeCopMoveHost) { $scope.removeCopyMoveHost(); } - $scope.removeCopyMoveHost = $scope.$on('CopyMoveHost', function(e, target_tree_id, host_id) { - CopyMoveHost({ scope: $scope, target_tree_id: target_tree_id, host_id: host_id }); + $scope.removeCopyMoveHost = $scope.$on('CopyMoveHost', function (e, target_tree_id, host_id) { + CopyMoveHost({ + scope: $scope, + target_tree_id: target_tree_id, + host_id: host_id }); + }); - $scope.showHosts = function(tree_id, group_id, show_failures) { + $scope.showHosts = function (tree_id, group_id, show_failures) { // Clicked on group if (tree_id !== null) { Wait('start'); - $scope.selected_tree_id = tree_id; + $scope.selected_tree_id = tree_id; $scope.selected_group_id = group_id; $scope.hosts = []; - $scope.show_failures = show_failures; // turn on failed hosts filter in hosts view - for (var i=0; i < $scope.groups.length; i++) { - if ($scope.groups[i].id == tree_id) { + $scope.show_failures = show_failures; // turn on failed hosts filter in hosts view + for (var i = 0; i < $scope.groups.length; i++) { + if ($scope.groups[i].id === tree_id) { $scope.groups[i].selected_class = 'selected'; $scope.groups[i].active_class = 'active-row'; $scope.selected_group_name = $scope.groups[i].name; - } - else { + } else { $scope.groups[i].selected_class = ''; $scope.groups[i].active_class = ''; } } - HostsReload({ scope: $scope, group_id: group_id, tree_id: tree_id, inventory_id: $scope.inventory_id }); - } - else { + HostsReload({ + scope: $scope, + group_id: group_id, + tree_id: tree_id, + inventory_id: $scope.inventory_id + }); + } else { Wait('stop'); } - } + }; - $scope.createGroup = function() { - GroupsAdd({ scope: $scope, inventory_id: $scope.inventory_id, group_id: $scope.selected_group_id }); - } - - $scope.editGroup = function(group_id, tree_id) { - GroupsEdit({ scope: $scope, inventory_id: $scope.inventory_id, group_id: group_id, tree_id: tree_id, groups_reload: true }); - } + $scope.createGroup = function () { + GroupsAdd({ + scope: $scope, + inventory_id: $scope.inventory_id, + group_id: $scope.selected_group_id + }); + }; + + $scope.editGroup = function (group_id, tree_id) { + GroupsEdit({ + scope: $scope, + inventory_id: $scope.inventory_id, + group_id: group_id, + tree_id: tree_id, + groups_reload: true + }); + }; // Launch inventory sync - $scope.updateGroup = function(id) { - var group = Find({ list: $scope.groups, key: 'id', val: id}); + $scope.updateGroup = function (id) { + var group = Find({ list: $scope.groups, key: 'id', val: id }); if (group) { if (Empty(group.source)) { // if no source, do nothing. - } - else if (group.status == 'updating') { + } else if (group.status === 'updating') { Alert('Update in Progress', 'The inventory update process is currently running for group ' + - $scope.groups[i].name + '. Use the Refresh button to monitor the status.', 'alert-info'); - } - else { + group.name + '. Use the Refresh button to monitor the status.', 'alert-info'); + } else { Wait('start'); Rest.setUrl(group.related.inventory_source); Rest.get() - .success( function(data, status, headers, config) { + .success(function (data) { InventoryUpdate({ - scope: $scope, + scope: $scope, url: data.related.update, - group_name: data.summary_fields.group.name, + group_name: data.summary_fields.group.name, group_source: data.source, tree_id: group.id, group_id: group.group_id - }); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to retrieve inventory source: ' + group.related.inventory_source + - ' POST returned status: ' + status }); }); + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve inventory source: ' + + group.related.inventory_source + ' POST returned status: ' + status }); + }); } - } } + }; - $scope.cancelUpdate = function(tree_id) { - GroupsCancelUpdate({ scope: $scope, tree_id: tree_id }); - } - - $scope.toggle = function(tree_id) { + $scope.cancelUpdate = function (tree_id) { + GroupsCancelUpdate({ + scope: $scope, + tree_id: tree_id + }); + }; + + $scope.toggle = function (tree_id) { // Expand/collapse nodes - ToggleChildren({ scope: $scope, list: list, id: tree_id }); - } + ToggleChildren({ + scope: $scope, + list: list, + id: tree_id + }); + }; - $scope.refreshGroups = function(tree_id, group_id) { + $scope.refreshGroups = function (tree_id, group_id) { // Refresh the tree data when refresh button cicked if (tree_id) { $scope.selected_tree_id = tree_id; $scope.selected_group_id = group_id; } - BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: true }); - } + BuildTree({ + scope: $scope, + inventory_id: $scope.inventory_id, + refresh: true + }); + }; - $scope.viewUpdateStatus = function(tree_id, group_id) { - ViewUpdateStatus({ scope: $scope, tree_id: tree_id, group_id: group_id }); - } + $scope.viewUpdateStatus = function (tree_id, group_id) { + ViewUpdateStatus({ + scope: $scope, + tree_id: tree_id, + group_id: group_id + }); + }; - $scope.deleteGroup = function(tree_id, group_id) { - GroupsDelete({ scope: $scope, tree_id: tree_id, group_id: group_id, inventory_id: $scope.inventory_id }); - } + $scope.deleteGroup = function (tree_id, group_id) { + GroupsDelete({ + scope: $scope, + tree_id: tree_id, + group_id: group_id, + inventory_id: $scope.inventory_id + }); + }; - $scope.createHost = function() { - HostsCreate({ scope: $scope }); - } - - $scope.editInventoryProperties = function() { - EditInventoryProperties({ scope: $scope, inventory_id: $scope.inventory_id }); - } + $scope.createHost = function () { + HostsCreate({ + scope: $scope + }); + }; - $scope.editHost = function(host_id) { - HostsEdit({ scope: $scope, host_id: host_id, inventory_id: $scope.inventory_id }); - } + $scope.editInventoryProperties = function () { + EditInventoryProperties({ + scope: $scope, + inventory_id: $scope.inventory_id + }); + }; - $scope.deleteHost = function(host_id, host_name) { - HostsDelete({ scope: $scope, host_id: host_id, host_name: host_name }); - } + $scope.editHost = function (host_id) { + HostsEdit({ + scope: $scope, + host_id: host_id, + inventory_id: $scope.inventory_id + }); + }; - $scope.toggleHostEnabled = function(host_id, external_source) { - ToggleHostEnabled({ scope: $scope, host_id: host_id, external_source: external_source }); - } + $scope.deleteHost = function (host_id, host_name) { + HostsDelete({ + scope: $scope, + host_id: host_id, + host_name: host_name + }); + }; - $scope.showGroupActivity = function() { + $scope.toggleHostEnabled = function (host_id, external_source) { + ToggleHostEnabled({ + scope: $scope, + host_id: host_id, + external_source: external_source + }); + }; + + $scope.showGroupActivity = function () { var url, title, group; if ($scope.selected_group_id) { - group = Find({ list: $scope.groups, key: 'id', val: $scope.selected_tree_id }); + group = Find({ + list: $scope.groups, + key: 'id', + val: $scope.selected_tree_id + }); url = GetBasePath('activity_stream') + '?group__id=' + $scope.selected_group_id; title = 'Showing all activities for group ' + group.name; - } - else { + } else { title = 'Showing all activities for all ' + $scope.inventory_name + ' groups'; url = GetBasePath('activity_stream') + '?group__inventory__id=' + $scope.inventory_id; } - Stream({ scope: $scope, inventory_name: $scope.inventory_name, url: url, title: title }); - } - - $scope.showHostActivity = function() { + Stream({ + scope: $scope, + inventory_name: $scope.inventory_name, + url: url, + title: title + }); + }; + + $scope.showHostActivity = function () { var url, title; title = 'Showing all activities for all ' + $scope.inventory_name + ' hosts'; url = GetBasePath('activity_stream') + '?host__inventory__id=' + $scope.inventory_id; - Stream({ scope: $scope, inventory_name: $scope.inventory_name, url: url, title: title }); - } + Stream({ + scope: $scope, + inventory_name: $scope.inventory_name, + url: url, + title: title + }); + }; - $scope.showJobSummary = function(job_id) { - ShowJobSummary({ job_id: job_id }); - } + $scope.showJobSummary = function (job_id) { + ShowJobSummary({ + job_id: job_id + }); + }; - $scope.showGroupHelp = function(params) { - var opts = { defn: InventoryGroupsHelp }; + $scope.showGroupHelp = function (params) { + var opts = { + defn: InventoryGroupsHelp + }; if (params) { opts.autoShow = params.autoShow || false; } HelpDialog(opts); - } + }; //Load tree data for the first time - BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: false }); + BuildTree({ + scope: $scope, + inventory_id: $scope.inventory_id, + refresh: false + }); - } +} -InventoriesEdit.$inject = [ '$scope', '$location', '$routeParams', '$compile', 'GenerateList', 'ClearScope', 'InventoryGroups', 'InventoryHosts', - 'BuildTree', 'Wait', 'GetSyncStatusMsg', 'InjectHosts', 'HostsReload', 'GroupsAdd', 'GroupsEdit', 'GroupsDelete', - 'Breadcrumbs', 'LoadBreadCrumbs', 'Empty', 'Rest', 'ProcessErrors', 'InventoryUpdate', 'Alert', 'ToggleChildren', - 'ViewUpdateStatus', 'GroupsCancelUpdate', 'Find', 'HostsCreate', 'EditInventoryProperties', 'HostsEdit', - 'HostsDelete', 'ToggleHostEnabled', 'CopyMoveGroup', 'CopyMoveHost', 'Stream', 'GetBasePath', 'ShowJobSummary', - 'ApplyEllipsis', 'WatchInventoryWindowResize', 'HelpDialog', 'InventoryGroupsHelp', 'Store' - ]; - +InventoriesEdit.$inject = ['$scope', '$location', '$routeParams', '$compile', 'GenerateList', 'ClearScope', 'InventoryGroups', 'InventoryHosts', + 'BuildTree', 'Wait', 'GetSyncStatusMsg', 'InjectHosts', 'HostsReload', 'GroupsAdd', 'GroupsEdit', 'GroupsDelete', 'Breadcrumbs', + 'LoadBreadCrumbs', 'Empty', 'Rest', 'ProcessErrors', 'InventoryUpdate', 'Alert', 'ToggleChildren', 'ViewUpdateStatus', 'GroupsCancelUpdate', + 'Find', 'HostsCreate', 'EditInventoryProperties', 'HostsEdit', 'HostsDelete', 'ToggleHostEnabled', 'CopyMoveGroup', 'CopyMoveHost', + 'Stream', 'GetBasePath', 'ShowJobSummary', 'ApplyEllipsis', 'WatchInventoryWindowResize', 'HelpDialog', 'InventoryGroupsHelp', 'Store' +]; \ No newline at end of file diff --git a/awx/ui/static/js/controllers/JobEvents.js b/awx/ui/static/js/controllers/JobEvents.js index 735fe2eaee..7c9406dd0d 100644 --- a/awx/ui/static/js/controllers/JobEvents.js +++ b/awx/ui/static/js/controllers/JobEvents.js @@ -3,180 +3,168 @@ * * * JobEvents.js - * + * * Controller functions for the Job Events model. * */ 'use strict'; -function JobEventsList ($filter, $scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobEventList, - GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, - ClearScope, ProcessErrors, GetBasePath, LookUpInit, ToggleChildren, - FormatDate, EventView, Refresh, Wait) -{ +function JobEventsList($filter, $scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobEventList, GenerateList, + LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, LookUpInit, ToggleChildren, + FormatDate, EventView, Refresh, Wait) { + ClearScope('htmlTemplate'); - var list = JobEventList; + + var list = JobEventList, + defaultUrl = GetBasePath('jobs') + $routeParams.id + '/job_events/', //?parent__isnull=1'; + view = GenerateList, + scope = view.inject(list, { mode: 'edit' }), + page; + list.base = $location.path(); - - var defaultUrl = GetBasePath('jobs') + $routeParams.id + '/job_events/'; //?parent__isnull=1'; - - var view = GenerateList; - var base = $location.path().replace(/^\//,'').split('/')[0]; - var scope = view.inject(list, { mode: 'edit' }); - scope.job_id = $routeParams.id; $rootScope.flashMessage = null; scope.selected = []; - scope.expand = true; //on load, automatically expand all nodes + scope.expand = true; //on load, automatically expand all nodes + + scope.parentNode = 'parent-event'; // used in ngClass to dynamically set row level class and control + scope.childNode = 'child-event'; // link color and cursor - scope.parentNode = 'parent-event'; // used in ngClass to dynamically set row level class and control - scope.childNode = 'child-event'; // link color and cursor - if (scope.removeSetHostLinks) { - scope.removeSetHostLinks(); + scope.removeSetHostLinks(); } - scope.removeSetHostLinks = scope.$on('SetHostLinks', function(e, inventory_id) { - for (var i=0; i < scope.jobevents.length; i++) { + scope.removeSetHostLinks = scope.$on('SetHostLinks', function (e, inventory_id) { + for (var i = 0; i < scope.jobevents.length; i++) { if (scope.jobevents[i].summary_fields.host) { - scope.jobevents[i].hostLink = "/#/inventories/" + inventory_id + "/hosts/?name=" + - escape(scope.jobevents[i].summary_fields.host.name); + scope.jobevents[i].hostLink = "/#/inventories/" + inventory_id + "/hosts/?name=" + + encodeURI(scope.jobevents[i].summary_fields.host.name); } } - }); + }); function formatJSON(eventData) { //turn JSON event data into an html form - var html = ''; - if (eventData['res']) { - var n, rows; - var found = false; - if (typeof eventData.res == 'string') { - n = eventData['res'].match(/\n/g); - rows = (n) ? n.length : 1; - rows = (rows > 10) ? 10 : rows; - found = true; - html += "
\n"; - html += "\n"; - html += "\n"; - html += "
\n"; - } - else { - for (var fld in eventData.res) { - if ( (fld == 'msg' || fld == 'stdout' || fld == 'stderr') && - (eventData.res[fld] !== null && eventData.res[fld] !== '') ) { - html += "
\n"; - html += "\n"; - n = eventData['res'][fld].match(/\n/g); - rows = (n) ? n.length : 1; - rows = (rows > 10) ? 10 : rows; - html += "\n"; - html += "
\n"; - found = true; - } - if ( fld == "results" && Array.isArray(eventData.res[fld]) && eventData.res[fld].length > 0 ) { - //html += "\n"; + html += "\n"; + } else { + for (fld in eventData.res) { + if ((fld === 'msg' || fld === 'stdout' || fld === 'stderr') && + (eventData.res[fld] !== null && eventData.res[fld] !== '')) { html += "
\n"; - html += "\n"; - html += "\n"; + html += "\n"; + n = eventData.res[fld].match(/\n/g); + rows = (n) ? n.length : 1; + rows = (rows > 10) ? 10 : rows; + html += "\n"; html += "
\n"; found = true; - } - } - if (fld == "rc" && eventData.res[fld] != '') { - html += "
\n"; - html += "\n"; - html += "\n"; - html += "
\n"; - found = true; - } - } - } - html = (found) ? "
\n" + html + "
\n" : ''; + } + if (fld === "results" && Array.isArray(eventData.res[fld]) && eventData.res[fld].length > 0) { + //html += "\n"; + html += "\n"; + found = true; + } + } + if (fld === "rc" && eventData.res[fld] !== '') { + html += "
\n"; + html += "\n"; + html += "\n"; + html += "
\n"; + found = true; + } + } + } + html = (found) ? "
\n" + html + "
\n" : ''; } - if (eventData['host']) { - html = "" + eventData['host'] + "\n" + html; - } - else { - html = (html == '' ) ? null : html; + if (eventData.hosts) { + html = "" + eventData.host + "\n" + html; + } else { + html = (html === '') ? null : html; } return html; - } + } if (scope.removePostRefresh) { - scope.removePostRefresh(); + scope.removePostRefresh(); } - scope.removePostRefresh = scope.$on('PostRefresh', function() { + scope.removePostRefresh = scope.$on('PostRefresh', function () { // Initialize the parent levels - var set = scope[list.name]; - var cDate; - for (var i=0; i < set.length; i++) { - set[i].event_display = set[i].event_display.replace(/^\u00a0*/g,''); - if (set[i].event_level < 3 ) { - set[i]['ngclick'] = "toggleChildren(" + set[i].id + ", \"" + set[i].related.children + "\")"; - set[i]['ngicon'] = 'fa fa-minus-square-o node-toggle'; - set[i]['class'] = 'parentNode'; + var set = scope[list.name], i; + for (i = 0; i < set.length; i++) { + set[i].event_display = set[i].event_display.replace(/^\u00a0*/g, ''); + if (set[i].event_level < 3) { + set[i].ngclick = "toggleChildren(" + set[i].id + ", \"" + set[i].related.children + "\")"; + set[i].ngicon = 'fa fa-minus-square-o node-toggle'; + set[i]['class'] = 'parentNode'; + } else { + set[i].ngicon = 'fa fa-square-o node-no-toggle'; + set[i]['class'] = 'childNode'; + set[i].event_detail = formatJSON(set[i].event_data); } - else { - set[i]['ngicon'] = 'fa fa-square-o node-no-toggle'; - set[i]['class'] = 'childNode'; - set[i]['event_detail'] = formatJSON(set[i].event_data); - } - set[i]['show'] = true; - set[i]['spaces'] = set[i].event_level * 24; + set[i].show = true; + set[i].spaces = set[i].event_level * 24; if (scope.jobevents[i].failed) { - scope.jobevents[i].status = 'error'; - if (i == set.length - 1) { - scope.jobevents[i].statusBadgeToolTip = "A failure occurred durring one or more playbook tasks."; - } - else if (set[i].event_level < 3) { - scope.jobevents[i].statusBadgeToolTip = "A failure occurred within the children of this event."; - } - else { - scope.jobevents[i].statusBadgeToolTip = "A failure occurred. Click to view details"; - } - } - else if (scope.jobevents[i].changed) { - scope.jobevents[i].status = 'changed'; - if (i == set.length - 1) { - scope.jobevents[i].statusBadgeToolTip = "A change was completed durring one or more playbook tasks."; - } - else if (set[i].event_level < 3) { - scope.jobevents[i].statusBadgeToolTip = "A change was completed by one or more children of this event."; - } - else { - scope.jobevents[i].statusBadgeToolTip = "A change was completed. Click to view details"; - } - } - else { - scope.jobevents[i].status = 'success'; - if (i == set.length - 1) { - scope.jobevents[i].statusBadgeToolTip = "All playbook tasks completed successfully."; - } - else if (set[i].event_level < 3) { - scope.jobevents[i].statusBadgeToolTip = "All the children of this event completed successfully."; - } - else { - scope.jobevents[i].statusBadgeToolTip = "No errors occurred. Click to view details"; - } + scope.jobevents[i].status = 'error'; + if (i === set.length - 1) { + scope.jobevents[i].statusBadgeToolTip = "A failure occurred durring one or more playbook tasks."; + } else if (set[i].event_level < 3) { + scope.jobevents[i].statusBadgeToolTip = "A failure occurred within the children of this event."; + } else { + scope.jobevents[i].statusBadgeToolTip = "A failure occurred. Click to view details"; + } + } else if (scope.jobevents[i].changed) { + scope.jobevents[i].status = 'changed'; + if (i === set.length - 1) { + scope.jobevents[i].statusBadgeToolTip = "A change was completed durring one or more playbook tasks."; + } else if (set[i].event_level < 3) { + scope.jobevents[i].statusBadgeToolTip = "A change was completed by one or more children of this event."; + } else { + scope.jobevents[i].statusBadgeToolTip = "A change was completed. Click to view details"; + } + } else { + scope.jobevents[i].status = 'success'; + if (i === set.length - 1) { + scope.jobevents[i].statusBadgeToolTip = "All playbook tasks completed successfully."; + } else if (set[i].event_level < 3) { + scope.jobevents[i].statusBadgeToolTip = "All the children of this event completed successfully."; + } else { + scope.jobevents[i].statusBadgeToolTip = "No errors occurred. Click to view details"; + } } //cDate = new Date(set[i].created); //set[i].created = FormatDate(cDate); @@ -187,160 +175,180 @@ function JobEventsList ($filter, $scope, $rootScope, $location, $log, $routePara // from job in the event that there are no job event records Rest.setUrl(GetBasePath('jobs') + scope.job_id); Rest.get() - .success( function(data, status, headers, config) { + .success(function (data) { scope.job_status = data.status; scope.job_name = data.summary_fields.job_template.name; - LoadBreadCrumbs({ path: '/jobs/' + scope.job_id, title: scope.job_id + ' - ' + data.summary_fields.job_template.name }); - scope.$emit('SetHostLinks', data.inventory); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to get job status for job: ' + scope.job_id + '. GET status: ' + status }); + LoadBreadCrumbs({ + path: '/jobs/' + scope.job_id, + title: scope.job_id + ' - ' + data.summary_fields.job_template.name }); - }); + scope.$emit('SetHostLinks', data.inventory); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Failed to get job status for job: ' + scope.job_id + '. GET status: ' + status + }); + }); + }); - SearchInit({ scope: scope, set: 'jobevents', list: list, url: defaultUrl }); - - var page = ($routeParams.page) ? parseInt($routeParams.page) - 1 : null; - PaginateInit({ scope: scope, list: list, url: defaultUrl, page: page }); + SearchInit({ + scope: scope, + set: 'jobevents', + list: list, + url: defaultUrl + }); + + page = ($routeParams.page) ? parseInt($routeParams.page,10) - 1 : null; + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl, + page: page + }); // Called from Inventories tab, host failed events link: if ($routeParams.host) { - scope[list.iterator + 'SearchField'] = 'host'; - scope[list.iterator + 'SearchValue'] = $routeParams.host; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['host'].label; + scope[list.iterator + 'SearchField'] = 'host'; + scope[list.iterator + 'SearchValue'] = $routeParams.host; + scope[list.iterator + 'SearchFieldLabel'] = list.fields.host.label; } - + scope.search(list.iterator, $routeParams.page); - - scope.toggleChildren = function(id, children) { + + scope.toggleChildren = function (id, children) { ToggleChildren({ - scope: scope, + scope: scope, list: list, id: id, children: children - }); - } - - scope.viewJobEvent = function(id) { - EventView({ event_id: id }); - } + }); + }; - scope.refresh = function() { - scope['jobSearchSpin'] = true; - scope['jobLoading'] = true; - Wait('start'); - Refresh({ scope: scope, set: 'jobevents', iterator: 'jobevent', url: scope['current_url'] }); - } + scope.viewJobEvent = function (id) { + EventView({ + event_id: id + }); + }; + + scope.refresh = function () { + scope.jobSearchSpin = true; + scope.jobLoading = true; + Wait('start'); + Refresh({ + scope: scope, + set: 'jobevents', + iterator: 'jobevent', + url: scope.current_url + }); + }; } -JobEventsList.$inject = [ '$filter', '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobEventList', - 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', - 'ProcessErrors','GetBasePath', 'LookUpInit', 'ToggleChildren', 'FormatDate', 'EventView', 'Refresh', 'Wait' - ]; +JobEventsList.$inject = ['$filter', '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobEventList', + 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', + 'ProcessErrors', 'GetBasePath', 'LookUpInit', 'ToggleChildren', 'FormatDate', 'EventView', 'Refresh', 'Wait' +]; -function JobEventsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, JobEventForm, GenerateForm, - Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, FormatDate, EventView, - Wait) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. - // Inject dynamic view - var form = JobEventForm; - var generator = GenerateForm; - var scope = GenerateForm.inject(form, {mode: 'edit', related: true}); - generator.reset(); - - var defaultUrl = GetBasePath('base') + 'job_events/' + $routeParams.event_id + '/'; - var base = $location.path().replace(/^\//,'').split('/')[0]; - - // Retrieve detail record and prepopulate the form - Wait('start'); - Rest.setUrl(defaultUrl); - Rest.get() - .success( function(data, status, headers, config) { - scope['event_display'] = data['event_display'].replace(/^\u00a0*/g,''); - LoadBreadCrumbs({ path: '/jobs/' + $routeParams.job_id + '/job_events/' + $routeParams.event_id, - title: scope['event_display'] }); - for (var fld in form.fields) { - switch(fld) { - case 'status': - if (data['failed']) { - scope['status'] = 'error'; - } - else if (data['changed']) { - scope['status'] = 'changed'; - } - else { - scope['status'] = 'success'; - } - break; - case 'created': - var cDate = new Date(data['created']); - scope['created'] = FormatDate(cDate); - break; - case 'host': - if (data['summary_fields'] && data['summary_fields']['host']) { - scope['host'] = data['summary_fields']['host']['name']; - } - break; - case 'id': - case 'task': - case 'play': - scope[fld] = data[fld]; - break; - case 'start': - case 'end': - if (data['event_data'] && data['event_data']['res'] && data['event_data']['res'][fld] !== undefined) { - var cDate = new Date(data['event_data']['res'][fld]); - scope[fld] = FormatDate(cDate); +function JobEventsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobEventForm, GenerateForm, + Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, FormatDate, EventView, + Wait) { + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. + // Inject dynamic view + var form = JobEventForm, + generator = GenerateForm, + scope = GenerateForm.inject(form, { mode: 'edit', related: true }), + defaultUrl = GetBasePath('base') + 'job_events/' + $routeParams.event_id + '/'; + + generator.reset(); + + // Retrieve detail record and prepopulate the form + Wait('start'); + Rest.setUrl(defaultUrl); + Rest.get() + .success(function (data) { + var cDate, fld, n, rows; + scope.event_display = data.event_display.replace(/^\u00a0*/g, ''); + LoadBreadCrumbs({ path: '/jobs/' + $routeParams.job_id + '/job_events/' + $routeParams.event_id, title: scope.event_display }); + for (fld in form.fields) { + switch (fld) { + case 'status': + if (data.failed) { + scope.status = 'error'; + } else if (data.changed) { + scope.status = 'changed'; + } else { + scope.status = 'success'; } break; - case 'msg': - case 'stdout': - case 'stderr': - case 'delta': - case 'rc': - if (data['event_data'] && data['event_data']['res'] && data['event_data']['res'][fld] !== undefined) { - scope[fld] = data['event_data']['res'][fld]; - if (form.fields[fld].type == 'textarea') { - var n = data['event_data']['res'][fld].match(/\n/g); - var rows = (n) ? n.length : 1; - rows = (rows > 15) ? 5 : rows; - $('textarea[name="' + fld + '"]').attr('rows',rows); + case 'created': + cDate = new Date(data.created); + scope.created = FormatDate(cDate); + break; + case 'host': + if (data.summary_fields && data.summary_fields.host) { + scope.host = data.summary_fields.host.name; + } + break; + case 'id': + case 'task': + case 'play': + scope[fld] = data[fld]; + break; + case 'start': + case 'end': + if (data.event_data && data.event_data.res && data.event_data.res[fld] !== undefined) { + cDate = new Date(data.event_data.res[fld]); + scope[fld] = FormatDate(cDate); + } + break; + case 'msg': + case 'stdout': + case 'stderr': + case 'delta': + case 'rc': + if (data.event_data && data.event_data.res && data.event_data.res[fld] !== undefined) { + scope[fld] = data.event_data.res[fld]; + if (form.fields[fld].type === 'textarea') { + n = data.event_data.res[fld].match(/\n/g); + rows = (n) ? n.length : 1; + rows = (rows > 15) ? 5 : rows; + $('textarea[name="' + fld + '"]').attr('rows', rows); } - } - break; - case 'module_name': - case 'module_args': - if (data['event_data']['res'] && data['event_data']['res']['invocation']) { - scope[fld] = data['event_data']['res']['invocation'][fld]; - } - break; - } - } - Wait('stop'); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to retrieve host: ' + $routeParams.event_id + '. GET status: ' + status }); - }); + } + break; + case 'module_name': + case 'module_args': + if (data.event_data.res && data.event_data.res.invocation) { + scope[fld] = data.event_data.res.invocation.fld; + } + break; + } + } + Wait('stop'); + }) + .error(function (data) { + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve host: ' + $routeParams.event_id + + '. GET status: ' + status }); + }); - scope.navigateBack = function() { - var url = '/jobs/' + $routeParams.job_id + '/job_events'; - if ($routeParams.page) { - url += '?page=' + $routeParams.page; - } - $location.url(url); - } + scope.navigateBack = function () { + var url = '/jobs/' + $routeParams.job_id + '/job_events'; + if ($routeParams.page) { + url += '?page=' + $routeParams.page; + } + $location.url(url); + }; + + scope.rawView = function () { + EventView({ + "event_id": scope.id + }); + }; - scope.rawView = function() { - EventView({"event_id": scope.id }); - } - } -JobEventsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobEventForm', - 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', - 'FormatDate', 'EventView', 'Wait' - ]; +JobEventsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobEventForm', + 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', 'FormatDate', + 'EventView', 'Wait' +]; \ No newline at end of file diff --git a/awx/ui/static/js/controllers/JobHosts.js b/awx/ui/static/js/controllers/JobHosts.js index 5c94a29274..94f3da0cfd 100644 --- a/awx/ui/static/js/controllers/JobHosts.js +++ b/awx/ui/static/js/controllers/JobHosts.js @@ -3,145 +3,165 @@ * * * JobHosts.js - * + * * Controller functions for the Job Hosts Summary model. * */ 'use strict'; -function JobHostSummaryList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobHostList, - GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, - ClearScope, ProcessErrors, GetBasePath, Refresh, JobStatusToolTip, Wait) -{ +function JobHostSummaryList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobHostList, GenerateList, + LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, Refresh, + JobStatusToolTip, Wait) { + ClearScope('htmlTemplate'); - var list = JobHostList; - var base = $location.path().replace(/^\//,'').split('/')[0]; - var defaultUrl = GetBasePath(base) + $routeParams.id + '/job_host_summaries/'; - var inventory_id; + + var list = JobHostList, + base = $location.path().replace(/^\//, '').split('/')[0], + defaultUrl = GetBasePath(base) + $routeParams.id + '/job_host_summaries/', + view = GenerateList, + scope = view.inject(list, { mode: 'edit' }); // When viewing all summaries for a particular host, show job ID, otherwise row ID. - if (base == 'hosts') { - list.index = false; + if (base === 'hosts') { + list.index = false; + } else { + list.index = true; } - else { - list.index = true; - } - - var view = GenerateList; - var scope = view.inject(list, { mode: 'edit' }); scope.selected = []; - + // control enable/disable/show of job specific view elements - if (base == 'hosts') { - scope.job_id = null; - scope.host_id = $routeParams.id; + if (base === 'hosts') { + scope.job_id = null; + scope.host_id = $routeParams.id; + } else { + scope.job_id = $routeParams.id; + scope.host_id = null; } - else { - scope.job_id = $routeParams.id; - scope.host_id = null; - } - + if (scope.RemoveSetHostLink) { - scope.RemoveSetHostLink(); + scope.RemoveSetHostLink(); } - scope.RemoveSetHostLink = scope.$on('setHostLink', function(e, inventory_id) { - for (var i=0; i < scope.jobhosts.length; i++) { - scope.jobhosts[i].hostLinkTo = '/#/inventories/' + inventory_id + '/?host_name=' + - escape(scope.jobhosts[i].summary_fields.host.name); + scope.RemoveSetHostLink = scope.$on('setHostLink', function (e, inventory_id) { + for (var i = 0; i < scope.jobhosts.length; i++) { + scope.jobhosts[i].hostLinkTo = '/#/inventories/' + inventory_id + '/?host_name=' + + encodeURI(scope.jobhosts[i].summary_fields.host.name); } - }); + }); // After a refresh, populate any needed summary field values on each row if (scope.removePostRefresh) { - scope.removePostRefresh(); + scope.removePostRefresh(); } - scope.removePostRefresh = scope.$on('PostRefresh', function() { - + scope.removePostRefresh = scope.$on('PostRefresh', function () { + // Set status, tooltips, badget icons, etc. - for( var i=0; i < scope.jobhosts.length; i++) { - scope.jobhosts[i].host_name = scope.jobhosts[i].summary_fields.host.name; - scope.jobhosts[i].status = (scope.jobhosts[i].failed) ? 'failed' : 'success'; - scope.jobhosts[i].statusBadgeToolTip = JobStatusToolTip(scope.jobhosts[i].status) + - " Click to view details."; - scope.jobhosts[i].statusLinkTo = '/#/jobs/' + scope.jobhosts[i].job + '/job_events/?host=' + - escape(scope.jobhosts[i].summary_fields.host.name); + for (var i = 0; i < scope.jobhosts.length; i++) { + scope.jobhosts[i].host_name = scope.jobhosts[i].summary_fields.host.name; + scope.jobhosts[i].status = (scope.jobhosts[i].failed) ? 'failed' : 'success'; + scope.jobhosts[i].statusBadgeToolTip = JobStatusToolTip(scope.jobhosts[i].status) + + " Click to view details."; + scope.jobhosts[i].statusLinkTo = '/#/jobs/' + scope.jobhosts[i].job + '/job_events/?host=' + + encodeURI(scope.jobhosts[i].summary_fields.host.name); } if (scope.job_id !== null && scope.job_id !== undefined && scope.job_id !== '') { - // need job_status so we can show/hide refresh button - Rest.setUrl(GetBasePath('jobs') + scope.job_id); - Rest.get() - .success( function(data, status, headers, config) { - LoadBreadCrumbs({ path: '/jobs/' + data.id, title: data.id + ' - ' + - data.summary_fields.job_template.name }); - scope.job_status = data.status; - if (!(data.status == 'pending' || data.status == 'waiting' || data.status == 'running')) { - if ($rootScope.timer) { - clearInterval($rootScope.timer); - } - } - scope.$emit('setHostLink', data.inventory); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to get job status for job: ' + scope.job_id + '. GET status: ' + status }); - }); + // need job_status so we can show/hide refresh button + Rest.setUrl(GetBasePath('jobs') + scope.job_id); + Rest.get() + .success(function (data) { + LoadBreadCrumbs({ + path: '/jobs/' + data.id, + title: data.id + ' - ' + + data.summary_fields.job_template.name + }); + scope.job_status = data.status; + if (!(data.status === 'pending' || data.status === 'waiting' || data.status === 'running')) { + if ($rootScope.timer) { + clearInterval($rootScope.timer); + } + } + scope.$emit('setHostLink', data.inventory); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Failed to get job status for job: ' + scope.job_id + '. GET status: ' + status + }); + }); + } else { + // Make the host name appear in breadcrumbs + LoadBreadCrumbs({ + path: '/hosts/' + scope.host_id, + title: ((scope.jobhosts.length > 0) ? scope.jobhosts[0].summary_fields.host.name : 'Host') + }); + if ($routeParams.inventory) { + scope.$emit('setHostLink', $routeParams.inventory); + } } - else { - // Make the host name appear in breadcrumbs - LoadBreadCrumbs({ path: '/hosts/' + scope['host_id'], - title: ( (scope.jobhosts.length > 0) ? scope.jobhosts[0].summary_fields.host.name : 'Host' ) }); - if ($routeParams['inventory']) { - scope.$emit('setHostLink', $routeParams['inventory']); - } - } - }); - - SearchInit({ scope: scope, set: 'jobhosts', list: list, url: defaultUrl }); - PaginateInit({ scope: scope, list: list, url: defaultUrl }); + }); + + SearchInit({ + scope: scope, + set: 'jobhosts', + list: list, + url: defaultUrl + }); + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl + }); // Called from Inventories tab, host failed events link: - if ($routeParams['host_name']) { - scope[list.iterator + 'SearchField'] = 'host'; - scope[list.iterator + 'SearchValue'] = $routeParams['host_name']; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['host'].label; + if ($routeParams.host_name) { + scope[list.iterator + 'SearchField'] = 'host'; + scope[list.iterator + 'SearchValue'] = $routeParams.host_name; + scope[list.iterator + 'SearchFieldLabel'] = list.fields.host.label; } - + scope.search(list.iterator); - - - scope.showEvents = function(host_name, last_job) { + + + scope.showEvents = function (host_name, last_job) { // When click on !Failed Events link, redirect to latest job/job_events for the host Rest.setUrl(last_job); Rest.get() - .success( function(data, status, headers, config) { - LoadBreadCrumbs({ path: '/jobs/' + data.id, title: data.name }); - $location.url('/jobs/' + data.id + '/job_events/?host=' + escape(host_name)); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to lookup last job: ' + last_job + '. GET status: ' + status }); - }); - } + .success(function (data) { + LoadBreadCrumbs({ + path: '/jobs/' + data.id, + title: data.name + }); + $location.url('/jobs/' + data.id + '/job_events/?host=' + encodeURI(host_name)); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to lookup last job: ' + last_job + + '. GET status: ' + status }); + }); + }; - scope.showJob = function(id) { - $location.path('/jobs/' + id); - } + scope.showJob = function (id) { + $location.path('/jobs/' + id); + }; - scope.refresh = function() { - if (scope.host_id == null) { - scope['jobSearchSpin'] = true; - scope['jobLoading'] = true; - Wait('start'); - Refresh({ scope: scope, set: 'jobhosts', iterator: 'jobhost', url: scope['current_url'] }); + scope.refresh = function () { + if (scope.host_id === null) { + scope.jobSearchSpin = true; + scope.jobLoading = true; + Wait('start'); + Refresh({ + scope: scope, + set: 'jobhosts', + iterator: 'jobhost', + url: scope.current_url + }); } - } - + }; + } -JobHostSummaryList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobHostList', - 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', - 'ProcessErrors', 'GetBasePath', 'Refresh', 'JobStatusToolTip', 'Wait' - ]; +JobHostSummaryList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobHostList', + 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', + 'ProcessErrors', 'GetBasePath', 'Refresh', 'JobStatusToolTip', 'Wait' +]; \ No newline at end of file diff --git a/awx/ui/static/js/controllers/JobTemplates.js b/awx/ui/static/js/controllers/JobTemplates.js index 0fb999e30c..7c00029440 100644 --- a/awx/ui/static/js/controllers/JobTemplates.js +++ b/awx/ui/static/js/controllers/JobTemplates.js @@ -3,716 +3,771 @@ * * * JobTemplates.js - * + * * Controller functions for the Job Template model. * */ - 'use strict'; -function JobTemplatesList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobTemplateList, - GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, - ClearScope, ProcessErrors, GetBasePath, PromptPasswords, JobTemplateForm, CredentialList, - LookUpInit, SubmitJob, Wait, Stream) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. - var list = JobTemplateList; - var defaultUrl = GetBasePath('job_templates'); - var view = GenerateList; - var base = $location.path().replace(/^\//,'').split('/')[0]; - var mode = (base == 'job_templates') ? 'edit' : 'select'; - var scope = view.inject(list, { mode: mode }); +function JobTemplatesList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobTemplateList, + GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, + ClearScope, ProcessErrors, GetBasePath, PromptPasswords, JobTemplateForm, CredentialList, + LookUpInit, SubmitJob, Wait, Stream) { + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. + var list = JobTemplateList, + defaultUrl = GetBasePath('job_templates'), + view = GenerateList, + base = $location.path().replace(/^\//, '').split('/')[0], + mode = (base === 'job_templates') ? 'edit' : 'select', + scope = view.inject(list, { mode: mode }); + $rootScope.flashMessage = null; - + if (scope.removePostRefresh) { - scope.removePostRefresh(); + scope.removePostRefresh(); } - scope.removePostRefresh = scope.$on('PostRefresh', function() { + scope.removePostRefresh = scope.$on('PostRefresh', function () { // Cleanup after a delete Wait('stop'); $('#prompt-modal').off(); - }); - - SearchInit({ scope: scope, set: 'job_templates', list: list, url: defaultUrl }); - PaginateInit({ scope: scope, list: list, url: defaultUrl }); + }); + + SearchInit({ + scope: scope, + set: 'job_templates', + list: list, + url: defaultUrl + }); + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl + }); // Called from Inventories tab, host failed events link: - if ($routeParams['name']) { - scope[list.iterator + 'SearchField'] = 'name'; - scope[list.iterator + 'SearchValue'] = $routeParams['name']; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['name'].label; + if ($routeParams.name) { + scope[list.iterator + 'SearchField'] = 'name'; + scope[list.iterator + 'SearchValue'] = $routeParams.name; + scope[list.iterator + 'SearchFieldLabel'] = list.fields.name.label; } scope.search(list.iterator); LoadBreadCrumbs(); - - scope.showActivity = function() { Stream({ scope: scope }); } - scope.addJobTemplate = function() { - $location.path($location.path() + '/add'); - } + scope.showActivity = function () { + Stream({ + scope: scope + }); + }; - scope.editJobTemplate = function(id) { - $location.path($location.path() + '/' + id); - } - - scope.deleteJobTemplate = function(id, name) { - var action = function() { - $('#prompt-modal').on('hidden.bs.modal', function(){ Wait('start'); }); - $('#prompt-modal').modal('hide'); - var url = defaultUrl + id + '/'; - Rest.setUrl(url); - Rest.destroy() - .success( function(data, status, headers, config) { - scope.search(list.iterator); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); - }); - }; + scope.addJobTemplate = function () { + $location.path($location.path() + '/add'); + }; - Prompt({ hdr: 'Delete', - body: 'Are you sure you want to delete ' + name + '?', - action: action + scope.editJobTemplate = function (id) { + $location.path($location.path() + '/' + id); + }; + + scope.deleteJobTemplate = function (id, name) { + var action = function () { + $('#prompt-modal').on('hidden.bs.modal', function () { + Wait('start'); + }); + $('#prompt-modal').modal('hide'); + var url = defaultUrl + id + '/'; + Rest.setUrl(url); + Rest.destroy() + .success(function () { + scope.search(list.iterator); + }) + .error(function (data) { + Wait('stop'); + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status + }); }); - } - - scope.submitJob = function(id) { - SubmitJob({ scope: scope, id: id }); - } + }; + + Prompt({ + hdr: 'Delete', + body: 'Are you sure you want to delete ' + name + '?', + action: action + }); + }; + + scope.submitJob = function (id) { + SubmitJob({ scope: scope, id: id }); + }; } -JobTemplatesList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobTemplateList', - 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', - 'ProcessErrors','GetBasePath', 'PromptPasswords', 'JobTemplateForm', 'CredentialList', 'LookUpInit', - 'SubmitJob', 'Wait', 'Stream' - ]; +JobTemplatesList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobTemplateList', + 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', + 'ProcessErrors', 'GetBasePath', 'PromptPasswords', 'JobTemplateForm', 'CredentialList', 'LookUpInit', + 'SubmitJob', 'Wait', 'Stream' +]; -function JobTemplatesAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, - GetBasePath, InventoryList, CredentialList, ProjectList, LookUpInit, - md5Setup, ParseTypeChange, Wait, Empty) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. +function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm, + GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, + GetBasePath, InventoryList, CredentialList, ProjectList, LookUpInit, + md5Setup, ParseTypeChange, Wait, Empty) { + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. - // Inject dynamic view - var defaultUrl = GetBasePath('job_templates'); - var form = JobTemplateForm; - var generator = GenerateForm; - var scope = generator.inject(form, {mode: 'add', related: false}); - var master = {}; - - scope.parseType = 'yaml'; - ParseTypeChange(scope); + // Inject dynamic view + var defaultUrl = GetBasePath('job_templates'), + form = JobTemplateForm, + generator = GenerateForm, + scope = generator.inject(form, { mode: 'add', related: false }), + master = {}, + CloudCredentialList = {}, + selectPlaybook, checkSCMStatus; - scope.job_type_options = [{ value: 'run', label: 'Run' }, { value: 'check', label: 'Check' }]; - scope.verbosity_options = [ - { value: '0', label: 'Default' }, - { value: '1', label: 'Verbose' }, - { value: '3', label: 'Debug' }]; - scope.playbook_options = []; - scope.allow_callbacks = 'false'; + scope.parseType = 'yaml'; + ParseTypeChange(scope); - generator.reset(); - LoadBreadCrumbs(); + scope.job_type_options = [ + { value: 'run', label: 'Run' }, + { value: 'check', label: 'Check' } + ]; - md5Setup({ - scope: scope, - master: master, - check_field: 'allow_callbacks', - default_val: false - }); + scope.verbosity_options = [ + { value: '0', label: 'Default' }, + { value: '1', label: 'Verbose' }, + { value: '3', label: 'Debug' } + ]; - LookUpInit({ - scope: scope, - form: form, - current_item: null, - list: InventoryList, - field: 'inventory' - }); + scope.playbook_options = []; + scope.allow_callbacks = 'false'; - // Clone the CredentialList object for use with cloud_credential. Cloning - // and changing properties to avoid collision. - var CloudCredentialList = {}; - jQuery.extend(true, CloudCredentialList, CredentialList); - CloudCredentialList.name = 'cloudcredentials', - CloudCredentialList.iterator = 'cloudcredential', - - LookUpInit({ - url: GetBasePath('credentials') + '?cloud=true', - scope: scope, - form: form, - current_item: null, - list: CloudCredentialList, - field: 'cloud_credential', - hdr: 'Select Cloud Credential' - }); - - LookUpInit({ - url: GetBasePath('credentials') + '?kind=ssh', - scope: scope, - form: form, - current_item: null, - list: CredentialList, - field: 'credential', - hdr: 'Select Machine Credential' - }); + generator.reset(); + LoadBreadCrumbs(); - // Update playbook select whenever project value changes - var selectPlaybook = function(oldValue, newValue) { - if (oldValue != newValue) { - if (scope.project) { - Wait('start'); - var url = GetBasePath('projects') + scope.project + '/playbooks/'; - Rest.setUrl(url); - Rest.get() - .success( function(data, status, headers, config) { - var opts = []; - for (var i=0; i < data.length; i++) { - opts.push(data[i]); - } - scope.playbook_options = opts; - Wait('stop'); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to get playbook list for ' + url +'. GET returned status: ' + status }); - }); - } - } - }; - - // Detect and alert user to potential SCM status issues - var checkSCMStatus = function(oldValue, newValue) { - if (oldValue !== newValue && !Empty(scope.project)) { - Rest.setUrl(GetBasePath('projects') + scope.project + '/'); - Rest.get() - .success( function(data, status, headers, config) { - var msg; - switch(data.status) { - case 'failed': - msg = "The selected project has a failed status. Review the project's SCM settings" + - " and run an update before adding it to a template."; - break; - case 'never updated': - msg = 'The selected project has a never updated status. You will need to run a successful' + - ' update in order to selected a playbook. Without a valid playbook you will not be able ' + - ' to save this template.'; - break; - case 'missing': - msg = 'The selected project has a status of missing. Please check the server and make sure ' + - ' the directory exists and file permissions are set correctly.'; - break; - } - if (msg) { - Alert('Waning', msg, 'alert-info'); - } - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to get project ' + scope.project +'. GET returned status: ' + status }); - }); - } - } - - // Register a watcher on project_name - if (scope.selectPlaybookUnregister) { - scope.selectPlaybookUnregister(); - } - scope.selectPlaybookUnregister = scope.$watch('project_name', function(oldval, newval) { - selectPlaybook(oldval, newval); - checkSCMStatus(oldval, newval); - }); + md5Setup({ + scope: scope, + master: master, + check_field: 'allow_callbacks', + default_val: false + }); - LookUpInit({ - scope: scope, - form: form, - current_item: null, - list: ProjectList, - field: 'project' - }); + LookUpInit({ + scope: scope, + form: form, + current_item: null, + list: InventoryList, + field: 'inventory' + }); - // Save - scope.formSave = function() { - generator.clearApiErrors(); - Wait('start'); - var data = {} - try { - // Make sure we have valid variable data - if (scope.parseType == 'json') { - var json_data = JSON.parse(scope.variables); //make sure JSON parses - } - else { - var json_data = jsyaml.load(scope.variables); //parse yaml - } - - // Make sure our JSON is actually an object - if (typeof json_data !== 'object') { - throw "failed to return an object!"; - } + // Clone the CredentialList object for use with cloud_credential. Cloning + // and changing properties to avoid collision. + jQuery.extend(true, CloudCredentialList, CredentialList); + CloudCredentialList.name = 'cloudcredentials'; + CloudCredentialList.iterator = 'cloudcredential'; - for (var fld in form.fields) { - if (form.fields[fld].type == 'select' && fld != 'playbook') { - data[fld] = scope[fld].value; - } - else { - if (fld != 'variables') { - data[fld] = scope[fld]; - } - } - } - - data.extra_vars = JSON.stringify(json_data, undefined, '\t'); - if (data.extra_vars == "null" || data.extra_vars == null) { - data.extra_vars = ""; - } + LookUpInit({ + url: GetBasePath('credentials') + '?cloud=true', + scope: scope, + form: form, + current_item: null, + list: CloudCredentialList, + field: 'cloud_credential', + hdr: 'Select Cloud Credential' + }); - Rest.setUrl(defaultUrl); - Rest.post(data) - .success( function(data, status, headers, config) { - Wait('stop'); - var base = $location.path().replace(/^\//,'').split('/')[0]; - (base == 'job_templates') ? ReturnToCaller() : ReturnToCaller(1); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to add new job template. POST returned status: ' + status }); - }); + LookUpInit({ + url: GetBasePath('credentials') + '?kind=ssh', + scope: scope, + form: form, + current_item: null, + list: CredentialList, + field: 'credential', + hdr: 'Select Machine Credential' + }); - } - catch(err) { - Wait('stop'); - Alert("Error", "Error parsing extra variables. Parser returned: " + err); - } - }; + // Update playbook select whenever project value changes + selectPlaybook = function (oldValue, newValue) { + var url; + if (oldValue !== newValue) { + if (scope.project) { + Wait('start'); + url = GetBasePath('projects') + scope.project + '/playbooks/'; + Rest.setUrl(url); + Rest.get() + .success(function (data) { + var i, opts = []; + for (i = 0; i < data.length; i++) { + opts.push(data[i]); + } + scope.playbook_options = opts; + Wait('stop'); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, form, { + hdr: 'Error!', + msg: 'Failed to get playbook list for ' + url + '. GET returned status: ' + status + }); + }); + } + } + }; - // Reset - scope.formReset = function() { - // Defaults - generator.reset(); - //$('#forks-slider').slider("option", "value", scope.forks); - for (var fld in master) { - scope[fld] = master[fld]; - } - }; -} - -JobTemplatesAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobTemplateForm', - 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', - 'GetBasePath', 'InventoryList', 'CredentialList', 'ProjectList', 'LookUpInit', - 'md5Setup', 'ParseTypeChange', 'Wait', 'Empty' ]; - - -function JobTemplatesEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, - RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList, CredentialList, - ProjectList, LookUpInit, PromptPasswords, GetBasePath, md5Setup, ParseTypeChange, - JobStatusToolTip, FormatDate, Wait, Stream, Empty) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. - - var defaultUrl= GetBasePath('job_templates'); - var generator = GenerateForm; - var form = JobTemplateForm; - var scope = generator.inject(form, {mode: 'edit', related: true}); - var loadingFinishedCount = 0; - - scope.parseType = 'yaml'; - ParseTypeChange(scope); - - // Our job type options - scope.job_type_options = [{ value: 'run', label: 'Run' }, { value: 'check', label: 'Check' }]; - scope.verbosity_options = [ - { value: '0', label: 'Default' }, - { value: '1', label: 'Verbose' }, - { value: '3', label: 'Debug' }]; - scope.playbook_options = null; - scope.playbook = null; - - generator.reset(); - - var base = $location.path().replace(/^\//,'').split('/')[0]; - var master = {}; - var id = $routeParams.id; - var relatedSets = {}; - - function getPlaybooks(project) { - if (project !== null && project !== '' && project !== undefined) { - var url = GetBasePath('projects') + project + '/playbooks/'; - Wait('start'); - Rest.setUrl(url); - Rest.get() - .success( function(data, status, headers, config) { - scope.playbook_options = []; - for (var i=0; i < data.length; i++) { - scope.playbook_options.push(data[i]); - if (data[i] == scope.playbook) { - scope['job_templates_form']['playbook'].$setValidity('required',true); - } - } - if (scope.playbook) { - scope.$emit('jobTemplateLoadFinished'); - } - else { - Wait('stop'); - } - }) - .error( function(data, status, headers, config) { - Wait('stop'); - Alert('Missing Playbooks', 'Unable to retrieve the list of playbooks for this project. Choose a different ' + - ' project or make the playbooks available on the file system.', 'alert-info'); - }); - } - } - - // Detect and alert user to potential SCM status issues - var checkSCMStatus = function() { - if (!Empty(scope.project)) { - Wait('start'); - Rest.setUrl(GetBasePath('projects') + scope.project + '/'); - Rest.get() - .success( function(data, status, headers, config) { - var msg; - switch(data.status) { - case 'failed': - msg = "The selected project has a failed status. Review the project's SCM settings" + - " and run an update before adding it to a template."; - break; - case 'never updated': - msg = 'The selected project has a never updated status. You will need to run a successful' + - ' update in order to selected a playbook. Without a valid playbook you will not be able ' + - ' to save this template.'; - break; - case 'missing': - msg = 'The selected project has a status of missing. Please check the server and make sure ' + - ' the directory exists and file permissions are set correctly.'; - break; - } - Wait('stop'); - if (msg) { - Alert('Waning', msg, 'alert-info'); - } - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to get project ' + scope.project +'. GET returned status: ' + status }); - }); - } - } - - - // Register a watcher on project_name. Refresh the playbook list on change. - if (scope.watchProjectUnregister) { - scope.watchProjectUnregister(); - } - scope.watchProjectUnregister = scope.$watch('project_name', function(oldValue, newValue) { - if (oldValue !== newValue && newValue !== '' && newValue !== null && newValue !== undefined) { - scope.playbook = null; - getPlaybooks(scope.project); - checkSCMStatus(); - } - }); - - // Turn off 'Wait' after both cloud credential and playbook list come back - if (scope.removeJobTemplateLoadFinished) { - scope.removeJobTemplateLoadFinished(); - } - scope.removeJobTemplateLoadFinished = scope.$on('jobTemplateLoadFinished', function() { - loadingFinishedCount++; - if (loadingFinishedCount >= 2) { - // The initial template load finished. Now load related jobs, which - // will turn off the 'working' spinner. - for (var set in relatedSets) { - scope.search(relatedSets[set].iterator); - } - - } - }); - - // Set the status/badge for each related job - if (scope.removeRelatedJobs) { - scope.removeRelatedJobs(); - } - scope.removeRelatedJobs = scope.$on('relatedjobs', function() { - if (scope['jobs'] && scope['jobs'].length) { - var cDate; - for (var i=0; i < scope['jobs'].length; i++) { - // Convert created date to local time zone - cDate = new Date(scope['jobs'][i].created); - scope['jobs'][i].created = FormatDate(cDate); - // Set tooltip and link - scope['jobs'][i].statusBadgeToolTip = JobStatusToolTip(scope['jobs'][i].status) + - " Click to view status details."; - scope['jobs'][i].statusLinkTo = '/#/jobs/' + scope['jobs'][i].id; - } - } - }); - - if (scope.cloudCredentialReadyRemove) { - scope.cloudCredentialReadyRemove(); - } - scope.cloudCredentialReadyRemove = scope.$on('cloudCredentialReady', function(e, name) { - scope['cloud_credential_name'] = name; - master['cloud_credential_name'] = name; - // Clone the CredentialList object for use with cloud_credential. Cloning - // and changing properties to avoid collision. - var CloudCredentialList = {}; - jQuery.extend(true, CloudCredentialList, CredentialList); - CloudCredentialList.name = 'cloudcredentials', - CloudCredentialList.iterator = 'cloudcredential', - LookUpInit({ - url: GetBasePath('credentials') + '?cloud=true', - scope: scope, - form: form, - current_item: scope['cloud_credential'], - list: CloudCredentialList, - field: 'cloud_credential', - hdr: 'Select Cloud Credential' - }); - scope.$emit('jobTemplateLoadFinished'); - }); - - - // Retrieve each related set and populate the playbook list - if (scope.jobTemplateLoadedRemove) { - scope.jobTemplateLoadedRemove(); - } - scope.jobTemplateLoadedRemove = scope.$on('jobTemplateLoaded', function(e, related_cloud_credential) { - - getPlaybooks(scope.project); - - var dft = (scope['host_config_key'] === "" || scope['host_config_key'] === null) ? 'false' : 'true'; - md5Setup({ - scope: scope, - master: master, - check_field: 'allow_callbacks', - default_val: dft - }); - - if (related_cloud_credential) { - Rest.setUrl(related_cloud_credential); - Rest.get() - .success( function(data, status, headers, config) { - scope.$emit('cloudCredentialReady', data.name); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to related cloud credential. GET returned status: ' + status }); - }); - } - else { - // No existing cloud credential - scope.$emit('cloudCredentialReady', null); - } - }); - - Wait('start'); - // Retrieve detail record and prepopulate the form - Rest.setUrl(defaultUrl + ':id/'); - Rest.get({ params: {id: id} }) - .success( function(data, status, headers, config) { - LoadBreadCrumbs({ path: '/job_templates/' + id, title: data.name }); - for (var fld in form.fields) { - if (fld != 'variables' && data[fld] !== null && data[fld] !== undefined) { - if (form.fields[fld].type == 'select') { - if (scope[fld + '_options'] && scope[fld + '_options'].length > 0) { - for (var i=0; i < scope[fld + '_options'].length; i++) { - if (data[fld] == scope[fld + '_options'][i].value) { - scope[fld] = scope[fld + '_options'][i]; - } - } - } - else { - scope[fld] = data[fld]; - } - } - else { - scope[fld] = data[fld]; - } - master[fld] = scope[fld]; - } - if (fld == 'variables') { - // Parse extra_vars, converting to YAML. - if ($.isEmptyObject(data.extra_vars) || data.extra_vars == "\{\}" || data.extra_vars == "null" - || data.extra_vars == "" || data.extra_vars == null) { - scope.variables = "---"; - } - else { - var json_obj = JSON.parse(data.extra_vars); - scope.variables = jsyaml.safeDump(json_obj); - } - master.variables = scope.variables; - } - if (form.fields[fld].type == 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) { - scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = - data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; - master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = - scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField]; - } - } - - scope.url = data.url; - var related = data.related; - for (var set in form.related) { - if (related[set]) { - relatedSets[set] = { url: related[set], iterator: form.related[set].iterator }; - } - } - - scope['callback_url'] = data.related['callback']; - master['callback_url'] = scope['callback_url']; - - LookUpInit({ - scope: scope, - form: form, - current_item: data.inventory, - list: InventoryList, - field: 'inventory' - }); - - LookUpInit({ - url: GetBasePath('credentials') + '?kind=ssh', - scope: scope, - form: form, - current_item: data.credential, - list: CredentialList, - field: 'credential', - hdr: 'Select Machine Credential' - }); - - LookUpInit({ - scope: scope, - form: form, - current_item: data.project, - list: ProjectList, - field: 'project' - }); - - // Initialize related search functions. Doing it here to make sure relatedSets object is populated. - RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets }); - RelatedPaginateInit({ scope: scope, relatedSets: relatedSets }); - scope.$emit('jobTemplateLoaded', data.related.cloud_credential); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to retrieve job template: ' + $routeParams.id + '. GET status: ' + status }); - }); - - // Save changes to the parent - scope.formSave = function() { - generator.clearApiErrors(); - Wait('start'); - var data = {} - try { - // Make sure we have valid variable data - if (scope.parseType == 'json') { - var json_data = JSON.parse(scope.variables); //make sure JSON parses - } - else { - var json_data = jsyaml.load(scope.variables); //parse yaml - } - - // Make sure our JSON is actually an object - if (typeof json_data !== 'object') { - throw "failed to return an object!"; - } - - for (var fld in form.fields) { - if (form.fields[fld].type == 'select' && fld != 'playbook') { - data[fld] = scope[fld].value; - } - else { - if (fld != 'variables' && fld != 'callback_url') { - data[fld] = scope[fld]; - } - } - } - - data.extra_vars = JSON.stringify(json_data, undefined, '\t'); - if (data.extra_vars == "null" || data.extra_vars == null) { - data.extra_vars = ""; - } - - Rest.setUrl(defaultUrl + id + '/'); - Rest.put(data) - .success( function(data, status, headers, config) { - Wait('stop'); - var base = $location.path().replace(/^\//,'').split('/')[0]; - (base == 'job_templates') ? ReturnToCaller() : ReturnToCaller(1); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to update job template. PUT returned status: ' + status }); - }); - - } - catch(err) { - Wait('stop'); - Alert("Error", "Error parsing extra variables. Parser returned: " + err); - } - }; - - scope.showActivity = function() { Stream({ scope: scope }); } - - // Cancel - scope.formReset = function() { - generator.reset(); - for (var fld in master) { - scope[fld] = master[fld]; - } - scope.parseType = 'yaml'; - $('#forks-slider').slider("option", "value", scope.forks); - }; - - // Related set: Add button - scope.add = function(set) { - $rootScope.flashMessage = null; - $location.path('/' + base + '/' + $routeParams.id + '/' + set); - }; - - // Related set: Edit button - scope.edit = function(set, id, name) { - $rootScope.flashMessage = null; - $location.path('/' + set + '/' + id); - }; - - // Related set: Delete button - scope['delete'] = function(set, itm_id, name, title) { - $rootScope.flashMessage = null; - - var action = function() { - var url = defaultUrl + id + '/' + set + '/'; - Rest.setUrl(url); - Rest.post({ id: itm_id, disassociate: 1 }) - .success( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); - scope.search(form.related[set].iterator); - }) - .error( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status }); - }); - }; - - Prompt({ hdr: 'Delete', - body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?', - action: action + // Detect and alert user to potential SCM status issues + checkSCMStatus = function (oldValue, newValue) { + if (oldValue !== newValue && !Empty(scope.project)) { + Rest.setUrl(GetBasePath('projects') + scope.project + '/'); + Rest.get() + .success(function (data) { + var msg; + switch (data.status) { + case 'failed': + msg = "The selected project has a failed status. Review the project's SCM settings" + + " and run an update before adding it to a template."; + break; + case 'never updated': + msg = 'The selected project has a never updated status. You will need to run a successful' + + ' update in order to selected a playbook. Without a valid playbook you will not be able ' + + ' to save this template.'; + break; + case 'missing': + msg = 'The selected project has a status of missing. Please check the server and make sure ' + + ' the directory exists and file permissions are set correctly.'; + break; + } + if (msg) { + Alert('Waning', msg, 'alert-info'); + } + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, form, { + hdr: 'Error!', + msg: 'Failed to get project ' + scope.project + '. GET returned status: ' + status + }); }); - - } + } + }; + + // Register a watcher on project_name + if (scope.selectPlaybookUnregister) { + scope.selectPlaybookUnregister(); + } + scope.selectPlaybookUnregister = scope.$watch('project_name', function (oldval, newval) { + selectPlaybook(oldval, newval); + checkSCMStatus(oldval, newval); + }); + + LookUpInit({ + scope: scope, + form: form, + current_item: null, + list: ProjectList, + field: 'project' + }); + + // Save + scope.formSave = function () { + generator.clearApiErrors(); + Wait('start'); + var data = {}, json_data, fld; + try { + // Make sure we have valid variable data + if (scope.parseType === 'json') { + json_data = JSON.parse(scope.variables); //make sure JSON parses + } else { + json_data = jsyaml.load(scope.variables); //parse yaml + } + + // Make sure our JSON is actually an object + if (typeof json_data !== 'object') { + throw "failed to return an object!"; + } + + for (fld in form.fields) { + if (form.fields[fld].type === 'select' && fld !== 'playbook') { + data[fld] = scope[fld].value; + } else { + if (fld !== 'variables') { + data[fld] = scope[fld]; + } + } + } + + data.extra_vars = JSON.stringify(json_data, undefined, '\t'); + if (Empty(data.extra_vars)) { + data.extra_vars = ""; + } + + Rest.setUrl(defaultUrl); + Rest.post(data) + .success(function () { + Wait('stop'); + var base = $location.path().replace(/^\//, '').split('/')[0]; + if (base === 'job_templates') { + ReturnToCaller(); + } + ReturnToCaller(1); + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, form, { + hdr: 'Error!', + msg: 'Failed to add new job template. POST returned status: ' + status + }); + }); + + } catch (err) { + Wait('stop'); + Alert("Error", "Error parsing extra variables. Parser returned: " + err); + } + }; + + // Reset + scope.formReset = function () { + // Defaults + generator.reset(); + //$('#forks-slider').slider("option", "value", scope.forks); + for (var fld in master) { + scope[fld] = master[fld]; + } + }; } -JobTemplatesEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobTemplateForm', - 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', - 'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList', - 'ProjectList', 'LookUpInit', 'PromptPasswords', 'GetBasePath', 'md5Setup', 'ParseTypeChange', - 'JobStatusToolTip', 'FormatDate', 'Wait', 'Stream', 'Empty' - ]; +JobTemplatesAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobTemplateForm', + 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', + 'GetBasePath', 'InventoryList', 'CredentialList', 'ProjectList', 'LookUpInit', + 'md5Setup', 'ParseTypeChange', 'Wait', 'Empty' +]; + + +function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm, GenerateForm, Rest, + Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList, + CredentialList, ProjectList, LookUpInit, PromptPasswords, GetBasePath, md5Setup, ParseTypeChange, JobStatusToolTip, FormatDate, + Wait, Stream, Empty, Prompt) { + + ClearScope('htmlTemplate'); + + var defaultUrl = GetBasePath('job_templates'), + generator = GenerateForm, + form = JobTemplateForm, + scope = generator.inject(form, { mode: 'edit', related: true }), + loadingFinishedCount = 0, + base = $location.path().replace(/^\//, '').split('/')[0], + master = {}, + id = $routeParams.id, + relatedSets = {}, + checkSCMStatus, getPlaybooks; + + scope.parseType = 'yaml'; + ParseTypeChange(scope); + + // Our job type options + scope.job_type_options = [ + { value: 'run', label: 'Run' }, + { value: 'check', label: 'Check' } + ]; + + scope.verbosity_options = [ + { value: '0', label: 'Default' }, + { value: '1', label: 'Verbose' }, + { value: '3', label: 'Debug' } + ]; + + scope.playbook_options = null; + scope.playbook = null; + generator.reset(); + + getPlaybooks = function (project) { + var url; + if (!Empty(project)) { + url = GetBasePath('projects') + project + '/playbooks/'; + Wait('start'); + Rest.setUrl(url); + Rest.get() + .success(function (data) { + var i; + scope.playbook_options = []; + for (i = 0; i < data.length; i++) { + scope.playbook_options.push(data[i]); + if (data[i] === scope.playbook) { + scope.job_templates_form.playbook.$setValidity('required', true); + } + } + if (scope.playbook) { + scope.$emit('jobTemplateLoadFinished'); + } else { + Wait('stop'); + } + }) + .error(function () { + Wait('stop'); + Alert('Missing Playbooks', 'Unable to retrieve the list of playbooks for this project. Choose a different ' + + ' project or make the playbooks available on the file system.', 'alert-info'); + }); + } + }; + + // Detect and alert user to potential SCM status issues + checkSCMStatus = function () { + if (!Empty(scope.project)) { + Wait('start'); + Rest.setUrl(GetBasePath('projects') + scope.project + '/'); + Rest.get() + .success(function (data) { + var msg; + switch (data.status) { + case 'failed': + msg = "The selected project has a failed status. Review the project's SCM settings" + + " and run an update before adding it to a template."; + break; + case 'never updated': + msg = 'The selected project has a never updated status. You will need to run a successful' + + ' update in order to selected a playbook. Without a valid playbook you will not be able ' + + ' to save this template.'; + break; + case 'missing': + msg = 'The selected project has a status of missing. Please check the server and make sure ' + + ' the directory exists and file permissions are set correctly.'; + break; + } + Wait('stop'); + if (msg) { + Alert('Waning', msg, 'alert-info'); + } + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, form, { hdr: 'Error!', msg: 'Failed to get project ' + scope.project + + '. GET returned status: ' + status }); + }); + } + }; + + + // Register a watcher on project_name. Refresh the playbook list on change. + if (scope.watchProjectUnregister) { + scope.watchProjectUnregister(); + } + scope.watchProjectUnregister = scope.$watch('project_name', function (oldValue, newValue) { + if (oldValue !== newValue && newValue !== '' && newValue !== null && newValue !== undefined) { + scope.playbook = null; + getPlaybooks(scope.project); + checkSCMStatus(); + } + }); + + // Turn off 'Wait' after both cloud credential and playbook list come back + if (scope.removeJobTemplateLoadFinished) { + scope.removeJobTemplateLoadFinished(); + } + scope.removeJobTemplateLoadFinished = scope.$on('jobTemplateLoadFinished', function () { + loadingFinishedCount++; + if (loadingFinishedCount >= 2) { + // The initial template load finished. Now load related jobs, which + // will turn off the 'working' spinner. + for (var set in relatedSets) { + scope.search(relatedSets[set].iterator); + } + + } + }); + + // Set the status/badge for each related job + if (scope.removeRelatedJobs) { + scope.removeRelatedJobs(); + } + scope.removeRelatedJobs = scope.$on('relatedjobs', function () { + var i, cDate; + if (scope.jobs && scope.jobs.length) { + for (i = 0; i < scope.jobs.length; i++) { + // Convert created date to local time zone + cDate = new Date(scope.jobs[i].created); + scope.jobs[i].created = FormatDate(cDate); + // Set tooltip and link + scope.jobs[i].statusBadgeToolTip = JobStatusToolTip(scope.jobs[i].status) + + " Click to view status details."; + scope.jobs[i].statusLinkTo = '/#/jobs/' + scope.jobs[i].id; + } + } + }); + + if (scope.cloudCredentialReadyRemove) { + scope.cloudCredentialReadyRemove(); + } + scope.cloudCredentialReadyRemove = scope.$on('cloudCredentialReady', function (e, name) { + var CloudCredentialList = {}; + scope.cloud_credential_name = name; + master.cloud_credential_name = name; + // Clone the CredentialList object for use with cloud_credential. Cloning + // and changing properties to avoid collision. + jQuery.extend(true, CloudCredentialList, CredentialList); + CloudCredentialList.name = 'cloudcredentials'; + CloudCredentialList.iterator = 'cloudcredential'; + LookUpInit({ + url: GetBasePath('credentials') + '?cloud=true', + scope: scope, + form: form, + current_item: scope.cloud_credential, + list: CloudCredentialList, + field: 'cloud_credential', + hdr: 'Select Cloud Credential' + }); + scope.$emit('jobTemplateLoadFinished'); + }); + + + // Retrieve each related set and populate the playbook list + if (scope.jobTemplateLoadedRemove) { + scope.jobTemplateLoadedRemove(); + } + scope.jobTemplateLoadedRemove = scope.$on('jobTemplateLoaded', function (e, related_cloud_credential) { + var dft; + getPlaybooks(scope.project); + + dft = (scope.host_config_key === "" || scope.host_config_key === null) ? 'false' : 'true'; + md5Setup({ + scope: scope, + master: master, + check_field: 'allow_callbacks', + default_val: dft + }); + + if (related_cloud_credential) { + Rest.setUrl(related_cloud_credential); + Rest.get() + .success(function (data) { + scope.$emit('cloudCredentialReady', data.name); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, null, {hdr: 'Error!', + msg: 'Failed to related cloud credential. GET returned status: ' + status }); + }); + } else { + // No existing cloud credential + scope.$emit('cloudCredentialReady', null); + } + }); + + Wait('start'); + // Retrieve detail record and prepopulate the form + Rest.setUrl(defaultUrl + ':id/'); + Rest.get({ params: { id: id } }) + .success(function (data) { + var fld, i, json_obj, related, set; + LoadBreadCrumbs({ path: '/job_templates/' + id, title: data.name }); + for (fld in form.fields) { + if (fld !== 'variables' && data[fld] !== null && data[fld] !== undefined) { + if (form.fields[fld].type === 'select') { + if (scope[fld + '_options'] && scope[fld + '_options'].length > 0) { + for (i = 0; i < scope[fld + '_options'].length; i++) { + if (data[fld] === scope[fld + '_options'][i].value) { + scope[fld] = scope[fld + '_options'][i]; + } + } + } else { + scope[fld] = data[fld]; + } + } else { + scope[fld] = data[fld]; + } + master[fld] = scope[fld]; + } + if (fld === 'variables') { + // Parse extra_vars, converting to YAML. + if ($.isEmptyObject(data.extra_vars) || data.extra_vars === "{}" || data.extra_vars === "null" || + data.extra_vars === "" || data.extra_vars === null) { + scope.variables = "---"; + } else { + json_obj = JSON.parse(data.extra_vars); + scope.variables = jsyaml.safeDump(json_obj); + } + master.variables = scope.variables; + } + if (form.fields[fld].type === 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) { + scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = + data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; + master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = + scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField]; + } + } + + scope.url = data.url; + related = data.related; + for (set in form.related) { + if (related[set]) { + relatedSets[set] = { + url: related[set], + iterator: form.related[set].iterator + }; + } + } + + scope.callback_url = data.related.callback; + master.callback_url = scope.callback_url; + + LookUpInit({ + scope: scope, + form: form, + current_item: data.inventory, + list: InventoryList, + field: 'inventory' + }); + + LookUpInit({ + url: GetBasePath('credentials') + '?kind=ssh', + scope: scope, + form: form, + current_item: data.credential, + list: CredentialList, + field: 'credential', + hdr: 'Select Machine Credential' + }); + + LookUpInit({ + scope: scope, + form: form, + current_item: data.project, + list: ProjectList, + field: 'project' + }); + + // Initialize related search functions. Doing it here to make sure relatedSets object is populated. + RelatedSearchInit({ + scope: scope, + form: form, + relatedSets: relatedSets + }); + RelatedPaginateInit({ + scope: scope, + relatedSets: relatedSets + }); + scope.$emit('jobTemplateLoaded', data.related.cloud_credential); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, form, { + hdr: 'Error!', + msg: 'Failed to retrieve job template: ' + $routeParams.id + '. GET status: ' + status + }); + }); + + // Save changes to the parent + scope.formSave = function () { + generator.clearApiErrors(); + Wait('start'); + var data = {}, json_data, fld; + try { + // Make sure we have valid variable data + if (scope.parseType === 'json') { + json_data = JSON.parse(scope.variables); //make sure JSON parses + } else { + json_data = jsyaml.load(scope.variables); //parse yaml + } + + // Make sure our JSON is actually an object + if (typeof json_data !== 'object') { + throw "failed to return an object!"; + } + + for (fld in form.fields) { + if (form.fields[fld].type === 'select' && fld !== 'playbook') { + data[fld] = scope[fld].value; + } else { + if (fld !== 'variables' && fld !== 'callback_url') { + data[fld] = scope[fld]; + } + } + } + + data.extra_vars = JSON.stringify(json_data, undefined, '\t'); + if (data.extra_vars === "null" || data.extra_vars === null) { + data.extra_vars = ""; + } + + Rest.setUrl(defaultUrl + id + '/'); + Rest.put(data) + .success(function () { + Wait('stop'); + var base = $location.path().replace(/^\//, '').split('/')[0]; + if (base === 'job_templates') { + ReturnToCaller(); + } + ReturnToCaller(1); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, form, { + hdr: 'Error!', + msg: 'Failed to update job template. PUT returned status: ' + status + }); + }); + + } catch (err) { + Wait('stop'); + Alert("Error", "Error parsing extra variables. Parser returned: " + err); + } + }; + + scope.showActivity = function () { + Stream({ + scope: scope + }); + }; + + // Cancel + scope.formReset = function () { + generator.reset(); + for (var fld in master) { + scope[fld] = master[fld]; + } + scope.parseType = 'yaml'; + $('#forks-slider').slider("option", "value", scope.forks); + }; + + // Related set: Add button + scope.add = function (set) { + $rootScope.flashMessage = null; + $location.path('/' + base + '/' + $routeParams.id + '/' + set); + }; + + // Related set: Edit button + scope.edit = function (set, id) { + $rootScope.flashMessage = null; + $location.path('/' + set + '/' + id); + }; + + // Related set: Delete button + scope['delete'] = function (set, itm_id, name, title) { + $rootScope.flashMessage = null; + + var action = function () { + var url = defaultUrl + id + '/' + set + '/'; + Rest.setUrl(url); + Rest.post({ + id: itm_id, + disassociate: 1 + }) + .success(function () { + $('#prompt-modal').modal('hide'); + scope.search(form.related[set].iterator); + }) + .error(function (data, status) { + $('#prompt-modal').modal('hide'); + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Call to ' + url + ' failed. POST returned status: ' + status + }); + }); + }; + + Prompt({ + hdr: 'Delete', + body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?', + action: action + }); + + }; +} + +JobTemplatesEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobTemplateForm', + 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit', + 'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList', 'ProjectList', 'LookUpInit', 'PromptPasswords', + 'GetBasePath', 'md5Setup', 'ParseTypeChange', 'JobStatusToolTip', 'FormatDate', 'Wait', 'Stream', 'Empty', 'Prompt' +]; \ No newline at end of file diff --git a/awx/ui/static/js/controllers/Jobs.js b/awx/ui/static/js/controllers/Jobs.js index e652b3b886..1335709118 100644 --- a/awx/ui/static/js/controllers/Jobs.js +++ b/awx/ui/static/js/controllers/Jobs.js @@ -3,21 +3,19 @@ * * * Jobs.js - * + * * Controller functions for the Job model. * */ - /* global jsyaml:false */ - 'use strict'; -function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobList, GenerateList, LoadBreadCrumbs, Prompt, +function JobsListCtrl($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, LookUpInit, SubmitJob, FormatDate, Refresh, JobStatusToolTip, Empty, Wait) { ClearScope('htmlTemplate'); - + var list = JobList, defaultUrl = GetBasePath('jobs'), view = GenerateList, @@ -26,19 +24,19 @@ function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest, $rootScope.flashMessage = null; scope.selected = []; - + if (scope.removePostRefresh) { scope.removePostRefresh(); } - scope.removePostRefresh = scope.$on('PostRefresh', function() { - var i,cDate; - $("tr.success").each(function() { + scope.removePostRefresh = scope.$on('PostRefresh', function () { + var i, cDate; + $("tr.success").each(function () { // Make sure no rows have a green background var ngc = $(this).attr('ng-class'); scope[ngc] = ""; }); if (scope.jobs && scope.jobs.length) { - for (i=0; i < scope.jobs.length; i++) { + for (i = 0; i < scope.jobs.length; i++) { // Convert created date to local time zone cDate = new Date(scope.jobs[i].created); scope.jobs[i].created = FormatDate(cDate); @@ -49,17 +47,25 @@ function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest, } } }); - + if ($routeParams.job_host_summaries__host) { defaultUrl += '?job_host_summaries__host=' + $routeParams.job_host_summaries__host; - } - else if ($routeParams.inventory__int && $routeParams.status) { + } else if ($routeParams.inventory__int && $routeParams.status) { defaultUrl += '?inventory__int=' + $routeParams.inventory__int + '&status=' + $routeParams.status; } - SearchInit({ scope: scope, set: 'jobs', list: list, url: defaultUrl }); - PaginateInit({ scope: scope, list: list, url: defaultUrl }); + SearchInit({ + scope: scope, + set: 'jobs', + list: list, + url: defaultUrl + }); + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl + }); // Called from Inventories page, failed jobs link. Find jobs for selected inventory. if ($routeParams.inventory__int) { @@ -76,7 +82,7 @@ function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest, scope[list.iterator + 'SearchField'] = 'status'; scope[list.iterator + 'SelectShow'] = true; scope[list.iterator + 'SearchSelectOpts'] = list.fields.status.searchOptions; - scope[list.iterator + 'SearchFieldLabel'] = list.fields.status.label.replace(/
/g,' '); + scope[list.iterator + 'SearchFieldLabel'] = list.fields.status.label.replace(/
/g, ' '); for (opt in list.fields.status.searchOptions) { if (list.fields.status.searchOptions[opt].value === $routeParams.status) { scope[list.iterator + 'SearchSelectValue'] = list.fields.status.searchOptions[opt]; @@ -89,71 +95,83 @@ function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest, LoadBreadCrumbs(); - scope.refresh = function() { + scope.refresh = function () { Wait('start'); scope.jobLoading = false; - Refresh({ scope: scope, set: 'jobs', iterator: 'job', url: scope.current_url }); + Refresh({ + scope: scope, + set: 'jobs', + iterator: 'job', + url: scope.current_url + }); }; scope.refreshJob = scope.refresh; - scope.editJob = function(id, name) { - LoadBreadCrumbs({ path: '/jobs/' + id, title: id + ' - ' + name }); + scope.editJob = function (id, name) { + LoadBreadCrumbs({ + path: '/jobs/' + id, + title: id + ' - ' + name + }); $location.path($location.path() + '/' + id); }; - scope.viewEvents = function(id, name) { - LoadBreadCrumbs({ path: '/jobs/' + id, title: id + ' - ' + name }); + scope.viewEvents = function (id, name) { + LoadBreadCrumbs({ + path: '/jobs/' + id, + title: id + ' - ' + name + }); $location.path($location.path() + '/' + id + '/job_events'); }; - scope.viewSummary = function(id, name) { - LoadBreadCrumbs({ path: '/jobs/' + id, title: id + ' - ' + name }); + scope.viewSummary = function (id, name) { + LoadBreadCrumbs({ + path: '/jobs/' + id, + title: id + ' - ' + name + }); $location.path($location.path() + '/' + id + '/job_host_summaries'); }; - scope.deleteJob = function(id) { + scope.deleteJob = function (id) { Rest.setUrl(defaultUrl + id + '/'); Rest.get() - .success( function(data) { - + .success(function (data) { + var action, url, action_label, hdr; - + if (data.status === 'pending' || data.status === 'running' || data.status === 'waiting') { url = data.related.cancel; action_label = 'cancel'; hdr = 'Cancel Job'; - } - else { + } else { url = defaultUrl + id + '/'; action_label = 'delete'; hdr = 'Delete Job'; } - action = function() { + action = function () { Rest.setUrl(url); if (action_label === 'cancel') { Rest.post() - .success( function() { + .success(function () { $('#prompt-modal').modal('hide'); scope.search(list.iterator); }) - .error( function(data, status) { + .error(function (data, status) { $('#prompt-modal').modal('hide'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status }); + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url + + ' failed. POST returned status: ' + status }); }); - } - else { + } else { Rest.destroy() - .success( function() { + .success(function () { $('#prompt-modal').modal('hide'); scope.search(list.iterator); }) - .error( function(data, status) { + .error(function (data, status) { $('#prompt-modal').modal('hide'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url + + ' failed. DELETE returned status: ' + status }); }); } }; @@ -164,40 +182,46 @@ function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest, action: action }); }) - .error( function(data, status) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to get job details. GET returned status: ' + status }); + .error(function (data, status) { + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get job details. GET returned status: ' + status }); }); }; - - scope.submitJob = function(id, template) { - SubmitJob({ scope: scope, id: id, template: template }); + + scope.submitJob = function (id, template) { + SubmitJob({ + scope: scope, + id: id, + template: template + }); }; } -JobsListCtrl.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobList', - 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', - 'ProcessErrors','GetBasePath', 'LookUpInit', 'SubmitJob', 'FormatDate', 'Refresh', 'JobStatusToolTip', - 'Empty', 'Wait' - ]; +JobsListCtrl.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobList', + 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', + 'ProcessErrors', 'GetBasePath', 'LookUpInit', 'SubmitJob', 'FormatDate', 'Refresh', 'JobStatusToolTip', + 'Empty', 'Wait' +]; -function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, JobForm, GenerateForm, Rest, Alert, ProcessErrors, - LoadBreadCrumbs, RelatedSearchInit,RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList, CredentialList, +function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobForm, GenerateForm, Rest, Alert, ProcessErrors, + LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList, CredentialList, ProjectList, LookUpInit, PromptPasswords, GetBasePath, md5Setup, FormatDate, JobStatusToolTip, Wait) { - - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. - var defaultUrl= GetBasePath('jobs'), + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. + + var defaultUrl = GetBasePath('jobs'), generator = GenerateForm, form = JobForm, - scope = generator.inject(form, {mode: 'edit', related: true}), + scope = generator.inject(form, { + mode: 'edit', + related: true + }), master = {}, id = $routeParams.id, relatedSets = {}, loadingFinishedCount = 0; - + generator.reset(); scope.job_id = id; @@ -209,18 +233,17 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, var url = GetBasePath('projects') + project + '/playbooks/'; Rest.setUrl(url); Rest.get() - .success( function(data) { + .success(function (data) { scope.playbook_options = []; - for (var i=0; i < data.length; i++) { + for (var i = 0; i < data.length; i++) { scope.playbook_options.push(data[i]); } scope.$emit('jobTemplateLoadFinished'); }) - .error( function() { + .error(function () { scope.$emit('jobTemplateLoadFinished'); }); - } - else { + } else { scope.$emit('jobTemplateLoadFinished'); } } @@ -230,23 +253,23 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, if (scope.jobLoadedRemove) { scope.jobLoadedRemove(); } - scope.jobLoadedRemove = scope.$on('jobLoaded', function(e, related_cloud_credential) { - + scope.jobLoadedRemove = scope.$on('jobLoaded', function (e, related_cloud_credential) { + getPlaybooks(scope.project); scope[form.name + 'ReadOnly'] = (scope.status === 'new') ? false : true; - + $('#forks-slider').slider("option", "value", scope.forks); $('#forks-slider').slider("disable"); - $('input[type="checkbox"]').attr('disabled','disabled'); - $('input[type="radio"]').attr('disabled','disabled'); - $('#host_config_key-gen-btn').attr('disabled','disabled'); - $('textarea').attr('readonly','readonly'); + $('input[type="checkbox"]').attr('disabled', 'disabled'); + $('input[type="radio"]').attr('disabled', 'disabled'); + $('#host_config_key-gen-btn').attr('disabled', 'disabled'); + $('textarea').attr('readonly', 'readonly'); // Get job template and display/hide host callback fields Rest.setUrl(scope.template_url); Rest.get() - .success( function(data) { + .success(function (data) { var dft = (data.host_config_key) ? 'true' : 'false'; scope.host_config_key = data.host_config_key; md5Setup({ @@ -258,7 +281,7 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, scope.callback_url = (data.related) ? data.related.callback : '<< Job template not found >>'; scope.$emit('jobTemplateLoadFinished'); }) - .error( function() { + .error(function () { Wait('stop'); scope.callback_url = '<< Job template not found >>'; }); @@ -267,16 +290,17 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, //Get the name of the cloud credential Rest.setUrl(related_cloud_credential); Rest.get() - .success( function(data) { + .success(function (data) { scope.cloud_credential_name = data.name; scope.$emit('jobTemplateLoadFinished'); }) - .error( function(data, status) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to related cloud credential. GET returned status: ' + status }); + .error(function (data, status) { + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Failed to related cloud credential. GET returned status: ' + status + }); }); - } - else { + } else { scope.$emit('jobTemplateLoadFinished'); } }); @@ -285,7 +309,7 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, if (scope.removeJobTemplateLoadFinished) { scope.removeJobTemplateLoadFinished(); } - scope.removeJobTemplateLoadFinished = scope.$on('jobTemplateLoadFinished', function() { + scope.removeJobTemplateLoadFinished = scope.$on('jobTemplateLoadFinished', function () { loadingFinishedCount++; if (loadingFinishedCount >= 3) { // The initial template load finished. Now load related jobs, which @@ -295,16 +319,27 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, }); // Our job type options - scope.job_type_options = [{ value: 'run', label: 'Run' }, { value: 'check', label: 'Check' }]; - scope.verbosity_options = [ - { value: '0', label: 'Default' }, - { value: '1', label: 'Verbose' }, - { value: '3', label: 'Debug' } - ]; + scope.job_type_options = [{ + value: 'run', + label: 'Run' + }, { + value: 'check', + label: 'Check' + }]; + scope.verbosity_options = [{ + value: '0', + label: 'Default' + }, { + value: '1', + label: 'Verbose' + }, { + value: '3', + label: 'Debug' + }]; scope.playbook_options = null; scope.playbook = null; - function calcRows (content) { + function calcRows(content) { var n = content.match(/\n/g), rows = (n) ? n.length : 1; return (rows > 15) ? 15 : rows; @@ -313,8 +348,8 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, // Retrieve detail record and prepopulate the form Wait('start'); Rest.setUrl(defaultUrl + ':id/'); - Rest.get({ params: {id: id} }) - .success( function(data) { + Rest.get({ params: { id: id } }) + .success(function (data) { //LoadBreadCrumbs({ path: '/jobs/' + id, title: data.id + ' - ' + data.summary_fields.job_template.name }); var i, cDate, fld, json_obj, related, set; LoadBreadCrumbs(); @@ -322,23 +357,21 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, if (fld !== 'variables' && data[fld] !== null && data[fld] !== undefined) { if (form.fields[fld].type === 'select') { if (scope[fld + '_options'] && scope[fld + '_options'].length > 0) { - for (i=0; i < scope[fld + '_options'].length; i++) { + for (i = 0; i < scope[fld + '_options'].length; i++) { if (data[fld] === scope[fld + '_options'][i].value) { scope[fld] = scope[fld + '_options'][i]; } } - } - else { + } else { scope[fld] = data[fld]; } } - } - else { + } else { scope[fld] = data[fld]; } master[fld] = scope[fld]; } - + scope.id = data.id; scope.name = (data.summary_fields && data.summary_fields.job_template) ? data.summary_fields.job_template.name : ''; @@ -347,8 +380,7 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, if ($.isEmptyObject(data.extra_vars) || data.extra_vars === "{}" || data.extra_vars === "null" || data.extra_vars === "" || data.extra_vars === null) { scope.variables = "---"; - } - else { + } else { json_obj = JSON.parse(data.extra_vars); scope.variables = jsyaml.safeDump(json_obj); } @@ -360,23 +392,22 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField]; } - + for (fld in form.statusFields) { if (data[fld] !== null && data[fld] !== undefined) { if (fld === 'created') { // Convert created date to local time zone cDate = new Date(data.created); scope.created = FormatDate(cDate); - } - else { + } else { scope[fld] = data[fld]; } } } scope.statusToolTip = JobStatusToolTip(data.status); - - $('form[name="jobs_form"] input[type="text"], form[name="jobs_form"] jobs_form textarea').attr('readonly','readonly'); + + $('form[name="jobs_form"] input[type="text"], form[name="jobs_form"] jobs_form textarea').attr('readonly', 'readonly'); $('form[name="jobs_form"] select').prop('disabled', 'disabled'); $('form[name="jobs_form"] .lookup-btn').prop('disabled', 'disabled'); $('form[name="jobs_form"] .buttons, form[name="jobs_form"] hr').hide(); @@ -385,12 +416,15 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, related = data.related; for (set in form.related) { if (related[set]) { - relatedSets[set] = { url: related[set], iterator: form.related[set].iterator }; + relatedSets[set] = { + url: related[set], + iterator: form.related[set].iterator + }; } } scope.stdout_rows = calcRows(scope.result_stdout); - + scope.traceback_rows = calcRows(scope.result_traceback); LookUpInit({ @@ -418,21 +452,30 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, }); // Initialize related search functions. Doing it here to make sure relatedSets object is populated. - RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets }); - RelatedPaginateInit({ scope: scope, relatedSets: relatedSets }); + RelatedSearchInit({ + scope: scope, + form: form, + relatedSets: relatedSets + }); + RelatedPaginateInit({ + scope: scope, + relatedSets: relatedSets + }); scope.template_url = data.related.job_template; scope.$emit('jobLoaded', data.related.cloud_credential); }) - .error( function(data, status) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to retrieve job: ' + $routeParams.id + '. GET status: ' + status }); + .error(function (data, status) { + ProcessErrors(scope, data, status, form, { + hdr: 'Error!', + msg: 'Failed to retrieve job: ' + $routeParams.id + '. GET status: ' + status + }); }); - scope.refresh = function() { + scope.refresh = function () { Wait('start'); Rest.setUrl(defaultUrl + id + '/'); Rest.get() - .success( function(data) { + .success(function (data) { scope.status = data.status; scope.result_stdout = data.result_stdout; scope.result_traceback = data.result_traceback; @@ -440,25 +483,26 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, scope.traceback_rows = calcRows(scope.result_traceback); Wait('stop'); }) - .error( function(data, status) { + .error(function (data, status) { Wait('stop'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Attempt to load job failed. GET returned status: ' + status }); + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Attempt to load job failed. GET returned status: ' + status + }); }); }; - scope.jobSummary = function() { + scope.jobSummary = function () { $location.path('/jobs/' + id + '/job_host_summaries'); }; - scope.jobEvents = function() { + scope.jobEvents = function () { $location.path('/jobs/' + id + '/job_events'); }; } -JobsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobForm', - 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', - 'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList', - 'ProjectList', 'LookUpInit', 'PromptPasswords', 'GetBasePath', 'md5Setup', 'FormatDate', - 'JobStatusToolTip', 'Wait' - ]; +JobsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobForm', + 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit', + 'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList', 'ProjectList', 'LookUpInit', 'PromptPasswords', + 'GetBasePath', 'md5Setup', 'FormatDate', 'JobStatusToolTip', 'Wait' +]; diff --git a/awx/ui/static/js/controllers/Organizations.js b/awx/ui/static/js/controllers/Organizations.js index 6e78ccd111..6ebfce7ac6 100644 --- a/awx/ui/static/js/controllers/Organizations.js +++ b/awx/ui/static/js/controllers/Organizations.js @@ -3,276 +3,327 @@ * * * Organizations.js - * + * * Controller functions for Organization model. * */ 'use strict'; -function OrganizationsList ($routeParams, $scope, $rootScope, $location, $log, Rest, Alert, LoadBreadCrumbs, Prompt, - GenerateList, OrganizationList, SearchInit, PaginateInit, ClearScope, ProcessErrors, - GetBasePath, SelectionInit, Wait, Stream) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. +function OrganizationsList($routeParams, $scope, $rootScope, $location, $log, Rest, Alert, LoadBreadCrumbs, Prompt, + GenerateList, OrganizationList, SearchInit, PaginateInit, ClearScope, ProcessErrors, GetBasePath, SelectionInit, Wait, Stream) { + + ClearScope('htmlTemplate'); - var list = OrganizationList; - var generate = GenerateList; - var paths = $location.path().replace(/^\//,'').split('/'); - var mode = (paths[0] == 'organizations') ? 'edit' : 'select'; // if base path 'users', we're here to add/edit users - var scope = generate.inject(OrganizationList, { mode: mode }); // Inject our view - var defaultUrl = GetBasePath('organizations'); - var iterator = list.iterator; + var list = OrganizationList, + generate = GenerateList, + paths = $location.path().replace(/^\//, '').split('/'), + mode = (paths[0] === 'organizations') ? 'edit' : 'select', // if base path 'users', we're here to add/edit users + scope = generate.inject(OrganizationList, { mode: mode }), + defaultUrl = GetBasePath('organizations'), + url; + $rootScope.flashMessage = null; LoadBreadCrumbs(); - - var url = GetBasePath('projects') + $routeParams.project_id + '/organizations/'; - SelectionInit({ scope: scope, list: list, url: url, returnToCaller: 1 }); + + url = GetBasePath('projects') + $routeParams.project_id + '/organizations/'; + SelectionInit({ + scope: scope, + list: list, + url: url, + returnToCaller: 1 + }); if (scope.removePostRefresh) { - scope.removePostRefresh(); + scope.removePostRefresh(); } - scope.removePostRefresh = scope.$on('PostRefresh', function() { + scope.removePostRefresh = scope.$on('PostRefresh', function () { // Cleanup after a delete Wait('stop'); $('#prompt-modal').off(); - }); - + }); + // Initialize search and paginate pieces and load data - SearchInit({ scope: scope, set: list.name, list: list, url: defaultUrl }); - PaginateInit({ scope: scope, list: list, url: defaultUrl }); + SearchInit({ + scope: scope, + set: list.name, + list: list, + url: defaultUrl + }); + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl + }); scope.search(list.iterator); - scope.showActivity = function() { Stream({ scope: scope }); } + scope.showActivity = function () { + Stream({ + scope: scope + }); + }; - scope.addOrganization = function() { - $location.path($location.path() + '/add'); - } + scope.addOrganization = function () { + $location.path($location.path() + '/add'); + }; - scope.editOrganization = function(id) { - $location.path($location.path() + '/' + id); - } - - scope.deleteOrganization = function(id, name) { - - var action = function() { - $('#prompt-modal').on('hidden.bs.modal', function(){ Wait('start'); }); - $('#prompt-modal').modal('hide'); - var url = defaultUrl + id + '/'; - Rest.setUrl(url); - Rest.destroy() - .success( function(data, status, headers, config) { - scope.search(list.iterator); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); - }); - }; + scope.editOrganization = function (id) { + $location.path($location.path() + '/' + id); + }; - Prompt({ hdr: 'Delete', - body: 'Are you sure you want to delete ' + name + '?', - action: action + scope.deleteOrganization = function (id, name) { + + var action = function () { + $('#prompt-modal').on('hidden.bs.modal', function () { + Wait('start'); + }); + $('#prompt-modal').modal('hide'); + var url = defaultUrl + id + '/'; + Rest.setUrl(url); + Rest.destroy() + .success(function () { + scope.search(list.iterator); + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status + }); }); - } + }; + + Prompt({ + hdr: 'Delete', + body: 'Are you sure you want to delete ' + name + '?', + action: action + }); + }; } -OrganizationsList.$inject=[ '$routeParams', '$scope', '$rootScope', '$location', '$log', 'Rest', 'Alert', 'LoadBreadCrumbs', 'Prompt', - 'GenerateList', 'OrganizationList', 'SearchInit', 'PaginateInit', 'ClearScope', 'ProcessErrors', - 'GetBasePath', 'SelectionInit', 'Wait', 'Stream']; +OrganizationsList.$inject = ['$routeParams', '$scope', '$rootScope', '$location', '$log', 'Rest', 'Alert', 'LoadBreadCrumbs', 'Prompt', + 'GenerateList', 'OrganizationList', 'SearchInit', 'PaginateInit', 'ClearScope', 'ProcessErrors', + 'GetBasePath', 'SelectionInit', 'Wait', 'Stream' +]; -function OrganizationsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, - ReturnToCaller, Wait) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. +function OrganizationsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm, + GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, + ReturnToCaller, Wait) { + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. - // Inject dynamic view - 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'); - generator.reset(); + // Inject dynamic view + var generator = GenerateForm, + form = OrganizationForm, + scope = generator.inject(form, { mode: 'add', related: false }), + base = $location.path().replace(/^\//, '').split('/')[0]; + + generator.reset(); - LoadBreadCrumbs(); + LoadBreadCrumbs(); - // Save - scope.formSave = function() { - generator.clearApiErrors(); - Wait('start'); - var url = GetBasePath(base); - url += (base != 'organizations') ? $routeParams['project_id'] + '/organizations/' : ''; - Rest.setUrl(url); - Rest.post({ name: $scope.name, - description: $scope.description }) - .success( function(data, status, headers, config) { - Wait('stop'); - if (base == 'organizations') { - $rootScope.flashMessage = "New organization successfully created!"; - $location.path('/organizations/' + data.id); - } - else { - ReturnToCaller(1); - } - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to add new organization. Post returned status: ' + status }); - }); - }; - - // Cancel - scope.formReset = function() { - $rootScope.flashMessage = null; - generator.reset(); - }; -} - -OrganizationsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'OrganizationForm', - 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', - 'ReturnToCaller', 'Wait']; - - -function OrganizationsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, - RelatedPaginateInit, Prompt, ClearScope, GetBasePath, Wait, Stream) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. - - // Inject dynamic view - var form = OrganizationForm; - var generator = GenerateForm; - var scope = GenerateForm.inject(form, {mode: 'edit', related: true}); - generator.reset(); - - var defaultUrl = GetBasePath('organizations'); - var base = $location.path().replace(/^\//,'').split('/')[0]; - var master = {}; - var id = $routeParams.organization_id; - var relatedSets = {}; - - // After the Organization is loaded, retrieve each related set - if (scope.organizationLoadedRemove) { - scope.organizationLoadedRemove(); - } - scope.organizationLoadedRemove = scope.$on('organizationLoaded', function() { - for (var set in relatedSets) { - scope.search(relatedSets[set].iterator); - } - Wait('stop'); - }); - - // Retrieve detail record and prepopulate the form - Wait('start'); - Rest.setUrl(defaultUrl + id + '/'); - Rest.get() - .success( function(data, status, headers, config) { - LoadBreadCrumbs({ path: '/organizations/' + id, title: data.name }); - for (var fld in form.fields) { - if (data[fld]) { - scope[fld] = data[fld]; - master[fld] = data[fld]; - } - } - var related = data.related; - for (var set in form.related) { - if (related[set]) { - relatedSets[set] = { url: related[set], iterator: form.related[set].iterator }; - } - } - // Initialize related search functions. Doing it here to make sure relatedSets object is populated. - RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets }); - RelatedPaginateInit({ scope: scope, relatedSets: relatedSets }); - scope.$emit('organizationLoaded'); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to retrieve organization: ' + $routeParams.id + '. GET status: ' + status }); - }); - - - // Save changes to the parent - scope.formSave = function() { - generator.clearApiErrors(); - Wait('start'); - var params = {}; - for (var fld in form.fields) { - params[fld] = scope[fld]; - } - Rest.setUrl(defaultUrl + id + '/'); - Rest.put(params) - .success( function(data, status, headers, config) { - Wait('stop'); - master = params; - $rootScope.flashMessage = "Your changes were successfully saved!"; - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, OrganizationForm, - { hdr: 'Error!', msg: 'Failed to update organization: ' + id + '. PUT status: ' + status }); - }); - }; - - scope.showActivity = function() { Stream({ scope: scope }); } - - // Reset the form - scope.formReset = function() { - $rootScope.flashMessage = null; - generator.reset(); - for (var fld in master) { - scope[fld] = master[fld]; - } - }; - - // Related set: Add button - scope.add = function(set) { - $rootScope.flashMessage = null; - $location.path('/' + base + '/' + $routeParams.organization_id + '/' + set); - }; - - // Related set: Edit button - scope.edit = function(set, id, name) { - $rootScope.flashMessage = null; - $location.path('/' + set + '/' + id); - }; - - // Related set: Delete button - scope['delete'] = function(set, itm_id, name, title) { - $rootScope.flashMessage = null; - - var action = function() { - Wait('start'); - var url = defaultUrl + $routeParams.organization_id + '/' + set + '/'; - Rest.setUrl(url); - Rest.post({ id: itm_id, disassociate: 1 }) - .success( function(data, status, headers, config) { - Wait('stop'); - $('#prompt-modal').modal('hide'); - scope.search(form.related[set].iterator); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - $('#prompt-modal').modal('hide'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status }); - }); - }; - - Prompt({ hdr: 'Delete', - body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?', - action: action + // Save + scope.formSave = function () { + generator.clearApiErrors(); + Wait('start'); + var url = GetBasePath(base); + url += (base !== 'organizations') ? $routeParams.project_id + '/organizations/' : ''; + Rest.setUrl(url); + Rest.post({ + name: $scope.name, + description: $scope.description + }) + .success(function (data) { + Wait('stop'); + if (base === 'organizations') { + $rootScope.flashMessage = "New organization successfully created!"; + $location.path('/organizations/' + data.id); + } else { + ReturnToCaller(1); + } + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, form, { + hdr: 'Error!', + msg: 'Failed to add new organization. Post returned status: ' + status }); - - } + }); + }; + + // Cancel + scope.formReset = function () { + $rootScope.flashMessage = null; + generator.reset(); + }; } -OrganizationsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'OrganizationForm', - 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', - 'RelatedPaginateInit', 'Prompt', 'ClearScope', 'GetBasePath', 'Wait', 'Stream']; +OrganizationsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'OrganizationForm', + 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', + 'ReturnToCaller', 'Wait' +]; + + +function OrganizationsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm, + GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, + RelatedPaginateInit, Prompt, ClearScope, GetBasePath, Wait, Stream) { + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. + + // Inject dynamic view + var form = OrganizationForm, + generator = GenerateForm, + scope = GenerateForm.inject(form, { mode: 'edit', related: true }), + defaultUrl = GetBasePath('organizations'), + base = $location.path().replace(/^\//, '').split('/')[0], + master = {}, + id = $routeParams.organization_id, + relatedSets = {}; + + generator.reset(); + + // After the Organization is loaded, retrieve each related set + if (scope.organizationLoadedRemove) { + scope.organizationLoadedRemove(); + } + scope.organizationLoadedRemove = scope.$on('organizationLoaded', function () { + for (var set in relatedSets) { + scope.search(relatedSets[set].iterator); + } + Wait('stop'); + }); + + // Retrieve detail record and prepopulate the form + Wait('start'); + Rest.setUrl(defaultUrl + id + '/'); + Rest.get() + .success(function (data) { + var fld, related, set; + LoadBreadCrumbs({ path: '/organizations/' + id, title: data.name }); + for (fld in form.fields) { + if (data[fld]) { + scope[fld] = data[fld]; + master[fld] = data[fld]; + } + } + related = data.related; + for (set in form.related) { + if (related[set]) { + relatedSets[set] = { + url: related[set], + iterator: form.related[set].iterator + }; + } + } + // Initialize related search functions. Doing it here to make sure relatedSets object is populated. + RelatedSearchInit({ + scope: scope, + form: form, + relatedSets: relatedSets + }); + RelatedPaginateInit({ + scope: scope, + relatedSets: relatedSets + }); + scope.$emit('organizationLoaded'); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, form, { + hdr: 'Error!', + msg: 'Failed to retrieve organization: ' + $routeParams.id + '. GET status: ' + status + }); + }); + + + // Save changes to the parent + scope.formSave = function () { + var fld, params = {}; + generator.clearApiErrors(); + Wait('start'); + for (fld in form.fields) { + params[fld] = scope[fld]; + } + Rest.setUrl(defaultUrl + id + '/'); + Rest.put(params) + .success(function () { + Wait('stop'); + master = params; + $rootScope.flashMessage = "Your changes were successfully saved!"; + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, OrganizationForm, { + hdr: 'Error!', + msg: 'Failed to update organization: ' + id + '. PUT status: ' + status + }); + }); + }; + + scope.showActivity = function () { + Stream({ + scope: scope + }); + }; + + // Reset the form + scope.formReset = function () { + $rootScope.flashMessage = null; + generator.reset(); + for (var fld in master) { + scope[fld] = master[fld]; + } + }; + + // Related set: Add button + scope.add = function (set) { + $rootScope.flashMessage = null; + $location.path('/' + base + '/' + $routeParams.organization_id + '/' + set); + }; + + // Related set: Edit button + scope.edit = function (set, id) { + $rootScope.flashMessage = null; + $location.path('/' + set + '/' + id); + }; + + // Related set: Delete button + scope['delete'] = function (set, itm_id, name, title) { + $rootScope.flashMessage = null; + + var action = function () { + Wait('start'); + var url = defaultUrl + $routeParams.organization_id + '/' + set + '/'; + Rest.setUrl(url); + Rest.post({ + id: itm_id, + disassociate: 1 + }) + .success(function () { + Wait('stop'); + $('#prompt-modal').modal('hide'); + scope.search(form.related[set].iterator); + }) + .error(function (data, status) { + Wait('stop'); + $('#prompt-modal').modal('hide'); + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Call to ' + url + ' failed. POST returned status: ' + status + }); + }); + }; + + Prompt({ + hdr: 'Delete', + body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?', + action: action + }); + + }; +} + +OrganizationsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'OrganizationForm', + 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', + 'RelatedPaginateInit', 'Prompt', 'ClearScope', 'GetBasePath', 'Wait', 'Stream' +]; \ No newline at end of file diff --git a/awx/ui/static/js/controllers/Permissions.js b/awx/ui/static/js/controllers/Permissions.js index 5bacac093a..14b018d442 100644 --- a/awx/ui/static/js/controllers/Permissions.js +++ b/awx/ui/static/js/controllers/Permissions.js @@ -3,310 +3,331 @@ * * * 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, - ClearScope, ProcessErrors, GetBasePath, CheckAccess, Wait) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. - var list = PermissionList; - var base = $location.path().replace(/^\//,'').split('/')[0]; - var defaultUrl = GetBasePath(base); - defaultUrl += ($routeParams['user_id'] !== undefined) ? $routeParams['user_id'] : $routeParams['team_id']; +function PermissionsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, PermissionList, + GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, + GetBasePath, CheckAccess, Wait) { + + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + + //scope. + var list = PermissionList, + base = $location.path().replace(/^\//, '').split('/')[0], + defaultUrl = GetBasePath(base), + view = GenerateList, + scope = view.inject(list, { mode: 'edit' }); // Inject our view + + defaultUrl += ($routeParams.user_id !== undefined) ? $routeParams.user_id : $routeParams.team_id; defaultUrl += '/permissions/'; - - var view = GenerateList; - var scope = view.inject(list, { mode: 'edit' }); // Inject our view + scope.selected = []; - - CheckAccess({ scope: scope }); - + + CheckAccess({ + scope: scope + }); + if (scope.removePostRefresh) { scope.removePostRefresh(); } - scope.removePostRefresh = scope.$on('PostRefresh', function() { + scope.removePostRefresh = scope.$on('PostRefresh', function () { // Cleanup after a delete Wait('stop'); $('#prompt-modal').off(); - }); + }); - SearchInit({ scope: scope, set: 'permissions', list: list, url: defaultUrl }); - PaginateInit({ scope: scope, list: list, url: defaultUrl }); + SearchInit({ + scope: scope, + set: 'permissions', + list: list, + url: defaultUrl + }); + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl + }); scope.search(list.iterator); LoadBreadCrumbs(); - scope.addPermission = function() { - if (scope.PermissionAddAllowed) { - $location.path($location.path() + '/add'); - } - } + scope.addPermission = function () { + if (scope.PermissionAddAllowed) { + $location.path($location.path() + '/add'); + } + }; - scope.editPermission = function(id) { - $location.path($location.path() + '/' + id); - } - - scope.deletePermission = function(id, name) { - var action = function() { - $('#prompt-modal').on('hidden.bs.modal', function(){ Wait('start'); }); - $('#prompt-modal').modal('hide'); - var url = GetBasePath('base') + 'permissions/' + id + '/'; - Rest.setUrl(url); - Rest.destroy() - .success( function(data, status, headers, config) { - scope.search(list.iterator); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); - }); - }; - - if (scope.PermissionAddAllowed) { - Prompt({ hdr: 'Delete', - body: 'Are you sure you want to delete ' + name + '?', - action: action + scope.editPermission = function (id) { + $location.path($location.path() + '/' + id); + }; + + scope.deletePermission = function (id, name) { + var action = function () { + $('#prompt-modal').on('hidden.bs.modal', function () { + Wait('start'); + }); + $('#prompt-modal').modal('hide'); + var url = GetBasePath('base') + 'permissions/' + id + '/'; + Rest.setUrl(url); + Rest.destroy() + .success(function () { + scope.search(list.iterator); + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); - } - } + }); + }; + + if (scope.PermissionAddAllowed) { + Prompt({ + hdr: 'Delete', + body: 'Are you sure you want to delete ' + name + '?', + action: action + }); + } + }; } -PermissionsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'PermissionList', - 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', - 'ClearScope', 'ProcessErrors', 'GetBasePath', 'CheckAccess', 'Wait' - ]; +PermissionsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'PermissionList', + 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', + 'ClearScope', 'ProcessErrors', 'GetBasePath', 'CheckAccess', 'Wait' +]; -function PermissionsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, - GetBasePath, ReturnToCaller, InventoryList, ProjectList, LookUpInit, CheckAccess, - Wait, PermissionCategoryChange) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. +function PermissionsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm, + GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, + GetBasePath, ReturnToCaller, InventoryList, ProjectList, LookUpInit, CheckAccess, + Wait, PermissionCategoryChange) { + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. - // Inject dynamic view - var form = PermissionsForm; - var generator = GenerateForm; - var id = ($routeParams.user_id !== undefined) ? $routeParams.user_id : $routeParams.team_id; - var base = $location.path().replace(/^\//,'').split('/')[0]; - var defaultUrl = GetBasePath(base) + id + '/permissions'; - var scope = generator.inject(form, {mode: 'add', related: false}); - var master = {}; - - CheckAccess({ scope: scope }) - generator.reset(); - LoadBreadCrumbs(); - - scope['inventoryrequired'] = true; - scope['projectrequired'] = false; - scope.category = 'Inventory'; - master.category = 'Inventory'; - master.inventoryrequired = true; - master.projectrequired = false; - - LookUpInit({ - scope: scope, - form: form, - current_item: null, - list: InventoryList, - field: 'inventory' - }); + // Inject dynamic view + var form = PermissionsForm, + generator = GenerateForm, + id = ($routeParams.user_id !== undefined) ? $routeParams.user_id : $routeParams.team_id, + base = $location.path().replace(/^\//, '').split('/')[0], + scope = generator.inject(form, { mode: 'add', related: false }), + master = {}; - LookUpInit({ - scope: scope, - form: form, - current_item: null, - list: ProjectList, - field: 'project' - }); + CheckAccess({ scope: scope }); + generator.reset(); + LoadBreadCrumbs(); - // Save - scope.formSave = function() { - generator.clearApiErrors(); - Wait('start'); - if (scope.PermissionAddAllowed) { - var data = {}; - for (var fld in form.fields) { - data[fld] = scope[fld]; - } - var url = (base == 'teams') ? GetBasePath('teams') + id + '/permissions/' : GetBasePath('users') + id + '/permissions/'; - Rest.setUrl(url); - Rest.post(data) - .success( function(data, status, headers, config) { - Wait('stop'); - ReturnToCaller(1); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, PermissionsForm, - { hdr: 'Error!', msg: 'Failed to create new permission. Post returned status: ' + status }); - }); - } - else { - Alert('Access Denied', 'You do not have access to create new permission objects. Please contact a system administrator.', 'alert-danger'); - } - }; + scope.inventoryrequired = true; + scope.projectrequired = false; + scope.category = 'Inventory'; + master.category = 'Inventory'; + master.inventoryrequired = true; + master.projectrequired = false; - // Cancel - scope.formReset = function() { - $rootScope.flashMessage = null; - generator.reset(); - for (var fld in master) { - scope[fld] = master[fld]; - } - scope.selectCategory(); - }; - - scope.selectCategory = function() { PermissionCategoryChange({ scope: scope, reset: true }); }; - + LookUpInit({ + scope: scope, + form: form, + current_item: null, + list: InventoryList, + field: 'inventory' + }); - scope.selectCategory(); + LookUpInit({ + scope: scope, + form: form, + current_item: null, + list: ProjectList, + field: 'project' + }); + + // Save + scope.formSave = function () { + var fld, url, data = {}; + generator.clearApiErrors(); + Wait('start'); + if (scope.PermissionAddAllowed) { + data = {}; + for (fld in form.fields) { + data[fld] = scope[fld]; + } + url = (base === 'teams') ? GetBasePath('teams') + id + '/permissions/' : GetBasePath('users') + id + '/permissions/'; + Rest.setUrl(url); + Rest.post(data) + .success(function () { + Wait('stop'); + ReturnToCaller(1); + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, PermissionsForm, { + hdr: 'Error!', + msg: 'Failed to create new permission. Post returned status: ' + status + }); + }); + } else { + Alert('Access Denied', 'You do not have access to create new permission objects. Please contact a system administrator.', + 'alert-danger'); + } + }; + + // Cancel + scope.formReset = function () { + $rootScope.flashMessage = null; + generator.reset(); + for (var fld in master) { + scope[fld] = master[fld]; + } + scope.selectCategory(); + }; + + scope.selectCategory = function () { + PermissionCategoryChange({ + scope: scope, + reset: true + }); + }; + + + scope.selectCategory(); } -PermissionsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'PermissionsForm', - 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', - 'ReturnToCaller', 'InventoryList', 'ProjectList', 'LookUpInit', 'CheckAccess', 'Wait', - 'PermissionCategoryChange' - ]; +PermissionsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'PermissionsForm', + 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', 'ReturnToCaller', + 'InventoryList', 'ProjectList', 'LookUpInit', 'CheckAccess', 'Wait', 'PermissionCategoryChange' +]; -function PermissionsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, - ClearScope, Prompt, GetBasePath, InventoryList, ProjectList, LookUpInit, CheckAccess, - Wait, PermissionCategoryChange) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. +function PermissionsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm, + GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, + ClearScope, Prompt, GetBasePath, InventoryList, ProjectList, LookUpInit, CheckAccess, + Wait, PermissionCategoryChange) { + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. - var generator = GenerateForm; - var form = PermissionsForm; - var scope = generator.inject(form, {mode: 'edit', related: true}); - var base_id = ($routeParams.user_id !== undefined) ? $routeParams.user_id : $routeParams.team_id; - var base = $location.path().replace(/^\//,'').split('/')[0]; - var id = $routeParams.permission_id; - var defaultUrl = GetBasePath('base') + 'permissions/' + id + '/'; - generator.reset(); + var generator = GenerateForm, + form = PermissionsForm, + scope = generator.inject(form, { mode: 'edit', related: true }), + base_id = ($routeParams.user_id !== undefined) ? $routeParams.user_id : $routeParams.team_id, + id = $routeParams.permission_id, + defaultUrl = GetBasePath('base') + 'permissions/' + id + '/', + master = {}; - var master = {}; - var relatedSets = {}; - - CheckAccess({ scope: scope }); + generator.reset(); - scope.selectCategory = function(resetIn) { - var reset = (resetIn == false) ? false : true; - PermissionCategoryChange({ scope: scope, reset: reset }); } + + CheckAccess({ + scope: scope + }); - // Retrieve detail record and prepopulate the form - Wait('start'); - Rest.setUrl(defaultUrl); - Rest.get() - .success( function(data, status, headers, config) { - - LoadBreadCrumbs({ path: '/users/' + base_id + '/permissions/' + id, title: data.name }); + scope.selectCategory = function (resetIn) { + var reset = (resetIn === false) ? false : true; + PermissionCategoryChange({ scope: scope, reset: reset }); + }; - for (var fld in form.fields) { - if (data[fld]) { - if (form.fields[fld].sourceModel) { - var sourceModel = form.fields[fld].sourceModel; - var sourceField = form.fields[fld].sourceField; - scope[sourceModel + '_' + sourceField] = data.summary_fields[sourceModel][sourceField]; - master[sourceModel + '_' + sourceField] = data.summary_fields[sourceModel][sourceField]; - } - scope[fld] = data[fld]; - master[fld] = scope[fld]; - } - } + // Retrieve detail record and prepopulate the form + Wait('start'); + Rest.setUrl(defaultUrl); + Rest.get() + .success(function (data) { + var fld, sourceModel, sourceField; + LoadBreadCrumbs({ path: '/users/' + base_id + '/permissions/' + id, title: data.name }); + for (fld in form.fields) { + if (data[fld]) { + if (form.fields[fld].sourceModel) { + sourceModel = form.fields[fld].sourceModel; + sourceField = form.fields[fld].sourceField; + scope[sourceModel + '_' + sourceField] = data.summary_fields[sourceModel][sourceField]; + master[sourceModel + '_' + sourceField] = data.summary_fields[sourceModel][sourceField]; + } + scope[fld] = data[fld]; + master[fld] = scope[fld]; + } + } - scope.category = 'Deploy'; - if (data['permission_type'] != 'run' && data['permission_type'] != 'check' ) { - scope.category = 'Inventory'; - } - master['category'] = scope.category; - scope.selectCategory(false); //call without resetting scope.category value + scope.category = 'Deploy'; + if (data.permission_type !== 'run' && data.permission_type !== 'check') { + scope.category = 'Inventory'; + } + master.category = scope.category; + scope.selectCategory(false); //call without resetting scope.category value - LookUpInit({ - scope: scope, - form: form, - current_item: data.inventory, - list: InventoryList, - field: 'inventory' - }); + LookUpInit({ + scope: scope, + form: form, + current_item: data.inventory, + list: InventoryList, + field: 'inventory' + }); - LookUpInit({ - scope: scope, - form: form, - current_item: data.project, - list: ProjectList, - field: 'project' - }); + LookUpInit({ + scope: scope, + form: form, + current_item: data.project, + list: ProjectList, + field: 'project' + }); - if (!scope.PermissionAddAllowed) { - // If not a privileged user, disable access - $('form[name="permission_form"]').find('select, input, button').each(function(index){ - if ($(this).is('input') || $(this).is('select')) { - $(this).attr('readonly','readonly'); - } - if ( $(this).is('input[type="checkbox"]') || - $(this).is('input[type="radio"]') || - $(this).is('button') ) { - $(this).attr('disabled','disabled'); - } - }); - } - Wait('stop'); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to retrieve Permission: ' + id + '. GET status: ' + status }); - }); + if (!scope.PermissionAddAllowed) { + // If not a privileged user, disable access + $('form[name="permission_form"]').find('select, input, button').each(function () { + if ($(this).is('input') || $(this).is('select')) { + $(this).attr('readonly', 'readonly'); + } + if ($(this).is('input[type="checkbox"]') || + $(this).is('input[type="radio"]') || + $(this).is('button')) { + $(this).attr('disabled', 'disabled'); + } + }); + } + Wait('stop'); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, form, { hdr: 'Error!', + msg: 'Failed to retrieve Permission: ' + id + '. GET status: ' + status }); + }); - // Save changes to the parent - scope.formSave = function() { - generator.clearApiErrors(); - Wait('start'); - var data = {} - for (var fld in form.fields) { - data[fld] = scope[fld]; - } - Rest.setUrl(defaultUrl); - Rest.put(data) - .success( function(data, status, headers, config) { - Wait('stop'); - ReturnToCaller(1); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to update Permission: ' + $routeParams.id + '. PUT status: ' + status }); - }); - }; + // Save changes to the parent + scope.formSave = function () { + var fld, data = {}; + generator.clearApiErrors(); + Wait('start'); + for (fld in form.fields) { + data[fld] = scope[fld]; + } + Rest.setUrl(defaultUrl); + Rest.put(data) + .success(function () { + Wait('stop'); + ReturnToCaller(1); + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, form, { hdr: 'Error!', msg: 'Failed to update Permission: ' + + $routeParams.id + '. PUT status: ' + status }); + }); + }; - // Cancel - scope.formReset = function() { - generator.reset(); - for (var fld in master) { - scope[fld] = master[fld]; - } - scope.selectCategory(false); - }; + // Cancel + scope.formReset = function () { + generator.reset(); + for (var fld in master) { + scope[fld] = master[fld]; + } + scope.selectCategory(false); + }; } -PermissionsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'PermissionsForm', - 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', - 'ClearScope', 'Prompt', 'GetBasePath', 'InventoryList', 'ProjectList', 'LookUpInit', 'CheckAccess', - 'Wait', 'PermissionCategoryChange' - ]; - +PermissionsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'PermissionsForm', + 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'Prompt', 'GetBasePath', + 'InventoryList', 'ProjectList', 'LookUpInit', 'CheckAccess', 'Wait', 'PermissionCategoryChange' +]; \ No newline at end of file diff --git a/awx/ui/static/js/controllers/Projects.js b/awx/ui/static/js/controllers/Projects.js index 2fb4c0bff7..85de2ac90a 100644 --- a/awx/ui/static/js/controllers/Projects.js +++ b/awx/ui/static/js/controllers/Projects.js @@ -3,77 +3,81 @@ * * * Projects.js - * + * * Controller functions for the Projects model. * */ 'use strict'; -function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, ProjectList, - GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, - ClearScope, ProcessErrors, GetBasePath, SelectionInit, ProjectUpdate, ProjectStatus, - FormatDate, Refresh, Wait, Stream, GetChoices) -{ +function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, ProjectList, GenerateList, LoadBreadCrumbs, + Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, SelectionInit, ProjectUpdate, + ProjectStatus, FormatDate, Refresh, Wait, Stream, GetChoices, Empty) { + ClearScope('htmlTemplate'); - + Wait('start'); - - var list = ProjectList; - var defaultUrl = GetBasePath('projects'); - var view = GenerateList; - var base = $location.path().replace(/^\//,'').split('/')[0]; - var mode = (base == 'projects') ? 'edit' : 'select'; - var scope = view.inject(list, { mode: mode }); - + + var list = ProjectList, + defaultUrl = GetBasePath('projects'), + view = GenerateList, + base = $location.path().replace(/^\//, '').split('/')[0], + mode = (base === 'projects') ? 'edit' : 'select', + scope = view.inject(list, { mode: mode }), + url = (base === 'teams') ? GetBasePath('teams') + $routeParams.team_id + '/projects/' : defaultUrl, + choiceCount = 0; + $rootScope.flashMessage = null; scope.projectLoading = true; - var url = (base == 'teams') ? GetBasePath('teams') + $routeParams.team_id + '/projects/' : defaultUrl; - - if (mode == 'select') { - SelectionInit({ scope: scope, list: list, url: url, returnToCaller: 1 }); + if (mode === 'select') { + SelectionInit({ + scope: scope, + list: list, + url: url, + returnToCaller: 1 + }); } if (scope.removePostRefresh) { - scope.removePostRefresh(); + scope.removePostRefresh(); } - scope.removePostRefresh = scope.$on('PostRefresh', function() { + scope.removePostRefresh = scope.$on('PostRefresh', function () { // Cleanup after a delete + var j, i; Wait('stop'); $('#prompt-modal').off(); if (scope.projects) { - for (var i=0; i < scope.projects.length; i++) { - if (scope.projects[i].status == 'ok') { + for (i = 0; i < scope.projects.length; i++) { + if (scope.projects[i].status === 'ok') { scope.projects[i].status = 'n/a'; } - switch(scope.projects[i].status) { - case 'n/a': - scope.projects[i].badge = 'none'; - break; - case 'updating': - case 'successful': - case 'ok': - scope.projects[i].badge = 'false'; - break; - case 'never updated': - case 'failed': - case 'missing': - scope.projects[i].badge = 'true'; - break; + switch (scope.projects[i].status) { + case 'n/a': + scope.projects[i].badge = 'none'; + break; + case 'updating': + case 'successful': + case 'ok': + scope.projects[i].badge = 'false'; + break; + case 'never updated': + case 'failed': + case 'missing': + scope.projects[i].badge = 'true'; + break; } - scope.projects[i].last_updated = (scope.projects[i].last_updated !== null) ? - FormatDate(new Date(scope.projects[i].last_updated)) : null; + scope.projects[i].last_updated = (scope.projects[i].last_updated !== null) ? + FormatDate(new Date(scope.projects[i].last_updated)) : null; - for (var j=0; j < scope.project_scm_type_options.length; j++) { - if (scope.project_scm_type_options[j].value == scope.projects[i].scm_type) { - scope.projects[i].scm_type = scope.project_scm_type_options[j].label - if (scope.projects[i].scm_type == 'Manual') { + for (j = 0; j < scope.project_scm_type_options.length; j++) { + if (scope.project_scm_type_options[j].value === scope.projects[i].scm_type) { + scope.projects[i].scm_type = scope.project_scm_type_options[j].label; + if (scope.projects[i].scm_type === 'Manual') { scope.projects[i].scm_update_tooltip = 'Manaul projects do not require an SCM update'; scope.projects[i].scm_type_class = 'btn-disabled'; - } - else { + } else { scope.projects[i].scm_update_tooltip = "Start an SCM update"; scope.projects[i].scm_type_class = ""; } @@ -82,64 +86,71 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, } } } - }); + }); if (scope.removeChoicesHere) { - scope.removeChoicesHere(); + scope.removeChoicesHere(); } - scope.removeChoicesHere = scope.$on('choicesCompleteProject', function() { - + scope.removeChoicesHere = scope.$on('choicesCompleteProject', function () { + var opt; + list.fields.scm_type.searchOptions = scope.project_scm_type_options; list.fields.status.searchOptions = scope.project_status_options; - - if ($routeParams['scm_type'] && $routeParams['status']) { - // Request coming from home page. User wants all errors for an scm_type - defaultUrl += '?status=' + $routeParams['status']; + + if ($routeParams.scm_type && $routeParams.status) { + // Request coming from home page. User wants all errors for an scm_type + defaultUrl += '?status=' + $routeParams.status; } - SearchInit({ scope: scope, set: 'projects', list: list, url: defaultUrl }); - PaginateInit({ scope: scope, list: list, url: defaultUrl }); - - if ($routeParams['scm_type']) { + SearchInit({ + scope: scope, + set: 'projects', + list: list, + url: defaultUrl + }); + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl + }); + + if ($routeParams.scm_type) { scope[list.iterator + 'SearchField'] = 'scm_type'; scope[list.iterator + 'SelectShow'] = true; - scope[list.iterator + 'SearchSelectOpts'] = list.fields['scm_type'].searchOptions; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['scm_type'].label.replace(/\/g,' '); - for (var opt in list.fields['scm_type'].searchOptions) { - if (list.fields['scm_type'].searchOptions[opt].value == $routeParams['scm_type']) { - scope[list.iterator + 'SearchSelectValue'] = list.fields['scm_type'].searchOptions[opt]; + scope[list.iterator + 'SearchSelectOpts'] = list.fields.scm_type.searchOptions; + scope[list.iterator + 'SearchFieldLabel'] = list.fields.scm_type.label.replace(//g, ' '); + for (opt in list.fields.scm_type.searchOptions) { + if (list.fields.scm_type.searchOptions[opt].value === $routeParams.scm_type) { + scope[list.iterator + 'SearchSelectValue'] = list.fields.scm_type.searchOptions[opt]; break; } } - } - else if ($routeParams['status']) { - scope[list.iterator + 'SearchValue'] = $routeParams['status']; + } else if ($routeParams.status) { + scope[list.iterator + 'SearchValue'] = $routeParams.status; scope[list.iterator + 'SearchField'] = 'status'; scope[list.iterator + 'SelectShow'] = true; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['status'].label; - scope[list.iterator + 'SearchSelectOpts'] = list.fields['status'].searchOptions; - for (var opt in list.fields['status'].searchOptions) { - if (list.fields['status'].searchOptions[opt].value == $routeParams['status']) { - scope[list.iterator + 'SearchSelectValue'] = list.fields['status'].searchOptions[opt]; + scope[list.iterator + 'SearchFieldLabel'] = list.fields.status.label; + scope[list.iterator + 'SearchSelectOpts'] = list.fields.status.searchOptions; + for (opt in list.fields.status.searchOptions) { + if (list.fields.status.searchOptions[opt].value === $routeParams.status) { + scope[list.iterator + 'SearchSelectValue'] = list.fields.status.searchOptions[opt]; break; } } } scope.search(list.iterator); - }); - - var choiceCount = 0; + }); if (scope.removeChoicesReady) { - scope.removeChoicesReady(); + scope.removeChoicesReady(); } - scope.removeChoicesReady = scope.$on('choicesReadyProject', function() { + scope.removeChoicesReady = scope.$on('choicesReadyProject', function () { choiceCount++; - if (choiceCount == 2) { - scope.$emit('choicesCompleteProject'); + if (choiceCount === 2) { + scope.$emit('choicesCompleteProject'); } - }); - + }); + // Load options for status --used in search GetChoices({ scope: scope, @@ -147,8 +158,8 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, field: 'status', variable: 'project_status_options', callback: 'choicesReadyProject' - }); - + }); + // Load the list of options for Kind GetChoices({ scope: scope, @@ -156,555 +167,591 @@ function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, field: 'scm_type', variable: 'project_scm_type_options', callback: 'choicesReadyProject' - }); + }); LoadBreadCrumbs(); - scope.showActivity = function() { Stream({ scope: scope }); } - - scope.addProject = function() { - $location.path($location.path() + '/add'); - } + scope.showActivity = function () { + Stream({ scope: scope }); + }; - scope.editProject = function(id) { - $location.path($location.path() + '/' + id); - } + scope.addProject = function () { + $location.path($location.path() + '/add'); + }; - scope.showSCMStatus = function(id) { - // Refresh the project list - var statusCheckRemove = scope.$on('PostRefresh', function() { - var project; - for (var i=0; i < scope.projects.length; i++) { - if (scope.projects[i].id == id) { - project = scope.projects[i]; - break; - } - } - if (project.scm_type !== null) { - if (project.related.current_update) { - Wait('start'); - ProjectStatus({ project_id: id, last_update: project.related.current_update }); - } - else if (project.related.last_update) { - Wait('start'); - ProjectStatus({ project_id: id, last_update: project.related.last_update }); - } - else { - Alert('No Updates Available', 'There is no SCM update information available for this project. An update has not yet been ' + - ' completed. If you have not already done so, start an update for this project.', 'alert-info'); - } - } - else { - Alert('Missing SCM Configuration', 'The selected project is not configured for SCM. You must first edit the project, provide SCM settings, ' + - 'and then run an update.', 'alert-info'); - } - statusCheckRemove(); - }); - - // Refresh the project list so we're looking at the latest data - scope.search(list.iterator, null, false, true); - } - - scope.deleteProject = function(id, name) { - var action = function() { - $('#prompt-modal').on('hiden.bs.modal', function(){ Wait('start'); }); + scope.editProject = function (id) { + $location.path($location.path() + '/' + id); + }; + + scope.showSCMStatus = function (id) { + // Refresh the project list + var i, statusCheckRemove = scope.$on('PostRefresh', function () { + var project; + for (i= 0; i < scope.projects.length; i++) { + if (scope.projects[i].id === id) { + project = scope.projects[i]; + break; + } + } + if (project.scm_type !== null) { + if (project.related.current_update) { + Wait('start'); + ProjectStatus({ + project_id: id, + last_update: project.related.current_update + }); + } else if (project.related.last_update) { + Wait('start'); + ProjectStatus({ + project_id: id, + last_update: project.related.last_update + }); + } else { + Alert('No Updates Available', 'There is no SCM update information available for this project. An update has not yet been ' + + ' completed. If you have not already done so, start an update for this project.', 'alert-info'); + } + } else { + Alert('Missing SCM Configuration', 'The selected project is not configured for SCM. You must first edit the project, provide SCM settings, ' + + 'and then run an update.', 'alert-info'); + } + statusCheckRemove(); + }); + + // Refresh the project list so we're looking at the latest data + scope.search(list.iterator, null, false, true); + }; + + scope.deleteProject = function (id, name) { + var action = function () { + $('#prompt-modal').on('hiden.bs.modal', function () { + Wait('start'); + }); $('#prompt-modal').modal('hide'); var url = defaultUrl + id + '/'; Rest.setUrl(url); Rest.destroy() - .success( function(data, status, headers, config) { + .success(function () { scope.search(list.iterator); - }) - .error( function(data, status, headers, config) { + }) + .error(function (data, status) { Wait('stop'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); - }); - }; + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status + }); + }); + }; - Prompt({ hdr: 'Delete', + Prompt({ + hdr: 'Delete', body: 'Are you sure you want to delete ' + name + '?', action: action - }); - } + }); + }; if (scope.removeCancelUpdate) { - scope.removeCancelUpdate(); + scope.removeCancelUpdate(); } - scope.removeCancelUpdate = scope.$on('Cancel_Update', function(e, url) { + scope.removeCancelUpdate = scope.$on('Cancel_Update', function (e, url) { // Cancel the project update process - Rest.setUrl(url) + Rest.setUrl(url); Rest.post() - .success( function(data, status, headers, config) { + .success(function () { Alert('SCM Update Cancel', 'Your request to cancel the update was submitted to the task maanger.', 'alert-info'); scope.refresh(); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST status: ' + status }); - }); - }); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST status: ' + status }); + }); + }); if (scope.removeCheckCancel) { - scope.removeCheckCancel(); + scope.removeCheckCancel(); } - scope.removeCheckCancel = scope.$on('Check_Cancel', function(e, data) { + scope.removeCheckCancel = scope.$on('Check_Cancel', function (e, data) { // Check that we 'can' cancel the update var url = data.related.cancel; Rest.setUrl(url); Rest.get() - .success( function(data, status, headers, config) { + .success(function (data) { if (data.can_cancel) { - scope.$emit('Cancel_Update', url); + scope.$emit('Cancel_Update', url); + } else { + Alert('Cancel Not Allowed', 'Either you do not have access or the SCM update process completed. ' + + 'Click the Refresh button to view the latest status.', 'alert-info'); } - else { - Alert('Cancel Not Allowed', 'Either you do not have access or the SCM update process completed. Click the Refresh button to' + - ' view the latest status.', 'alert-info'); - } - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. GET status: ' + status }); - }); - }); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url + ' failed. GET status: ' + status }); + }); + }); - scope.cancelUpdate = function(id, name) { + scope.cancelUpdate = function (id, name) { // Start the cancel process - var project; - var found = false; - for (var i=0; i < scope.projects.length; i++) { - if (scope.projects[i].id == id) { - project = scope.projects[i]; - found = true; - break; + var i, project, found = false; + for (i = 0; i < scope.projects.length; i++) { + if (scope.projects[i].id === id) { + project = scope.projects[i]; + found = true; + break; } } if (found && project.related.current_update) { - Rest.setUrl(project.related.current_update); - Rest.get() - .success( function(data, status, headers, config) { - scope.$emit('Check_Cancel', data); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + project.related.current_update + ' failed. GET status: ' + status }); - }); - } - else { - Alert('Update Not Found', 'An SCM update does not appear to be running for project: ' + name + '. Click the Refresh ' + - 'button to view the latet status.', 'alert-info'); - } + Rest.setUrl(project.related.current_update); + Rest.get() + .success(function (data) { + scope.$emit('Check_Cancel', data); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Call to ' + project.related.current_update + ' failed. GET status: ' + status + }); + }); + } else { + Alert('Update Not Found', 'An SCM update does not appear to be running for project: ' + name + '. Click the Refresh ' + + 'button to view the latet status.', 'alert-info'); } + }; - scope.refresh = function() { + scope.refresh = function () { Wait('start'); - scope['projectLoading'] = false; - Refresh({ scope: scope, set: 'projects', iterator: 'project', url: scope['current_url'] }); - } + scope.projectLoading = false; + Refresh({ + scope: scope, + set: 'projects', + iterator: 'project', + url: scope.current_url + }); + }; - scope.SCMUpdate = function(project_id) { - for (var i=0; i < scope.projects.length; i++) { - if (scope.projects[i].id == project_id) { - if (scope.projects[i].scm_type == "Manual" || scope.projects[i].scm_type == "" || scope.projects[i].scm_type == null ) { - // Do not respond. Button appears greyed out as if it is disabled. Not disabled though, because we need mouse over event - // to work. So user can click, but we just won't do anything. - //Alert('Missing SCM Setup', 'Before running an SCM update, edit the project and provide the SCM access information.', 'alert-info'); - break; - } - else if (scope.projects[i].status == 'updating') { - Alert('Update in Progress', 'The SCM update process is running. Use the Refresh button to monitor the status.', 'alert-info'); - } - else { - ProjectUpdate({ scope: scope, project_id: project_id }); - } - } - } - } + scope.SCMUpdate = function (project_id) { + var i; + for (i = 0; i < scope.projects.length; i++) { + if (scope.projects[i].id === project_id) { + if (scope.projects[i].scm_type === "Manual" || Empty(scope.projects[i].scm_type)) { + // Do not respond. Button appears greyed out as if it is disabled. Not disabled though, because we need mouse over event + // to work. So user can click, but we just won't do anything. + //Alert('Missing SCM Setup', 'Before running an SCM update, edit the project and provide the SCM access information.', 'alert-info'); + break; + } else if (scope.projects[i].status === 'updating') { + Alert('Update in Progress', 'The SCM update process is running. Use the Refresh button to monitor the status.', 'alert-info'); + } else { + ProjectUpdate({ + scope: scope, + project_id: project_id + }); + } + } + } + }; } -ProjectsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'ProjectList', 'GenerateList', - 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', - 'GetBasePath', 'SelectionInit', 'ProjectUpdate', 'ProjectStatus', 'FormatDate', 'Refresh', 'Wait', 'Stream', - 'GetChoices' ]; +ProjectsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'ProjectList', 'GenerateList', + 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', 'GetBasePath', + 'SelectionInit', 'ProjectUpdate', 'ProjectStatus', 'FormatDate', 'Refresh', 'Wait', 'Stream', 'GetChoices', 'Empty' +]; -function ProjectsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, ProjectsForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, - GetBasePath, ReturnToCaller, GetProjectPath, LookUpInit, OrganizationList, - CredentialList, GetChoices, DebugForm, Wait) -{ - ClearScope('tree-form'); - ClearScope('htmlTemplate'); +function ProjectsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, ProjectsForm, + GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, + GetBasePath, ReturnToCaller, GetProjectPath, LookUpInit, OrganizationList, + CredentialList, GetChoices, DebugForm, Wait) { + ClearScope('tree-form'); + ClearScope('htmlTemplate'); - // Inject dynamic view - var form = ProjectsForm; - var generator = GenerateForm; - var base = $location.path().replace(/^\//,'').split('/')[0]; - var defaultUrl = GetBasePath('projects'); - var scope = generator.inject(form, {mode: 'add', related: false}); - var id = $routeParams.id; - var master = {}; + // Inject dynamic view + var form = ProjectsForm, + generator = GenerateForm, + base = $location.path().replace(/^\//, '').split('/')[0], + defaultUrl = GetBasePath('projects'), + scope = generator.inject(form, { mode: 'add', related: false }), + master = {}; - generator.reset(); - LoadBreadCrumbs(); - - GetProjectPath({ scope: scope, master: master }); - - if (scope.removeChoicesReady) { - scope.removeChoicesReady(); - } - scope.removeChoicesReady = scope.$on('choicesReady', function() { - for (var i=0; i < scope.scm_type_options.length; i++) { - if (scope.scm_type_options[i].value == '') { - scope['scm_type'] = scope.scm_type_options[i]; - break; - } - } - scope.scmRequired = false; - master['scm_type'] = scope['scm_type']; - }); + generator.reset(); + LoadBreadCrumbs(); - // Load the list of options for Kind - GetChoices({ + GetProjectPath({ + scope: scope, + master: master + }); + + if (scope.removeChoicesReady) { + scope.removeChoicesReady(); + } + scope.removeChoicesReady = scope.$on('choicesReady', function () { + var i; + for (i = 0; i < scope.scm_type_options.length; i++) { + if (scope.scm_type_options[i].value === '') { + scope.scm_type = scope.scm_type_options[i]; + break; + } + } + scope.scmRequired = false; + master.scm_type = scope.scm_type; + }); + + // Load the list of options for Kind + GetChoices({ scope: scope, url: defaultUrl, field: 'scm_type', variable: 'scm_type_options', callback: 'choicesReady' - }); + }); - LookUpInit({ - scope: scope, - form: form, - list: OrganizationList, - field: 'organization' - }); + LookUpInit({ + scope: scope, + form: form, + list: OrganizationList, + field: 'organization' + }); - LookUpInit({ - scope: scope, - url: GetBasePath('credentials') + '?kind=scm', - form: form, - list: CredentialList, - field: 'credential' - }); + LookUpInit({ + scope: scope, + url: GetBasePath('credentials') + '?kind=scm', + form: form, + list: CredentialList, + field: 'credential' + }); - // Save - scope.formSave = function() { - generator.clearApiErrors(); - var data = {}; - for (var fld in form.fields) { - if (form.fields[fld].type == 'checkbox_group') { - for (var i=0; i < form.fields[fld].fields.length; i++) { - data[form.fields[fld].fields[i].name] = scope[form.fields[fld].fields[i].name]; - } - } - else { - if (form.fields[fld].type !== 'alertblock') { - data[fld] = scope[fld]; - } - } - } - data.scm_type = scope.scm_type.value; - if (scope.scm_type.value !== '') { - delete data.local_path; - } - else { - data.local_path = scope.local_path.value; - } + // Save + scope.formSave = function () { + var i, fld, url, data={}; + generator.clearApiErrors(); + data = {}; + for (fld in form.fields) { + if (form.fields[fld].type === 'checkbox_group') { + for (i = 0; i < form.fields[fld].fields.length; i++) { + data[form.fields[fld].fields[i].name] = scope[form.fields[fld].fields[i].name]; + } + } else { + if (form.fields[fld].type !== 'alertblock') { + data[fld] = scope[fld]; + } + } + } + data.scm_type = scope.scm_type.value; + if (scope.scm_type.value !== '') { + delete data.local_path; + } else { + data.local_path = scope.local_path.value; + } - var url = (base == 'teams') ? GetBasePath('teams') + $routeParams.team_id + '/projects/' : defaultUrl; - Wait('start'); - Rest.setUrl(url); - Rest.post(data) - .success( function(data, status, headers, config) { - var id = data.id; - var url = GetBasePath('projects') + id + '/organizations/'; - var org = { id: scope.organization }; - Rest.setUrl(url); - Rest.post(org) - .success( function(data, status, headers, config) { - Wait('stop'); - $rootScope.flashMessage = "New project successfully created!"; - (base == 'projects') ? ReturnToCaller() : ReturnToCaller(1); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, ProjectsForm, - { hdr: 'Error!', msg: 'Failed to add organization to project. POST returned status: ' + status }); - }); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, ProjectsForm, - { hdr: 'Error!', msg: 'Failed to create new project. POST returned status: ' + status }); - }); - }; + url = (base === 'teams') ? GetBasePath('teams') + $routeParams.team_id + '/projects/' : defaultUrl; + Wait('start'); + Rest.setUrl(url); + Rest.post(data) + .success(function (data) { + var id = data.id, + url = GetBasePath('projects') + id + '/organizations/', + org = { id: scope.organization }; + Rest.setUrl(url); + Rest.post(org) + .success(function () { + Wait('stop'); + $rootScope.flashMessage = "New project successfully created!"; + if (base === 'projects') { + ReturnToCaller(); + } + ReturnToCaller(1); + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, ProjectsForm, { + hdr: 'Error!', + msg: 'Failed to add organization to project. POST returned status: ' + status + }); + }); + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, ProjectsForm, { + hdr: 'Error!', + msg: 'Failed to create new project. POST returned status: ' + status + }); + }); + }; - scope.scmChange = function() { - // When an scm_type is set, path is not required - if (scope.scm_type) { - scope.pathRequired = (scope.scm_type.value == '') ? true : false; - scope.scmRequired = (scope.scm_type.value !== '') ? true : false; - scope.scmBranchLabel = (scope.scm_type.value == 'svn') ? 'Revision #' : 'SCM Branch'; - } - } + scope.scmChange = function () { + // When an scm_type is set, path is not required + if (scope.scm_type) { + scope.pathRequired = (scope.scm_type.value === '') ? true : false; + scope.scmRequired = (scope.scm_type.value !== '') ? true : false; + scope.scmBranchLabel = (scope.scm_type.value === 'svn') ? 'Revision #' : 'SCM Branch'; + } + }; - // Cancel - scope.formReset = function() { - $rootScope.flashMessage = null; - generator.reset(); - for (var fld in master) { - scope[fld] = master[fld]; - } - scope.scmChange(); - }; + // Cancel + scope.formReset = function () { + var fld; + $rootScope.flashMessage = null; + generator.reset(); + for (fld in master) { + scope.fld = master.fld; + } + scope.scmChange(); + }; } -ProjectsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'ProjectsForm', - 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', - 'ReturnToCaller', 'GetProjectPath', 'LookUpInit', 'OrganizationList', 'CredentialList', 'GetChoices', - 'DebugForm', 'Wait' - ]; +ProjectsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'ProjectsForm', + 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', + 'ReturnToCaller', 'GetProjectPath', 'LookUpInit', 'OrganizationList', 'CredentialList', 'GetChoices', + 'DebugForm', 'Wait' +]; -function ProjectsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, ProjectsForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, - RelatedPaginateInit, Prompt, ClearScope, GetBasePath, ReturnToCaller, GetProjectPath, - Authorization, CredentialList, LookUpInit, GetChoices, Empty, DebugForm, Wait, Stream) -{ - ClearScope('tree-form'); - ClearScope('htmlTemplate'); +function ProjectsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, ProjectsForm, + GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, Prompt, + ClearScope, GetBasePath, ReturnToCaller, GetProjectPath, Authorization, CredentialList, LookUpInit, GetChoices, + Empty, DebugForm, Wait, Stream) { + + ClearScope('htmlTemplate'); - // Inject dynamic view - var form = ProjectsForm; - var generator = GenerateForm; - var scope = generator.inject(form, {mode: 'edit', related: true}); - generator.reset(); - - var defaultUrl = GetBasePath('projects') + $routeParams.id + '/'; - var base = $location.path().replace(/^\//,'').split('/')[0]; - var master = {}; - var id = $routeParams.id; - var relatedSets = {}; + // Inject dynamic view + var form = ProjectsForm, + generator = GenerateForm, + scope = generator.inject(form, { mode: 'edit', related: true }), + defaultUrl = GetBasePath('projects') + $routeParams.id + '/', + base = $location.path().replace(/^\//, '').split('/')[0], + master = {}, + id = $routeParams.id, + relatedSets = {}; - scope.project_local_paths = []; - scope.base_dir = ''; + generator.reset(); - // After the project is loaded, retrieve each related set - if (scope.projectLoadedRemove) { - scope.projectLoadedRemove(); - } - scope.projectLoadedRemove = scope.$on('projectLoaded', function() { - for (var set in relatedSets) { - scope.search(relatedSets[set].iterator); - } - - if (Authorization.getUserInfo('is_superuser') == true) { - GetProjectPath({ scope: scope, master: master }); - } - else { - var opts = []; - opts.push({ label: scope['local_path'], value: scope['local_path'] }); - scope.project_local_paths = opts; - scope.local_path = scope['project_local_paths'][0]; - scope.base_dir = 'You do not have access to view this property'; - } + scope.project_local_paths = []; + scope.base_dir = ''; - LookUpInit({ - url: GetBasePath('credentials') + '?kind=scm', - scope: scope, - form: form, - list: CredentialList, - field: 'credential' - }); + // After the project is loaded, retrieve each related set + if (scope.projectLoadedRemove) { + scope.projectLoadedRemove(); + } + scope.projectLoadedRemove = scope.$on('projectLoaded', function () { + var set, opts=[]; - scope.pathRequired = (scope.scm_type.value == '') ? true : false; - scope.scmRequired = (scope.scm_type.value !== '') ? true : false; - scope.scmBranchLabel = (scope.scm_type.value == 'svn') ? 'Revision #' : 'SCM Branch'; - Wait('stop'); - }); + for (set in relatedSets) { + scope.search(relatedSets[set].iterator); + } - if (scope.removeChoicesReady) { - scope.removeChoicesReady(); - } - scope.removeChoicesReady = scope.$on('choicesReady', function() { - // Retrieve detail record and prepopulate the form - Rest.setUrl(defaultUrl); - Rest.get({ params: {id: id} }) - .success( function(data, status, headers, config) { - LoadBreadCrumbs({ path: '/projects/' + id, title: data.name }); - for (var fld in form.fields) { - if (form.fields[fld].type == 'checkbox_group') { - for (var i=0; i < form.fields[fld].fields.length; i++) { - scope[form.fields[fld].fields[i].name] = data[form.fields[fld].fields[i].name]; - master[form.fields[fld].fields[i].name] = data[form.fields[fld].fields[i].name]; - } - } - else { - if (data[fld]) { - scope[fld] = data[fld]; - master[fld] = data[fld]; - } - } - if (fld !== 'organization' && form.fields[fld].sourceModel && - data.summary_fields && data.summary_fields[form.fields[fld].sourceModel]) { - scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = - data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; - master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = - data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; - } - } - var related = data.related; - for (var set in form.related) { - if (related[set]) { - relatedSets[set] = { url: related[set], iterator: form.related[set].iterator }; - } - } - - data.scm_type = (Empty(data.scm_type)) ? '' : data.scm_type; - - for (var i=0; i < scope.scm_type_options.length; i++) { - if (scope.scm_type_options[i].value == data.scm_type) { - scope.scm_type = scope.scm_type_options[i]; - break; - } - } - - if (scope.scm_type.value !== '') { - scope.pathRequired = false; - scope.scmRequired = true; - } - else { - scope.pathRequired = true; - scope.scmRequired = false; - } + if (Authorization.getUserInfo('is_superuser') === true) { + GetProjectPath({ scope: scope, master: master }); + } else { + opts.push({ + label: scope.local_path, + value: scope.local_path + }); + scope.project_local_paths = opts; + scope.local_path = scope.project_local_paths[0]; + scope.base_dir = 'You do not have access to view this property'; + } - master['scm_type'] = scope['scm_type']; - scope.scmBranchLabel = (scope.scm_type.value == 'svn') ? 'Revision #' : 'SCM Branch'; - - // Initialize related search functions. Doing it here to make sure relatedSets object is populated. - RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets }); - RelatedPaginateInit({ scope: scope, relatedSets: relatedSets }); - scope.$emit('projectLoaded'); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to retrieve project: ' + id + '. GET status: ' + status }); - }); - }); + LookUpInit({ + url: GetBasePath('credentials') + '?kind=scm', + scope: scope, + form: form, + list: CredentialList, + field: 'credential' + }); - // Load the list of options for Kind - Wait('start'); - GetChoices({ + scope.pathRequired = (scope.scm_type.value === '') ? true : false; + scope.scmRequired = (scope.scm_type.value !== '') ? true : false; + scope.scmBranchLabel = (scope.scm_type.value === 'svn') ? 'Revision #' : 'SCM Branch'; + Wait('stop'); + }); + + if (scope.removeChoicesReady) { + scope.removeChoicesReady(); + } + scope.removeChoicesReady = scope.$on('choicesReady', function () { + // Retrieve detail record and prepopulate the form + Rest.setUrl(defaultUrl); + Rest.get({ params: { id: id } }) + .success(function (data) { + var related, set, fld, i; + LoadBreadCrumbs({ path: '/projects/' + id, title: data.name }); + for (fld in form.fields) { + if (form.fields[fld].type === 'checkbox_group') { + for (i = 0; i < form.fields[fld].fields.length; i++) { + scope[form.fields[fld].fields[i].name] = data[form.fields[fld].fields[i].name]; + master[form.fields[fld].fields[i].name] = data[form.fields[fld].fields[i].name]; + } + } else { + if (data[fld]) { + scope[fld] = data[fld]; + master[fld] = data[fld]; + } + } + if (fld !== 'organization' && form.fields[fld].sourceModel && + data.summary_fields && data.summary_fields[form.fields[fld].sourceModel]) { + scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = + data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; + master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = + data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; + } + } + related = data.related; + for (set in form.related) { + if (related[set]) { + relatedSets[set] = { + url: related[set], + iterator: form.related[set].iterator + }; + } + } + + data.scm_type = (Empty(data.scm_type)) ? '' : data.scm_type; + + for (i = 0; i < scope.scm_type_options.length; i++) { + if (scope.scm_type_options[i].value === data.scm_type) { + scope.scm_type = scope.scm_type_options[i]; + break; + } + } + + if (scope.scm_type.value !== '') { + scope.pathRequired = false; + scope.scmRequired = true; + } else { + scope.pathRequired = true; + scope.scmRequired = false; + } + + master.scm_type = scope.scm_type; + scope.scmBranchLabel = (scope.scm_type.value === 'svn') ? 'Revision #' : 'SCM Branch'; + + // Initialize related search functions. Doing it here to make sure relatedSets object is populated. + RelatedSearchInit({ + scope: scope, + form: form, + relatedSets: relatedSets + }); + RelatedPaginateInit({ + scope: scope, + relatedSets: relatedSets + }); + scope.$emit('projectLoaded'); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, form, { + hdr: 'Error!', + msg: 'Failed to retrieve project: ' + id + '. GET status: ' + status + }); + }); + }); + + // Load the list of options for Kind + Wait('start'); + GetChoices({ url: GetBasePath('projects'), scope: scope, field: 'scm_type', variable: 'scm_type_options', callback: 'choicesReady' - }); + }); - // Save changes to the parent - scope.formSave = function() { - generator.clearApiErrors(); - Wait('start'); - $rootScope.flashMessage = null; - var params = {}; - for (var fld in form.fields) { - if (form.fields[fld].type == 'checkbox_group') { - for (var i=0; i < form.fields[fld].fields.length; i++) { - params[form.fields[fld].fields[i].name] = scope[form.fields[fld].fields[i].name]; - } - } - else { - if (form.fields[fld].type !== 'alertblock') { - params[fld] = scope[fld]; - } - } - } - - params.scm_type = scope.scm_type.value; - if (scope.scm_type.value !== '') { - delete params.local_path; - } - else { - params.local_path = scope.local_path.value; - } + // Save changes to the parent + scope.formSave = function () { + var fld, i, params; + generator.clearApiErrors(); + Wait('start'); + $rootScope.flashMessage = null; + params = {}; + for (fld in form.fields) { + if (form.fields[fld].type === 'checkbox_group') { + for (i = 0; i < form.fields[fld].fields.length; i++) { + params[form.fields[fld].fields[i].name] = scope[form.fields[fld].fields[i].name]; + } + } else { + if (form.fields[fld].type !== 'alertblock') { + params[fld] = scope[fld]; + } + } + } - Rest.setUrl(defaultUrl); - Rest.put(params) - .success( function(data, status, headers, config) { + params.scm_type = scope.scm_type.value; + if (scope.scm_type.value !== '') { + delete params.local_path; + } else { + params.local_path = scope.local_path.value; + } + + Rest.setUrl(defaultUrl); + Rest.put(params) + .success(function() { Wait('stop'); ReturnToCaller(); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to update project: ' + id + '. PUT status: ' + status }); - }); - }; + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, form, { hdr: 'Error!', msg: 'Failed to update project: ' + id + '. PUT status: ' + status }); + }); + }; - scope.showActivity = function() { Stream({ scope: scope }); } + scope.showActivity = function () { + Stream({ + scope: scope + }); + }; - // Related set: Add button - scope.add = function(set) { - $rootScope.flashMessage = null; - $location.path('/' + base + '/' + $routeParams.id + '/' + set); - }; + // Related set: Add button + scope.add = function (set) { + $rootScope.flashMessage = null; + $location.path('/' + base + '/' + $routeParams.id + '/' + set); + }; - // Related set: Edit button - scope.edit = function(set, id, name) { - $rootScope.flashMessage = null; - $location.path('/' + set + '/' + id); - }; + // Related set: Edit button + scope.edit = function (set, id) { + $rootScope.flashMessage = null; + $location.path('/' + set + '/' + id); + }; - // Related set: Delete button - scope['delete'] = function(set, itm_id, name, title) { - var action = function() { - var url = GetBasePath('projects') + id + '/' + set + '/'; - $rootScope.flashMessage = null; - Rest.setUrl(url); - Rest.post({ id: itm_id, disassociate: 1 }) - .success( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); - scope.search(form.related[set].iterator); - }) - .error( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status }); - }); - }; + // Related set: Delete button + scope['delete'] = function (set, itm_id, name, title) { + var action = function () { + var url = GetBasePath('projects') + id + '/' + set + '/'; + $rootScope.flashMessage = null; + Rest.setUrl(url); + Rest.post({ id: itm_id, disassociate: 1 }) + .success(function () { + $('#prompt-modal').modal('hide'); + scope.search(form.related[set].iterator); + }) + .error(function (data, status) { + $('#prompt-modal').modal('hide'); + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status }); + }); + }; - Prompt({ hdr: 'Delete', - body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?', - action: action - }); - } - - scope.scmChange = function() { - if (scope.scm_type) { - scope.pathRequired = (scope.scm_type.value == '') ? true : false; - scope.scmRequired = (scope.scm_type.value !== '') ? true : false; - scope.scmBranchLabel = (scope.scm_type.value == 'svn') ? 'Revision #' : 'SCM Branch'; - } - } + Prompt({ + hdr: 'Delete', + body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?', + action: action + }); + }; - // Reset the form - scope.formReset = function() { - $rootScope.flashMessage = null; - generator.reset(); - for (var fld in master) { - scope[fld] = master[fld]; - } - scope.scmChange(); - //DebugForm({ scope: scope, form: form }); - }; + scope.scmChange = function () { + if (scope.scm_type) { + scope.pathRequired = (scope.scm_type.value === '') ? true : false; + scope.scmRequired = (scope.scm_type.value !== '') ? true : false; + scope.scmBranchLabel = (scope.scm_type.value === 'svn') ? 'Revision #' : 'SCM Branch'; + } + }; + + // Reset the form + scope.formReset = function () { + $rootScope.flashMessage = null; + generator.reset(); + for (var fld in master) { + scope[fld] = master[fld]; + } + scope.scmChange(); + }; } -ProjectsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'ProjectsForm', - 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', - 'RelatedPaginateInit', 'Prompt', 'ClearScope', 'GetBasePath', 'ReturnToCaller', - 'GetProjectPath', 'Authorization', 'CredentialList', 'LookUpInit', 'GetChoices', 'Empty', - 'DebugForm', 'Wait', 'Stream' - ]; +ProjectsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'ProjectsForm', 'GenerateForm', + 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit', 'Prompt', 'ClearScope', + 'GetBasePath', 'ReturnToCaller', 'GetProjectPath', 'Authorization', 'CredentialList', 'LookUpInit', 'GetChoices', 'Empty', + 'DebugForm', 'Wait', 'Stream' +]; \ No newline at end of file diff --git a/awx/ui/static/js/controllers/Teams.js b/awx/ui/static/js/controllers/Teams.js index bc85bf9eb5..74d68afa2e 100644 --- a/awx/ui/static/js/controllers/Teams.js +++ b/awx/ui/static/js/controllers/Teams.js @@ -3,353 +3,383 @@ * * * Teams.js - * + * * Controller functions for the Team model. * */ - + 'use strict'; -function TeamsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, TeamList, - GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, - ClearScope, ProcessErrors, SetTeamListeners, GetBasePath, SelectionInit, Wait, Stream) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. - var list = TeamList; - var defaultUrl = GetBasePath('teams'); - var view = GenerateList; - var paths = $location.path().replace(/^\//,'').split('/'); - var mode = (paths[0] == 'teams') ? 'edit' : 'select'; // if base path 'teams', we're here to add/edit teams - var scope = view.inject(list, { mode: mode }); // Inject our view - scope.selected = []; +function TeamsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, TeamList, GenerateList, LoadBreadCrumbs, + Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, SetTeamListeners, GetBasePath, SelectionInit, Wait, + Stream) { - var url = GetBasePath('base') + $location.path() + '/'; - SelectionInit({ scope: scope, list: list, url: url, returnToCaller: 1 }); - - if (scope.removePostRefresh) { - scope.removePostRefresh(); - } - scope.removePostRefresh = scope.$on('PostRefresh', function() { - // After a refresh, populate the organization name on each row - if (scope.teams) { - for ( var i=0; i < scope.teams.length; i++) { - scope.teams[i].organization_name = scope.teams[i].summary_fields.organization.name; - } - } - }); + ClearScope('htmlTemplate'); - SearchInit({ scope: scope, set: 'teams', list: list, url: defaultUrl }); - PaginateInit({ scope: scope, list: list, url: defaultUrl }); + var list = TeamList, + defaultUrl = GetBasePath('teams'), + view = GenerateList, + paths = $location.path().replace(/^\//, '').split('/'), + mode = (paths[0] === 'teams') ? 'edit' : 'select', // if base path 'teams', we're here to add/edit teams + scope = view.inject(list, { mode: mode }), + url; + + scope.selected = []; + + url = GetBasePath('base') + $location.path() + '/'; + SelectionInit({ + scope: scope, + list: list, + url: url, + returnToCaller: 1 + }); + + if (scope.removePostRefresh) { + scope.removePostRefresh(); + } + scope.removePostRefresh = scope.$on('PostRefresh', function () { + // After a refresh, populate the organization name on each row + var i; + if (scope.teams) { + for (i = 0; i < scope.teams.length; i++) { + scope.teams[i].organization_name = scope.teams[i].summary_fields.organization.name; + } + } + }); + + SearchInit({ + scope: scope, + set: 'teams', + list: list, + url: defaultUrl + }); + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl + }); scope.search(list.iterator); LoadBreadCrumbs(); - scope.showActivity = function() { Stream({ scope: scope }); } - - scope.addTeam = function() { - $location.path($location.path() + '/add'); - } + scope.showActivity = function () { + Stream({ + scope: scope + }); + }; - scope.editTeam = function(id) { - $location.path($location.path() + '/' + id); - } - - scope.deleteTeam = function(id, name) { - - var action = function() { - Wait('start'); - var url = defaultUrl + id + '/'; - Rest.setUrl(url); - Rest.destroy() - .success( function(data, status, headers, config) { - Wait('stop'); - $('#prompt-modal').modal('hide'); - scope.search(list.iterator); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - $('#prompt-modal').modal('hide'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); - }); - }; + scope.addTeam = function () { + $location.path($location.path() + '/add'); + }; - Prompt({ hdr: 'Delete', - body: 'Are you sure you want to delete ' + name + '?', - action: action + scope.editTeam = function (id) { + $location.path($location.path() + '/' + id); + }; + + scope.deleteTeam = function (id, name) { + + var action = function () { + Wait('start'); + var url = defaultUrl + id + '/'; + Rest.setUrl(url); + Rest.destroy() + .success(function () { + Wait('stop'); + $('#prompt-modal').modal('hide'); + scope.search(list.iterator); + }) + .error(function (data, status) { + Wait('stop'); + $('#prompt-modal').modal('hide'); + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status + }); }); - } - - /* - scope.lookupOrganization = function(organization_id) { - Rest.setUrl(GetBasePath('organizations') + organization_id + '/'); - Rest.get() - .success( function(data, status, headers, config) { - return data.name; - }); - } - */ - + }; + + Prompt({ + hdr: 'Delete', + body: 'Are you sure you want to delete ' + name + '?', + action: action + }); + }; } -TeamsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'TeamList', 'GenerateList', - 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', - 'SetTeamListeners', 'GetBasePath', 'SelectionInit', 'Wait', 'Stream' ]; +TeamsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'TeamList', 'GenerateList', + 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', + 'SetTeamListeners', 'GetBasePath', 'SelectionInit', 'Wait', 'Stream' +]; -function TeamsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, GenerateForm, - Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateList, - OrganizationList, SearchInit, PaginateInit, GetBasePath, LookUpInit, Wait) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. +function TeamsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, GenerateForm, + Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateList, + OrganizationList, SearchInit, PaginateInit, GetBasePath, LookUpInit, Wait) { + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. - // Inject dynamic view - var defaultUrl = GetBasePath('teams'); - var form = TeamForm; - var generator = GenerateForm; - var scope = generator.inject(form, {mode: 'add', related: false}); - $rootScope.flashMessage = null; - generator.reset(); - LoadBreadCrumbs(); - - LookUpInit({ - scope: scope, - form: form, - current_item: null, - list: OrganizationList, - field: 'organization' - }); - - // Save - scope.formSave = function() { - generator.clearApiErrors(); - Wait('start'); - Rest.setUrl(defaultUrl); - var data = {} - for (var fld in form.fields) { - data[fld] = scope[fld]; - } - Rest.post(data) - .success( function(data, status, headers, config) { - Wait('stop'); - $rootScope.flashMessage = "New team successfully created!"; - $location.path('/teams/' + data.id); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to add new team. Post returned status: ' + status }); - }); - }; + // Inject dynamic view + var defaultUrl = GetBasePath('teams'), + form = TeamForm, + generator = GenerateForm, + scope = generator.inject(form, { mode: 'add', related: false }); + + $rootScope.flashMessage = null; + generator.reset(); + LoadBreadCrumbs(); - // Reset - scope.formReset = function() { - // Defaults - generator.reset(); - }; + LookUpInit({ + scope: scope, + form: form, + current_item: null, + list: OrganizationList, + field: 'organization' + }); + + // Save + scope.formSave = function () { + var fld, data; + generator.clearApiErrors(); + Wait('start'); + Rest.setUrl(defaultUrl); + data = {}; + for (fld in form.fields) { + data[fld] = scope[fld]; + } + Rest.post(data) + .success(function (data) { + Wait('stop'); + $rootScope.flashMessage = "New team successfully created!"; + $location.path('/teams/' + data.id); + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, form, { hdr: 'Error!', msg: 'Failed to add new team. Post returned status: ' + + status }); + }); + }; + + // Reset + scope.formReset = function () { + // Defaults + generator.reset(); + }; } -TeamsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'TeamForm', 'GenerateForm', - 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList', - 'OrganizationList', 'SearchInit', 'PaginateInit', 'GetBasePath', 'LookUpInit', 'Wait']; +TeamsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'TeamForm', 'GenerateForm', + 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList', + 'OrganizationList', 'SearchInit', 'PaginateInit', 'GetBasePath', 'LookUpInit', 'Wait' +]; -function TeamsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, - RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInit, Prompt, - GetBasePath, CheckAccess, OrganizationList, Wait, Stream) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. +function TeamsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, + GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, + RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInit, Prompt, + GetBasePath, CheckAccess, OrganizationList, Wait, Stream) { + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. - var defaultUrl=GetBasePath('teams'); - var generator = GenerateForm; - var form = TeamForm; - var scope = generator.inject(form, {mode: 'edit', related: true}); - generator.reset(); - - var base = $location.path().replace(/^\//,'').split('/')[0]; - var master = {}; - var id = $routeParams.team_id; - var relatedSets = {}; + var defaultUrl = GetBasePath('teams'), + generator = GenerateForm, + form = TeamForm, + scope = generator.inject(form, { mode: 'edit', related: true }), + base = $location.path().replace(/^\//, '').split('/')[0], + master = {}, + id = $routeParams.team_id, + relatedSets = {}; - scope.PermissionAddAllowed = false; - - // Retrieve each related set and any lookups - if (scope.teamLoadedRemove) { - scope.teamLoadedRemove(); - } - scope.teamLoadedRemove = scope.$on('teamLoaded', function() { - CheckAccess({ scope: scope }); - Rest.setUrl(scope['organization_url']); - Rest.get() - .success( function(data, status, headers, config) { - scope['organization_name'] = data.name; - master['organization_name'] = data.name; - Wait('stop'); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to retrieve organization: ' + scope.orgnization_url + '. GET status: ' + status }); - }); - for (var set in relatedSets) { - scope.search(relatedSets[set].iterator); - } - }); + generator.reset(); - // Retrieve detail record and prepopulate the form - Wait('start'); - Rest.setUrl(defaultUrl + ':id/'); - Rest.get({ params: {id: id} }) - .success( function(data, status, headers, config) { - LoadBreadCrumbs({ path: '/teams/' + id, title: data.name }); - for (var fld in form.fields) { - if (data[fld]) { - scope[fld] = data[fld]; - master[fld] = scope[fld]; - } - } - var related = data.related; - for (var set in form.related) { - if (related[set]) { - relatedSets[set] = { url: related[set], iterator: form.related[set].iterator }; - } - } - // Initialize related search functions. Doing it here to make sure relatedSets object is populated. - RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets }); - RelatedPaginateInit({ scope: scope, relatedSets: relatedSets }); + scope.PermissionAddAllowed = false; - LookUpInit({ - scope: scope, - form: form, - current_item: data['organization'], - list: OrganizationList, - field: 'organization' - }); + // Retrieve each related set and any lookups + if (scope.teamLoadedRemove) { + scope.teamLoadedRemove(); + } + scope.teamLoadedRemove = scope.$on('teamLoaded', function () { + CheckAccess({ scope: scope }); + Rest.setUrl(scope.organization_url); + Rest.get() + .success(function (data) { + scope.organization_name = data.name; + master.organization_name = data.name; + Wait('stop'); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve organization: ' + + scope.orgnization_url + '. GET status: ' + status }); + }); + for (var set in relatedSets) { + scope.search(relatedSets[set].iterator); + } + }); - scope['organization_url'] = data.related.organization; - scope.$emit('teamLoaded'); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to retrieve team: ' + $routeParams.team_id + '. GET status: ' + status }); - }); + // Retrieve detail record and prepopulate the form + Wait('start'); + Rest.setUrl(defaultUrl + ':id/'); + Rest.get({ + params: { + id: id + } + }) + .success(function (data) { + var fld, related, set; + LoadBreadCrumbs({ path: '/teams/' + id, title: data.name }); + for (fld in form.fields) { + if (data[fld]) { + scope[fld] = data[fld]; + master[fld] = scope[fld]; + } + } + related = data.related; + for (set in form.related) { + if (related[set]) { + relatedSets[set] = { + url: related[set], + iterator: form.related[set].iterator + }; + } + } + // Initialize related search functions. Doing it here to make sure relatedSets object is populated. + RelatedSearchInit({ + scope: scope, + form: form, + relatedSets: relatedSets + }); + RelatedPaginateInit({ + scope: scope, + relatedSets: relatedSets + }); - scope.showActivity = function() { Stream({ scope: scope }); } - - // Save changes to the parent - scope.formSave = function() { - generator.clearApiErrors(); - Wait('start'); - $rootScope.flashMessage = null; - Rest.setUrl(defaultUrl + $routeParams.team_id +'/'); - var data = {} - for (var fld in form.fields) { - data[fld] = scope[fld]; - } - Rest.put(data) - .success( function(data, status, headers, config) { - Wait('stop'); - var base = $location.path().replace(/^\//,'').split('/')[0]; - (base == 'teams') ? ReturnToCaller() : ReturnToCaller(1); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to update team: ' + $routeParams.team_id + '. PUT status: ' + status }); - }); - }; + LookUpInit({ + scope: scope, + form: form, + current_item: data.organization, + list: OrganizationList, + field: 'organization' + }); - // Cancel - scope.formReset = function() { - $rootScope.flashMessage = null; - generator.reset(); - for (var fld in master) { - scope[fld] = master[fld]; - } - }; + scope.organization_url = data.related.organization; + scope.$emit('teamLoaded'); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, form, { hdr: 'Error!', msg: 'Failed to retrieve team: ' + $routeParams.team_id + + '. GET status: ' + status }); + }); - // Related set: Add button - scope.add = function(set) { - $rootScope.flashMessage = null; - if (set == 'permissions') { - if (scope.PermissionAddAllowed) { - $location.path('/' + base + '/' + $routeParams.team_id + '/' + set + '/add'); - } - else { - Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.'); - } - } - else { - $location.path('/' + base + '/' + $routeParams.team_id + '/' + set); - } - }; + scope.showActivity = function () { + Stream({ + scope: scope + }); + }; - // Related set: Edit button - scope.edit = function(set, id, name) { - $rootScope.flashMessage = null; - if (set == 'permissions') { - $location.path('/' + base + '/' + $routeParams.team_id + '/' + set + '/' + id); - } - else { - $location.path('/' + set + '/' + id); - } - }; + // Save changes to the parent + scope.formSave = function () { + var data = {}, fld; + generator.clearApiErrors(); + Wait('start'); + $rootScope.flashMessage = null; + Rest.setUrl(defaultUrl + $routeParams.team_id + '/'); + for (fld in form.fields) { + data[fld] = scope[fld]; + } + Rest.put(data) + .success(function () { + Wait('stop'); + var base = $location.path().replace(/^\//, '').split('/')[0]; + if (base === 'teams') { + ReturnToCaller(); + } + ReturnToCaller(1); + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, form, { hdr: 'Error!', + msg: 'Failed to update team: ' + $routeParams.team_id + '. PUT status: ' + status }); + }); + }; - // Related set: Delete button - scope['delete'] = function(set, itm_id, name, title) { - $rootScope.flashMessage = null; - - var action = function() { - var url; - if (set == 'permissions') { - if (scope.PermissionAddAllowed) { - url = GetBasePath('base') + 'permissions/' + itm_id + '/'; - Rest.setUrl(url); - Rest.destroy() - .success( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); - scope.search(form.related[set].iterator); - }) - .error( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); + // Cancel + scope.formReset = function () { + $rootScope.flashMessage = null; + generator.reset(); + for (var fld in master) { + scope[fld] = master[fld]; + } + }; + + // Related set: Add button + scope.add = function (set) { + $rootScope.flashMessage = null; + if (set === 'permissions') { + if (scope.PermissionAddAllowed) { + $location.path('/' + base + '/' + $routeParams.team_id + '/' + set + '/add'); + } else { + Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.'); + } + } else { + $location.path('/' + base + '/' + $routeParams.team_id + '/' + set); + } + }; + + // Related set: Edit button + scope.edit = function (set, id) { + $rootScope.flashMessage = null; + if (set === 'permissions') { + $location.path('/' + base + '/' + $routeParams.team_id + '/' + set + '/' + id); + } else { + $location.path('/' + set + '/' + id); + } + }; + + // Related set: Delete button + scope['delete'] = function (set, itm_id, name, title) { + $rootScope.flashMessage = null; + + var action = function () { + var url; + if (set === 'permissions') { + if (scope.PermissionAddAllowed) { + url = GetBasePath('base') + 'permissions/' + itm_id + '/'; + Rest.setUrl(url); + Rest.destroy() + .success(function () { + $('#prompt-modal').modal('hide'); + scope.search(form.related[set].iterator); + }) + .error(function (data, status) { + $('#prompt-modal').modal('hide'); + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url + + ' failed. DELETE returned status: ' + status }); }); - } - else { - Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.'); - } - } - else { - var url = defaultUrl + $routeParams.team_id + '/' + set + '/'; - Rest.setUrl(url); - Rest.post({ id: itm_id, disassociate: 1 }) - .success( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); - scope.search(form.related[set].iterator); - }) - .error( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status }); - }); - } - }; - - Prompt({ hdr: 'Delete', - body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?', - action: action - }); - } + } else { + Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.'); + } + } else { + url = defaultUrl + $routeParams.team_id + '/' + set + '/'; + Rest.setUrl(url); + Rest.post({ id: itm_id, disassociate: 1 }) + .success(function () { + $('#prompt-modal').modal('hide'); + scope.search(form.related[set].iterator); + }) + .error(function (data, status) { + $('#prompt-modal').modal('hide'); + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url + + ' failed. POST returned status: ' + status }); + }); + } + }; + Prompt({ + hdr: 'Delete', + body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?', + action: action + }); + }; } -TeamsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'TeamForm', - 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', - 'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'LookUpInit', 'Prompt', - 'GetBasePath', 'CheckAccess', 'OrganizationList', 'Wait', 'Stream' - ]; - +TeamsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'TeamForm', + 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit', + 'ReturnToCaller', 'ClearScope', 'LookUpInit', 'Prompt', 'GetBasePath', 'CheckAccess', 'OrganizationList', 'Wait', 'Stream' +]; \ No newline at end of file diff --git a/awx/ui/static/js/controllers/Users.js b/awx/ui/static/js/controllers/Users.js index 50b157a2f9..0c981247f8 100644 --- a/awx/ui/static/js/controllers/Users.js +++ b/awx/ui/static/js/controllers/Users.js @@ -3,453 +3,480 @@ * * * Users.js - * + * * Controller functions for User model. * */ - 'use strict'; -function UsersList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, UserList, - GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, - ClearScope, ProcessErrors, GetBasePath, SelectionInit, Wait, Stream) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. +function UsersList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, UserList, GenerateList, LoadBreadCrumbs, + Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, SelectionInit, Wait, Stream) { + + ClearScope('htmlTemplate'); + + var list = UserList, + defaultUrl = GetBasePath('users'), + view = GenerateList, + base = $location.path().replace(/^\//, '').split('/')[0], + mode = (base === 'users') ? 'edit' : 'select', // if base path 'users', we're here to add/edit users + scope = view.inject(UserList, { mode: mode }), + url = (base === 'organizations') ? GetBasePath('organizations') + $routeParams.organization_id + '/users/' : + GetBasePath('teams') + $routeParams.team_id + '/users/'; - var list = UserList; - var defaultUrl = GetBasePath('users'); - var view = GenerateList; - var base = $location.path().replace(/^\//,'').split('/')[0]; - var mode = (base == 'users') ? 'edit' : 'select'; // if base path 'users', we're here to add/edit users - var scope = view.inject(UserList, { mode: mode }); // Inject our view scope.selected = []; - var url = (base == 'organizations') ? GetBasePath('organizations') + $routeParams.organization_id + '/users/' : - GetBasePath('teams') + $routeParams.team_id + '/users/'; - SelectionInit({ scope: scope, list: list, url: url, returnToCaller: 1 }); + SelectionInit({ + scope: scope, + list: list, + url: url, + returnToCaller: 1 + }); if (scope.removePostRefresh) { - scope.removePostRefresh(); + scope.removePostRefresh(); } - scope.removePostRefresh = scope.$on('PostRefresh', function() { + scope.removePostRefresh = scope.$on('PostRefresh', function () { // Cleanup after a delete Wait('stop'); $('#prompt-modal').off(); - }); + }); $rootScope.flashMessage = null; - SearchInit({ scope: scope, set: 'users', list: list, url: defaultUrl }); - PaginateInit({ scope: scope, list: list, url: defaultUrl }); + SearchInit({ + scope: scope, + set: 'users', + list: list, + url: defaultUrl + }); + PaginateInit({ + scope: scope, + list: list, + url: defaultUrl + }); scope.search(list.iterator); LoadBreadCrumbs(); - - scope.showActivity = function() { Stream({ scope: scope }); } - - scope.addUser = function() { - $location.path($location.path() + '/add'); - } - scope.editUser = function(id) { - $location.path($location.path() + '/' + id); - } - - scope.deleteUser = function(id, name) { - - var action = function() { - $('#prompt-modal').on('hidden.bs.modal', function(){ Wait('start'); }); - $('#prompt-modal').modal('hide'); - var url = defaultUrl + id + '/'; - Rest.setUrl(url); - Rest.destroy() - .success( function(data, status, headers, config) { - scope.search(list.iterator); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); - }); - }; + scope.showActivity = function () { + Stream({ + scope: scope + }); + }; - Prompt({ hdr: 'Delete', - body: 'Are you sure you want to delete ' + name + '?', - action: action + scope.addUser = function () { + $location.path($location.path() + '/add'); + }; + + scope.editUser = function (id) { + $location.path($location.path() + '/' + id); + }; + + scope.deleteUser = function (id, name) { + + var action = function () { + $('#prompt-modal').on('hidden.bs.modal', function () { + Wait('start'); + }); + $('#prompt-modal').modal('hide'); + var url = defaultUrl + id + '/'; + Rest.setUrl(url); + Rest.destroy() + .success(function () { + scope.search(list.iterator); + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + + status }); }); - } + }; + + Prompt({ + hdr: 'Delete', + body: 'Are you sure you want to delete ' + name + '?', + action: action + }); + }; } -UsersList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'UserList', 'GenerateList', - 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', - 'GetBasePath', 'SelectionInit', 'Wait', 'Stream']; +UsersList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'UserList', 'GenerateList', + 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', 'GetBasePath', + 'SelectionInit', 'Wait', 'Stream' +]; -function UsersAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, - GetBasePath, LookUpInit, OrganizationList, ResetForm, Wait) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. +function UsersAdd($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm, GenerateForm, Rest, Alert, ProcessErrors, + LoadBreadCrumbs, ReturnToCaller, ClearScope, GetBasePath, LookUpInit, OrganizationList, ResetForm, Wait) { + + ClearScope('htmlTemplate'); - // Inject dynamic view - var defaultUrl = GetBasePath('organizations'); - var form = UserForm; - ResetForm(); - var generator = GenerateForm; - var scope = generator.inject(form, {mode: 'add', related: false}); - - scope.ldap_user = false; - scope.not_ldap_user = !scope.ldap_user; - scope.ldap_dn = null; + // Inject dynamic view + var defaultUrl = GetBasePath('organizations'), + form = UserForm, + generator = GenerateForm, + scope = generator.inject(form, { mode: 'add', related: false }); + + ResetForm(); + + scope.ldap_user = false; + scope.not_ldap_user = !scope.ldap_user; + scope.ldap_dn = null; - generator.reset(); + generator.reset(); - LoadBreadCrumbs(); + LoadBreadCrumbs(); - // Configure the lookup dialog. If we're adding a user through the Organizations tab, - // default the Organization value. - LookUpInit({ - scope: scope, - form: form, - current_item: ($routeParams.organization_id !== undefined) ? $routeParams.organization_id : null, - list: OrganizationList, - field: 'organization' - }); + // Configure the lookup dialog. If we're adding a user through the Organizations tab, + // default the Organization value. + LookUpInit({ + scope: scope, + form: form, + current_item: ($routeParams.organization_id !== undefined) ? $routeParams.organization_id : null, + list: OrganizationList, + field: 'organization' + }); - if ($routeParams.organization_id) { - scope.organization = $routeParams.organization_id; - Rest.setUrl(GetBasePath('organizations') + $routeParams.organization_id + '/'); - Rest.get() - .success( function(data, status, headers, config) { - scope['organization_name'] = data.name; - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to lookup Organization: ' + data.id + '. GET returned status: ' + status }); - }); - } + if ($routeParams.organization_id) { + scope.organization = $routeParams.organization_id; + Rest.setUrl(GetBasePath('organizations') + $routeParams.organization_id + '/'); + Rest.get() + .success(function (data) { + scope.organization_name = data.name; + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, form, { + hdr: 'Error!', + msg: 'Failed to lookup Organization: ' + data.id + '. GET returned status: ' + status + }); + }); + } - // Save - scope.formSave = function() { - generator.clearApiErrors(); - if (scope.organization !== undefined && scope.organization !== null && scope.organization !== '') { - Rest.setUrl(defaultUrl + scope.organization + '/users/'); - var data = {} - for (var fld in form.fields) { - if (form.fields[fld].realName) { - data[form.fields[fld].realName] = scope[fld]; - } - else { - data[fld] = scope[fld]; - } - } - - data.is_superuser = (data.is_superuser == null || data.is_superuser == undefined || data.is_superuser == '') ? false : - data.is_superuser; - Wait('start'); - Rest.post(data) - .success( function(data, status, headers, config) { - var base = $location.path().replace(/^\//,'').split('/')[0]; - if (base == 'users') { - $rootScope.flashMessage = 'New user successfully created!'; - $location.path('/users/' + data.id); - } - else { - ReturnToCaller(1); - } - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to add new user. POST returned status: ' + status }); - }); - } - else { - scope.organization_name_api_error = 'A value is required'; - } - }; + // Save + scope.formSave = function () { + generator.clearApiErrors(); + var fld, data = {}; + if (scope.organization !== undefined && scope.organization !== null && scope.organization !== '') { + Rest.setUrl(defaultUrl + scope.organization + '/users/'); + for (fld in form.fields) { + if (form.fields[fld].realName) { + data[form.fields[fld].realName] = scope[fld]; + } else { + data[fld] = scope[fld]; + } + } + data.is_superuser = data.is_superuser || false; + Wait('start'); + Rest.post(data) + .success(function (data) { + var base = $location.path().replace(/^\//, '').split('/')[0]; + if (base === 'users') { + $rootScope.flashMessage = 'New user successfully created!'; + $location.path('/users/' + data.id); + } + ReturnToCaller(1); + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, form, { hdr: 'Error!', msg: 'Failed to add new user. POST returned status: ' + status }); + }); + } else { + scope.organization_name_api_error = 'A value is required'; + } + }; - // Cancel - scope.formReset = function() { - // Defaults - generator.reset(); - scope.ldap_user = false; - }; + // Cancel + scope.formReset = function () { + // Defaults + generator.reset(); + scope.ldap_user = false; + }; - // Password change - scope.clearPWConfirm = function(fld) { - // If password value changes, make sure password_confirm must be re-entered - scope[fld] = ''; - scope[form.name + '_form'][fld].$setValidity('awpassmatch', false); - } + // Password change + scope.clearPWConfirm = function (fld) { + // If password value changes, make sure password_confirm must be re-entered + scope[fld] = ''; + scope[form.name + '_form'][fld].$setValidity('awpassmatch', false); + }; } -UsersAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'UserForm', 'GenerateForm', - 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GetBasePath', - 'LookUpInit', 'OrganizationList', 'ResetForm', 'Wait' ]; +UsersAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'UserForm', 'GenerateForm', + 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GetBasePath', + 'LookUpInit', 'OrganizationList', 'ResetForm', 'Wait' +]; -function UsersEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm, - GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, - RelatedPaginateInit, ReturnToCaller, ClearScope, GetBasePath, Prompt, CheckAccess, - ResetForm, Wait, Stream) -{ - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior - //scope. +function UsersEdit($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm, + GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, + RelatedPaginateInit, ReturnToCaller, ClearScope, GetBasePath, Prompt, CheckAccess, + ResetForm, Wait, Stream) { + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + //scope. - var defaultUrl=GetBasePath('users'); - var generator = GenerateForm; - var form = UserForm; - var base = $location.path().replace(/^\//,'').split('/')[0]; - var master = {}; - var id = $routeParams.user_id; - var relatedSets = {}; + var defaultUrl = GetBasePath('users'), + generator = GenerateForm, + form = UserForm, + base = $location.path().replace(/^\//, '').split('/')[0], + master = {}, + id = $routeParams.user_id, + relatedSets = {}; + + if ($scope.removeFormReady) { + $scope.removeFormReady(); + } + $scope.removeFormReady = $scope.$on('formReady', function () { + var scope = generator.inject(form, { mode: 'edit', related: true }); + generator.reset(); - if ($scope.removeFormReady) { - $scope.removeFormReady(); - } - $scope.removeFormReady = $scope.$on('formReady', function() { - var scope = generator.inject(form, {mode: 'edit', related: true}); - generator.reset(); - if (scope.removePostRefresh) { - scope.removePostRefresh(); + scope.removePostRefresh(); } - scope.PermissionAddAllowed = false; + scope.PermissionAddAllowed = false; - // After the Organization is loaded, retrieve each related set - if (scope.removeUserLoaded) { - scope.removeUserLoaded(); - } - scope.removeUserLoaded = scope.$on('userLoaded', function() { - for (var set in relatedSets) { - scope.search(relatedSets[set].iterator); - } - CheckAccess({ scope: scope }); //Does the user have access to add/edit Permissions? - Wait('stop'); - }); + // After the Organization is loaded, retrieve each related set + if (scope.removeUserLoaded) { + scope.removeUserLoaded(); + } + scope.removeUserLoaded = scope.$on('userLoaded', function () { + for (var set in relatedSets) { + scope.search(relatedSets[set].iterator); + } + CheckAccess({ + scope: scope + }); //Does the user have access to add/edit Permissions? + Wait('stop'); + }); - // Retrieve detail record and prepopulate the form - Rest.setUrl(defaultUrl + ':id/'); - Rest.get({ params: {id: id} }) - .success( function(data, status, headers, config) { - LoadBreadCrumbs({ path: '/users/' + id, title: data.username }); - for (var fld in form.fields) { - if (data[fld]) { - if (fld == 'is_superuser') { - scope[fld] = (data[fld] == 'true' || data[fld] == true) ? 'true' : 'false'; - } - else { - scope[fld] = data[fld]; - } - master[fld] = scope[fld]; - } - } - var related = data.related; - for (var set in form.related) { - if (related[set]) { - relatedSets[set] = { url: related[set], iterator: form.related[set].iterator }; - } - } - - scope.ldap_user = (data.ldap_dn !== null && data.ldap_dn !== undefined && data.ldap_dn !== '') ? true : false; - scope.not_ldap_user = !scope.ldap_user; - master.ldap_user = scope.ldap_user; - - // Initialize related search functions. Doing it here to make sure relatedSets object is populated. - RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets }); - RelatedPaginateInit({ scope: scope, relatedSets: relatedSets }); - scope.$emit('userLoaded'); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to retrieve user: ' + $routeParams.id + '. GET status: ' + status }); - }); - - // Save changes to the parent - scope.formSave = function() { - generator.clearApiErrors(); - $rootScope.flashMessage = null; - Rest.setUrl(defaultUrl + id + '/'); - var data = {} - for (var fld in form.fields) { - if (form.fields[fld].realName) { - data[form.fields[fld].realName] = scope[fld]; - } - else { - data[fld] = scope[fld]; - } - } + // Retrieve detail record and prepopulate the form + Rest.setUrl(defaultUrl + ':id/'); + Rest.get({ params: { id: id } }) + .success(function (data) { + LoadBreadCrumbs({ path: '/users/' + id, title: data.username }); + var fld, related, set; + for (fld in form.fields) { + if (data[fld]) { + if (fld === 'is_superuser') { + scope[fld] = (data[fld] === 'true' || data[fld] === true) ? 'true' : 'false'; + } else { + scope[fld] = data[fld]; + } + master[fld] = scope[fld]; + } + } + related = data.related; + for (set in form.related) { + if (related[set]) { + relatedSets[set] = { + url: related[set], + iterator: form.related[set].iterator + }; + } + } - data.is_superuser = (data.is_superuser == null || data.is_superuser == undefined || data.is_superuser == '') ? false : - data.is_superuser; - - Wait('start'); - Rest.put(data) - .success( function(data, status, headers, config) { - Wait('stop'); - var base = $location.path().replace(/^\//,'').split('/')[0]; - (base == 'users') ? ReturnToCaller() : ReturnToCaller(1); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to update users: ' + $routeParams.id + '. PUT status: ' + status }); - }); - }; + scope.ldap_user = (data.ldap_dn !== null && data.ldap_dn !== undefined && data.ldap_dn !== '') ? true : false; + scope.not_ldap_user = !scope.ldap_user; + master.ldap_user = scope.ldap_user; - scope.showActivity = function() { Stream({ scope: scope }); } + // Initialize related search functions. Doing it here to make sure relatedSets object is populated. + RelatedSearchInit({ + scope: scope, + form: form, + relatedSets: relatedSets + }); + RelatedPaginateInit({ + scope: scope, + relatedSets: relatedSets + }); + scope.$emit('userLoaded'); + }) + .error(function (data, status) { + ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve user: ' + + $routeParams.id + '. GET status: ' + status }); + }); - // Cancel - scope.formReset = function() { - $rootScope.flashMessage = null; - generator.reset(); - for (var fld in master) { - scope[fld] = master[fld]; - } - scope['password_confirm'] = scope['password']; - }; + // Save changes to the parent + scope.formSave = function () { + var data = {}, fld; + generator.clearApiErrors(); + $rootScope.flashMessage = null; + Rest.setUrl(defaultUrl + id + '/'); + for (fld in form.fields) { + if (form.fields[fld].realName) { + data[form.fields[fld].realName] = scope[fld]; + } else { + data[fld] = scope[fld]; + } + } - // Password change - scope.clearPWConfirm = function(fld) { - // If password value changes, make sure password_confirm must be re-entered - scope[fld] = ''; - scope[form.name + '_form'][fld].$setValidity('awpassmatch', false); - $rootScope.flashMessage = null; - } + data.is_superuser = data.is_superuser || false; + + Wait('start'); + Rest.put(data) + .success(function () { + Wait('stop'); + var base = $location.path().replace(/^\//, '').split('/')[0]; + if (base === 'users') { + ReturnToCaller(); + } + ReturnToCaller(1); + }) + .error(function (data, status) { + Wait('stop'); + ProcessErrors(scope, data, status, form, { hdr: 'Error!', msg: 'Failed to update users: ' + $routeParams.id + + '. PUT status: ' + status }); + }); + }; + + scope.showActivity = function () { + Stream({ + scope: scope + }); + }; + + // Cancel + scope.formReset = function () { + $rootScope.flashMessage = null; + generator.reset(); + for (var fld in master) { + scope[fld] = master[fld]; + } + scope.password_confirm = scope.password; + }; + + // Password change + scope.clearPWConfirm = function (fld) { + // If password value changes, make sure password_confirm must be re-entered + scope[fld] = ''; + scope[form.name + '_form'][fld].$setValidity('awpassmatch', false); + $rootScope.flashMessage = null; + }; - // Related set: Add button - scope.add = function(set) { - $rootScope.flashMessage = null; - if (set == 'permissions') { - if (scope.PermissionAddAllowed) { - $location.path('/' + base + '/' + $routeParams.user_id + '/' + set + '/add'); - } - else { - Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.'); - } - } - else { - $location.path('/' + base + '/' + $routeParams.user_id + '/' + set); - } - }; + // Related set: Add button + scope.add = function (set) { + $rootScope.flashMessage = null; + if (set === 'permissions') { + if (scope.PermissionAddAllowed) { + $location.path('/' + base + '/' + $routeParams.user_id + '/' + set + '/add'); + } else { + Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.'); + } + } else { + $location.path('/' + base + '/' + $routeParams.user_id + '/' + set); + } + }; - // Related set: Edit button - scope.edit = function(set, id, name) { - $rootScope.flashMessage = null; - if (set == 'permissions') { - $location.path('/users/' + $routeParams.user_id + '/permissions/' + id); - } - else { - $location.path('/' + set + '/' + id); - } - }; + // Related set: Edit button + scope.edit = function (set, id) { + $rootScope.flashMessage = null; + if (set === 'permissions') { + $location.path('/users/' + $routeParams.user_id + '/permissions/' + id); + } else { + $location.path('/' + set + '/' + id); + } + }; - // Related set: Delete button - scope['delete'] = function(set, itm_id, name, title) { - $rootScope.flashMessage = null; - - var action = function() { - var url; - if (set == 'permissions') { - if (scope.PermissionAddAllowed) { - url = GetBasePath('base') + 'permissions/' + itm_id + '/'; + // Related set: Delete button + scope['delete'] = function (set, itm_id, name, title) { + $rootScope.flashMessage = null; + + var action = function () { + var url; + if (set === 'permissions') { + if (scope.PermissionAddAllowed) { + url = GetBasePath('base') + 'permissions/' + itm_id + '/'; + Rest.setUrl(url); + Rest.destroy() + .success(function () { + $('#prompt-modal').modal('hide'); + scope.search(form.related[set].iterator); + }) + .error(function (data, status) { + $('#prompt-modal').modal('hide'); + ProcessErrors(scope, data, status, null, { hdr: 'Error!', + msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); + }); + } else { + Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.'); + } + } else { + url = defaultUrl + $routeParams.user_id + '/' + set + '/'; Rest.setUrl(url); - Rest.destroy() - .success( function(data, status, headers, config) { + Rest.post({ + id: itm_id, + disassociate: 1 + }) + .success(function () { $('#prompt-modal').modal('hide'); scope.search(form.related[set].iterator); - }) - .error( function(data, status, headers, config) { + }) + .error(function (data, status) { $('#prompt-modal').modal('hide'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); + ProcessErrors(scope, data, status, null, { + hdr: 'Error!', + msg: 'Call to ' + url + ' failed. POST returned status: ' + status }); - } - else { - Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.'); - } - } - else { - url = defaultUrl + $routeParams.user_id + '/' + set + '/'; - Rest.setUrl(url); - Rest.post({ id: itm_id, disassociate: 1 }) - .success( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); - scope.search(form.related[set].iterator); - }) - .error( function(data, status, headers, config) { - $('#prompt-modal').modal('hide'); - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status }); - }); - } - } + }); + } + }; - Prompt({ hdr: 'Delete', - body: 'Are you sure you want to remove ' + name + ' from ' + scope.username + ' ' + title + '?', - action: action - }); - } - - }); // $scope.$on - - // Put form back to its original state - ResetForm(); - - - if ($scope.removeModifyForm) { - $scope.removeModifyForm(); - } - $scope.removeModifyForm = $scope.$on('modifyForm', function() { - // Modify form based on LDAP settings - Rest.setUrl(GetBasePath('config')); - Rest.get() - .success( function(data, status, headers, config) { - if (data['user_ldap_fields']) { - var fld; - for (var i=0; i < data['user_ldap_fields'].length; i++) { - fld = data['user_ldap_fields'][i]; - if (form.fields[fld]) { - form.fields[fld]['readonly'] = true; - form.fields[fld]['editRequired'] = false; - if (form.fields[fld].awRequiredWhen) { - delete form.fields[fld].awRequiredWhen; - } - } - } - } - $scope.$emit('formReady'); - }) - .error( function(data, status, headers, config) { - ProcessErrors($scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to retrieve application config. GET status: ' + status }); - }); - }); - - Wait('start'); - Rest.setUrl(defaultUrl + id + '/'); - Rest.get() - .success( function(data, status, headers, config) { - if (data.ldap_dn !== null && data.ldap_dn !== undefined && data.ldap_dn !== '') { - //this is an LDAP user - $scope.$emit('modifyForm'); - } - else { - $scope.$emit('formReady'); - } - }) - .error( function(data, status, headers, config) { - ProcessErrors($scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to retrieve user: ' + id + '. GET status: ' + status }); + Prompt({ + hdr: 'Delete', + body: 'Are you sure you want to remove ' + name + ' from ' + scope.username + ' ' + title + '?', + action: action }); + }; + }); // $scope.$on + + // Put form back to its original state + ResetForm(); + + + if ($scope.removeModifyForm) { + $scope.removeModifyForm(); + } + $scope.removeModifyForm = $scope.$on('modifyForm', function () { + // Modify form based on LDAP settings + Rest.setUrl(GetBasePath('config')); + Rest.get() + .success(function (data) { + var i, fld; + if (data.user_ldap_fields) { + for (i = 0; i < data.user_ldap_fields.length; i++) { + fld = data.user_ldap_fields[i]; + if (form.fields[fld]) { + form.fields[fld].readonly = true; + form.fields[fld].editRequired = false; + if (form.fields[fld].awRequiredWhen) { + delete form.fields[fld].awRequiredWhen; + } + } + } + } + $scope.$emit('formReady'); + }) + .error(function (data, status) { + ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve application config. GET status: ' + status }); + }); + }); + + Wait('start'); + Rest.setUrl(defaultUrl + id + '/'); + Rest.get() + .success(function (data) { + if (data.ldap_dn !== null && data.ldap_dn !== undefined && data.ldap_dn !== '') { + //this is an LDAP user + $scope.$emit('modifyForm'); + } else { + $scope.$emit('formReady'); + } + }) + .error(function (data, status) { + ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve user: ' + id + '. GET status: ' + status }); + }); } -UsersEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'UserForm', - 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', - 'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'GetBasePath', 'Prompt', 'CheckAccess', - 'ResetForm', 'Wait', 'Stream']; - +UsersEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'UserForm', 'GenerateForm', + 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', + 'GetBasePath', 'Prompt', 'CheckAccess', 'ResetForm', 'Wait', 'Stream' +]; \ No newline at end of file