From d25e712e2197115c17e3e9316d1231ed2224e1dc Mon Sep 17 00:00:00 2001
From: vagrant
Date: Tue, 11 Feb 2014 04:52:15 +0000
Subject: [PATCH] Finixhed applying jsHint linting to js files. Created initial
Gruntfile.js build script and package.json script for keeping track of
required node modules.
---
.gitignore | 1 +
Gruntfile.js | 32 +
awx/ui/static/js/app.js | 515 +--
awx/ui/static/js/config.js | 32 +-
awx/ui/static/js/controllers/Credentials.js | 21 +-
awx/ui/static/js/controllers/JobEvents.js | 15 +-
awx/ui/static/js/forms/ActivityDetail.js | 15 +-
awx/ui/static/js/forms/Credentials.js | 174 +-
awx/ui/static/js/forms/Groups.js | 170 +-
awx/ui/static/js/forms/HostGroups.js | 39 +-
awx/ui/static/js/forms/Hosts.js | 66 +-
awx/ui/static/js/forms/Inventories.js | 53 +-
awx/ui/static/js/forms/InventoryGroups.js | 27 -
awx/ui/static/js/forms/InventoryHosts.js | 147 -
awx/ui/static/js/forms/InventoryStatus.js | 57 -
awx/ui/static/js/forms/JobEventData.js | 7 +-
awx/ui/static/js/forms/JobEvents.js | 144 +
awx/ui/static/js/forms/JobSummary.js | 12 +-
awx/ui/static/js/forms/JobTemplates.js | 141 +-
awx/ui/static/js/forms/Jobs.js | 155 +-
awx/ui/static/js/forms/LicenseForm.js | 84 +
awx/ui/static/js/forms/Organizations.js | 133 +-
awx/ui/static/js/forms/Permissions.js | 138 +-
awx/ui/static/js/forms/ProjectStatus.js | 11 +-
awx/ui/static/js/forms/Projects.js | 246 +-
awx/ui/static/js/forms/Teams.js | 197 +-
awx/ui/static/js/forms/Users.js | 192 +-
awx/ui/static/js/help/InventoryGroups.js | 95 +-
awx/ui/static/js/help/InventoryHosts.js | 24 -
awx/ui/static/js/helpers/Access.js | 187 +-
awx/ui/static/js/helpers/Children.js | 118 +-
awx/ui/static/js/helpers/Credentials.js | 325 +-
awx/ui/static/js/helpers/Events.js | 473 +--
awx/ui/static/js/helpers/Groups.js | 2075 ++++++------
awx/ui/static/js/helpers/Hosts.js | 2 +
awx/ui/static/js/helpers/JobSubmission.js | 882 +++--
awx/ui/static/js/helpers/Jobs.js | 229 +-
awx/ui/static/js/helpers/Lookup.js | 268 +-
awx/ui/static/js/helpers/PaginationHelpers.js | 290 +-
awx/ui/static/js/helpers/Parse.js | 100 +-
awx/ui/static/js/helpers/Permissions.js | 75 +-
awx/ui/static/js/helpers/ProjectPath.js | 130 +-
awx/ui/static/js/helpers/Projects.js | 216 +-
awx/ui/static/js/helpers/Selection.js | 291 +-
awx/ui/static/js/helpers/Users.js | 55 +-
awx/ui/static/js/helpers/api-defaults.js | 162 +-
awx/ui/static/js/helpers/inventory.js | 442 +--
awx/ui/static/js/helpers/md5.js | 54 +-
awx/ui/static/js/helpers/refresh-related.js | 64 +-
awx/ui/static/js/helpers/refresh.js | 78 +-
awx/ui/static/js/helpers/related-search.js | 412 ++-
awx/ui/static/js/helpers/search.js | 898 +++---
awx/ui/static/js/helpers/teams.js | 202 +-
awx/ui/static/js/lists/Admins.js | 38 +-
awx/ui/static/js/lists/CloudCredentials.js | 40 +-
awx/ui/static/js/lists/Credentials.js | 63 +-
awx/ui/static/js/lists/Groups.js | 38 +-
awx/ui/static/js/lists/HomeGroups.js | 76 +-
awx/ui/static/js/lists/HomeHosts.js | 44 +-
awx/ui/static/js/lists/Hosts.js | 36 +-
awx/ui/static/js/lists/Inventories.js | 65 +-
awx/ui/static/js/lists/InventoryHosts.js | 49 +-
awx/ui/static/js/lists/JobEvents.js | 26 +-
awx/ui/static/js/lists/JobHosts.js | 25 +-
awx/ui/static/js/lists/JobTemplates.js | 51 +-
awx/ui/static/js/lists/Jobs.js | 3 +
awx/ui/static/js/lists/Organizations.js | 38 +-
awx/ui/static/js/lists/Permissions.js | 49 +-
awx/ui/static/js/lists/Projects.js | 70 +-
awx/ui/static/js/lists/Streams.js | 88 +-
awx/ui/static/js/lists/Teams.js | 44 +-
awx/ui/static/js/lists/Users.js | 47 +-
.../static/js/widgets/InventorySyncStatus.js | 172 +-
awx/ui/static/js/widgets/JobStatus.js | 165 +-
awx/ui/static/js/widgets/ObjectCount.js | 112 +-
awx/ui/static/js/widgets/SCMSyncStatus.js | 171 +-
awx/ui/static/js/widgets/Stream.js | 847 ++---
awx/ui/static/lib/ansible/AuthService.js | 241 +-
awx/ui/static/lib/ansible/InventoryTree.js | 511 +--
awx/ui/static/lib/ansible/RestServices.js | 334 +-
awx/ui/static/lib/ansible/Timer.js | 83 +-
awx/ui/static/lib/ansible/TreeSelector.js | 693 ----
awx/ui/static/lib/ansible/Utilities.js | 702 ++--
awx/ui/static/lib/ansible/api-loader.js | 54 +-
awx/ui/static/lib/ansible/directives.js | 1 +
awx/ui/static/lib/ansible/filters.js | 31 +-
awx/ui/static/lib/ansible/form-generator.js | 2825 ++++++++---------
.../static/lib/ansible/generator-helpers.js | 1218 ++++---
awx/ui/static/lib/ansible/license.js | 305 +-
awx/ui/static/lib/ansible/list-generator.js | 805 ++---
awx/ui/static/lib/ansible/prompt-dialog.js | 49 +-
awx/ui/static/lib/ansible/pwdmeter.js | 455 +--
awx/ui/templates/ui/index.html | 4 +-
package.json | 9 +
94 files changed, 10589 insertions(+), 11059 deletions(-)
create mode 100644 Gruntfile.js
delete mode 100644 awx/ui/static/js/forms/InventoryGroups.js
delete mode 100644 awx/ui/static/js/forms/InventoryHosts.js
delete mode 100644 awx/ui/static/js/forms/InventoryStatus.js
create mode 100644 awx/ui/static/js/forms/JobEvents.js
create mode 100644 awx/ui/static/js/forms/LicenseForm.js
delete mode 100644 awx/ui/static/js/help/InventoryHosts.js
delete mode 100644 awx/ui/static/lib/ansible/TreeSelector.js
create mode 100644 package.json
diff --git a/.gitignore b/.gitignore
index e8fd62b1cc..5538679ba9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@ awx/public/static
awx/ui/static/js/awx-min.js
awx/ui/static/css/awx.min.css
env/*
+node_modules/**
build
deb-build
dist
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000000..2765d65d13
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,32 @@
+module.exports = function(grunt) {
+
+ grunt.initConfig({
+
+ pkg: grunt.file.readJSON('./package.json'),
+
+ jshint: {
+ options: {
+ jshintrc: '.jshintrc'
+ },
+ uses_defaults: ['awx/ui/static/js/*','awx/ui/static/lib/ansible/*', '!awx/ui/static/js/awx-min.js']
+ },
+
+ uglify: {
+ options: {
+ banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
+ '<%= grunt.template.today("yyyy-mm-dd") %> */'
+ },
+ my_target: {
+ files: {
+ 'awx/ui/static/js/awx-min.js': ['awx/ui/static/js/**/*.js', 'awx/ui/static/lib/ansible/*.js',
+ '!awx/ui/static/js/awx-min.js']
+ }
+ }
+ }
+ });
+
+ grunt.loadNpmTasks('grunt-contrib-jshint');
+ grunt.loadNpmTasks('grunt-contrib-uglify');
+
+ grunt.registerTask('default', ['jshint', 'uglify']);
+}
diff --git a/awx/ui/static/js/app.js b/awx/ui/static/js/app.js
index a95a888464..fa88f9140f 100644
--- a/awx/ui/static/js/app.js
+++ b/awx/ui/static/js/app.js
@@ -4,23 +4,22 @@
* Our main application mdoule. Declare application routes and perform initialization chores.
*
*/
-
var urlPrefix = $basePath;
angular.module('ansible', [
'RestServices',
'AuthService',
'Utilities',
- 'OrganizationFormDefinition',
+ 'OrganizationFormDefinition',
'UserFormDefinition',
'FormGenerator',
'OrganizationListDefinition',
- 'UserListDefinition',
+ 'UserListDefinition',
'UserHelper',
- 'ListGenerator',
+ 'ListGenerator',
'PromptDialog',
- 'ApiLoader',
- 'RelatedSearchHelper',
+ 'ApiLoader',
+ 'RelatedSearchHelper',
'SearchHelper',
'PaginationHelpers',
'RefreshHelper',
@@ -58,6 +57,7 @@ angular.module('ansible', [
'JobFormDefinition',
'JobEventsListDefinition',
'JobEventDataDefinition',
+ 'JobEventsFormDefinition',
'JobHostDefinition',
'JobSummaryDefinition',
'ParseHelper',
@@ -75,9 +75,7 @@ angular.module('ansible', [
'ObjectCountWidget',
'StreamWidget',
'JobsHelper',
- 'InventoryStatusDefinition',
'InventoryGroupsHelpDefinition',
- 'InventoryHostsHelpDefinition',
'InventoryTree',
'CredentialsHelper',
'TimerService',
@@ -85,253 +83,368 @@ angular.module('ansible', [
'HomeGroupListDefinition',
'HomeHostListDefinition',
'ActivityDetailDefinition'
- ])
- .config(['$routeProvider', function($routeProvider) {
- $routeProvider.
- when('/jobs',
- { templateUrl: urlPrefix + 'partials/jobs.html', controller: JobsListCtrl }).
+])
+ .config(['$routeProvider',
+ function ($routeProvider) {
+ $routeProvider.
+ when('/jobs', {
+ templateUrl: urlPrefix + 'partials/jobs.html',
+ controller: 'JobsListCtrl'
+ }).
- when('/jobs/:id',
- { templateUrl: urlPrefix + 'partials/jobs.html', controller: JobsEdit }).
+ when('/jobs/:id', {
+ templateUrl: urlPrefix + 'partials/jobs.html',
+ controller: 'JobsEdit'
+ }).
- when('/jobs/:id/job_events',
- { templateUrl: urlPrefix + 'partials/jobs.html', controller: JobEventsList }).
+ when('/jobs/:id/job_events', {
+ templateUrl: urlPrefix + 'partials/jobs.html',
+ controller: 'JobEventsList'
+ }).
- when('/jobs/:id/job_host_summaries',
- { templateUrl: urlPrefix + 'partials/jobs.html', controller: JobHostSummaryList }).
-
- when('/jobs/:job_id/job_events/:event_id',
- { templateUrl: urlPrefix + 'partials/jobs.html', controller: JobEventsEdit }).
+ when('/jobs/:id/job_host_summaries', {
+ templateUrl: urlPrefix + 'partials/jobs.html',
+ controller: 'JobHostSummaryList'
+ }).
- when('/job_templates',
- { templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesList }).
-
- when('/job_templates/add',
- { templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesAdd }).
+ when('/jobs/:job_id/job_events/:event_id', {
+ templateUrl: urlPrefix + 'partials/jobs.html',
+ controller: 'JobEventsEdit'
+ }).
- when('/job_templates/:id',
- { templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesEdit }).
+ when('/job_templates', {
+ templateUrl: urlPrefix + 'partials/job_templates.html',
+ controller: 'JobTemplatesList'
+ }).
- when('/projects',
- { templateUrl: urlPrefix + 'partials/projects.html', controller: ProjectsList }).
+ when('/job_templates/add', {
+ templateUrl: urlPrefix + 'partials/job_templates.html',
+ controller: 'JobTemplatesAdd'
+ }).
- when('/projects/add',
- { templateUrl: urlPrefix + 'partials/projects.html', controller: ProjectsAdd }).
+ when('/job_templates/:id', {
+ templateUrl: urlPrefix + 'partials/job_templates.html',
+ controller: 'JobTemplatesEdit'
+ }).
- when('/projects/:id',
- { templateUrl: urlPrefix + 'partials/projects.html', controller: ProjectsEdit }).
+ when('/projects', {
+ templateUrl: urlPrefix + 'partials/projects.html',
+ controller: 'ProjectsList'
+ }).
- when('/projects/:project_id/organizations',
- { templateUrl: urlPrefix + 'partials/projects.html', controller: OrganizationsList }).
+ when('/projects/add', {
+ templateUrl: urlPrefix + 'partials/projects.html',
+ controller: 'ProjectsAdd'
+ }).
- when('/projects/:project_id/organizations/add',
- { templateUrl: urlPrefix + 'partials/projects.html', controller: OrganizationsAdd }).
+ when('/projects/:id', {
+ templateUrl: urlPrefix + 'partials/projects.html',
+ controller: 'ProjectsEdit'
+ }).
- when('/hosts/:id/job_host_summaries',
- { templateUrl: urlPrefix + 'partials/jobs.html', controller: JobHostSummaryList }).
+ when('/projects/:project_id/organizations', {
+ templateUrl: urlPrefix + 'partials/projects.html',
+ controller: 'OrganizationsList'
+ }).
- when('/inventories',
- { templateUrl: urlPrefix + 'partials/inventories.html', controller: InventoriesList }).
+ when('/projects/:project_id/organizations/add', {
+ templateUrl: urlPrefix + 'partials/projects.html',
+ controller: 'OrganizationsAdd'
+ }).
- when('/inventories/add',
- { templateUrl: urlPrefix + 'partials/inventories.html', controller: InventoriesAdd }).
+ when('/hosts/:id/job_host_summaries', {
+ templateUrl: urlPrefix + 'partials/jobs.html',
+ controller: 'JobHostSummaryList'
+ }).
- when('/inventories/:inventory_id',
- { templateUrl: urlPrefix + 'partials/inventory-edit.html', controller: InventoriesEdit }).
+ when('/inventories', {
+ templateUrl: urlPrefix + 'partials/inventories.html',
+ controller: 'InventoriesList'
+ }).
- when('/organizations', { templateUrl: urlPrefix + 'partials/organizations.html',
- controller: OrganizationsList }).
+ when('/inventories/add', {
+ templateUrl: urlPrefix + 'partials/inventories.html',
+ controller: 'InventoriesAdd'
+ }).
- when('/organizations/add', { templateUrl: urlPrefix + 'partials/organizations.html',
- controller: OrganizationsAdd }).
+ when('/inventories/:inventory_id', {
+ templateUrl: urlPrefix + 'partials/inventory-edit.html',
+ controller: 'InventoriesEdit'
+ }).
- when('/organizations/:organization_id', { templateUrl: urlPrefix + 'partials/organizations.html',
- controller: OrganizationsEdit }).
+ when('/organizations', {
+ templateUrl: urlPrefix + 'partials/organizations.html',
+ controller: 'OrganizationsList'
+ }).
- when('/organizations/:organization_id/admins', { templateUrl: urlPrefix + 'partials/organizations.html',
- controller: AdminsList }).
+ when('/organizations/add', {
+ templateUrl: urlPrefix + 'partials/organizations.html',
+ controller: 'OrganizationsAdd'
+ }).
- when('/organizations/:organization_id/users', { templateUrl: urlPrefix + 'partials/users.html',
- controller: UsersList }).
+ when('/organizations/:organization_id', {
+ templateUrl: urlPrefix + 'partials/organizations.html',
+ controller: 'OrganizationsEdit'
+ }).
- when('/organizations/:organization_id/users/add', { templateUrl: urlPrefix + 'partials/users.html',
- controller: UsersAdd }).
+ when('/organizations/:organization_id/admins', {
+ templateUrl: urlPrefix + 'partials/organizations.html',
+ controller: 'AdminsList'
+ }).
- when('/organizations/:organization_id/users/:user_id', { templateUrl: urlPrefix + 'partials/users.html',
- controller: UsersEdit }).
+ when('/organizations/:organization_id/users', {
+ templateUrl: urlPrefix + 'partials/users.html',
+ controller: 'UsersList'
+ }).
- when('/teams', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: TeamsList }).
+ when('/organizations/:organization_id/users/add', {
+ templateUrl: urlPrefix + 'partials/users.html',
+ controller: 'UsersAdd'
+ }).
- when('/teams/add', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: TeamsAdd }).
+ when('/organizations/:organization_id/users/:user_id', {
+ templateUrl: urlPrefix + 'partials/users.html',
+ controller: 'UsersEdit'
+ }).
- when('/teams/:team_id', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: TeamsEdit }).
-
- when('/teams/:team_id/permissions/add', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: PermissionsAdd }).
+ when('/teams', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'TeamsList'
+ }).
- when('/teams/:team_id/permissions', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: PermissionsList }).
+ when('/teams/add', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'TeamsAdd'
+ }).
- when('/teams/:team_id/permissions/:permission_id', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: PermissionsEdit }).
+ when('/teams/:team_id', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'TeamsEdit'
+ }).
- when('/teams/:team_id/users', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: UsersList }).
+ when('/teams/:team_id/permissions/add', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'PermissionsAdd'
+ }).
- when('/teams/:team_id/users/:user_id', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: UsersEdit }).
+ when('/teams/:team_id/permissions', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'PermissionsList'
+ }).
- when('/teams/:team_id/projects', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: ProjectsList }).
+ when('/teams/:team_id/permissions/:permission_id', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'PermissionsEdit'
+ }).
- when('/teams/:team_id/projects/add', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: ProjectsAdd }).
+ when('/teams/:team_id/users', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'UsersList'
+ }).
- when('/teams/:team_id/projects/:project_id', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: ProjectsEdit }).
-
- when('/teams/:team_id/credentials', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: CredentialsList }).
+ when('/teams/:team_id/users/:user_id', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'UsersEdit'
+ }).
- when('/teams/:team_id/credentials/add', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: CredentialsAdd }).
+ when('/teams/:team_id/projects', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'ProjectsList'
+ }).
- when('/teams/:team_id/credentials/:credential_id', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: CredentialsEdit }).
+ when('/teams/:team_id/projects/add', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'ProjectsAdd'
+ }).
- when('/credentials', { templateUrl: urlPrefix + 'partials/credentials.html',
- controller: CredentialsList }).
+ when('/teams/:team_id/projects/:project_id', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'ProjectsEdit'
+ }).
- when('/credentials/add', { templateUrl: urlPrefix + 'partials/credentials.html',
- controller: CredentialsAdd }).
+ when('/teams/:team_id/credentials', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'CredentialsList'
+ }).
- when('/credentials/:credential_id', { templateUrl: urlPrefix + 'partials/credentials.html',
- controller: CredentialsEdit }).
-
- when('/users', { templateUrl: urlPrefix + 'partials/users.html',
- controller: UsersList }).
+ when('/teams/:team_id/credentials/add', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'CredentialsAdd'
+ }).
- when('/users/add', { templateUrl: urlPrefix + 'partials/users.html',
- controller: UsersAdd }).
+ when('/teams/:team_id/credentials/:credential_id', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'CredentialsEdit'
+ }).
- when('/users/:user_id', { templateUrl: urlPrefix + 'partials/users.html',
- controller: UsersEdit }).
+ when('/credentials', {
+ templateUrl: urlPrefix + 'partials/credentials.html',
+ controller: 'CredentialsList'
+ }).
- when('/users/:user_id/credentials', { templateUrl: urlPrefix + 'partials/users.html',
- controller: CredentialsList }).
+ when('/credentials/add', {
+ templateUrl: urlPrefix + 'partials/credentials.html',
+ controller: 'CredentialsAdd'
+ }).
- when('/users/:user_id/permissions/add', { templateUrl: urlPrefix + 'partials/users.html',
- controller: PermissionsAdd }).
+ when('/credentials/:credential_id', {
+ templateUrl: urlPrefix + 'partials/credentials.html',
+ controller: 'CredentialsEdit'
+ }).
- when('/users/:user_id/permissions', { templateUrl: urlPrefix + 'partials/users.html',
- controller: PermissionsList }).
+ when('/users', {
+ templateUrl: urlPrefix + 'partials/users.html',
+ controller: 'UsersList'
+ }).
- when('/users/:user_id/permissions/:permission_id', { templateUrl: urlPrefix + 'partials/users.html',
- controller: PermissionsEdit }).
+ when('/users/add', {
+ templateUrl: urlPrefix + 'partials/users.html',
+ controller: 'UsersAdd'
+ }).
- when('/users/:user_id/credentials/add', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: CredentialsAdd }).
+ when('/users/:user_id', {
+ templateUrl: urlPrefix + 'partials/users.html',
+ controller: 'UsersEdit'
+ }).
- when('/teams/:user_id/credentials/:credential_id', { templateUrl: urlPrefix + 'partials/teams.html',
- controller: CredentialsEdit }).
+ when('/users/:user_id/credentials', {
+ templateUrl: urlPrefix + 'partials/users.html',
+ controller: 'CredentialsList'
+ }).
- when('/login', { templateUrl: urlPrefix + 'partials/home.html', controller: Authenticate }).
+ when('/users/:user_id/permissions/add', {
+ templateUrl: urlPrefix + 'partials/users.html',
+ controller: 'PermissionsAdd'
+ }).
- when('/logout', { templateUrl: urlPrefix + 'partials/home.html', controller: Authenticate }).
+ when('/users/:user_id/permissions', {
+ templateUrl: urlPrefix + 'partials/users.html',
+ controller: 'PermissionsList'
+ }).
- when('/home', { templateUrl: urlPrefix + 'partials/home.html', controller: Home }).
+ when('/users/:user_id/permissions/:permission_id', {
+ templateUrl: urlPrefix + 'partials/users.html',
+ controller: 'PermissionsEdit'
+ }).
- when('/home/groups', { templateUrl: urlPrefix + 'partials/subhome.html', controller: HomeGroups }).
+ when('/users/:user_id/credentials/add', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'CredentialsAdd'
+ }).
- when('/home/hosts', { templateUrl: urlPrefix + 'partials/subhome.html', controller: HomeHosts }).
-
- otherwise({redirectTo: '/home'});
- }])
- .run(['$cookieStore', '$rootScope', 'CheckLicense', '$location', 'Authorization','LoadBasePaths', 'ViewLicense',
- 'Timer', 'ClearScope', 'HideStream',
- function($cookieStore, $rootScope, CheckLicense, $location, Authorization, LoadBasePaths, ViewLicense,
- Timer, ClearScope, HideStream) {
-
- LoadBasePaths();
-
- $rootScope.breadcrumbs = new Array();
- $rootScope.crumbCache = new Array();
- $rootScope.sessionTimer = Timer.init();
+ when('/teams/:user_id/credentials/:credential_id', {
+ templateUrl: urlPrefix + 'partials/teams.html',
+ controller: 'CredentialsEdit'
+ }).
- $rootScope.$on("$routeChangeStart", function(event, next, current) {
+ when('/login', {
+ templateUrl: urlPrefix + 'partials/home.html',
+ controller: 'Authenticate'
+ }).
- // Before navigating away from current tab, make sure the primary view is visible
- if ($('#stream-container').is(':visible')) {
- HideStream();
- }
+ when('/logout', {
+ templateUrl: urlPrefix + 'partials/home.html',
+ controller: 'Authenticate'
+ }).
- // On each navigation request, check that the user is logged in
- if ( !/^\/(login|logout)/.test($location.path()) ) {
- // capture most recent URL, excluding login/logout
- $rootScope.lastPath = $location.path();
- $cookieStore.put('lastPath', $location.path());
- }
+ when('/home', {
+ templateUrl: urlPrefix + 'partials/home.html',
+ controller: 'Home'
+ }).
- if (Authorization.isUserLoggedIn() == false) {
- if ( next.templateUrl != (urlPrefix + 'partials/login.html') ) {
- $location.path('/login');
- }
- }
- else if ($rootScope.sessionTimer.isExpired()) {
- if ( next.templateUrl != (urlPrefix + 'partials/login.html') ) {
- $rootScope.sessionTimer.expireSession();
- $location.path('/login');
- }
- }
- else {
- if ($rootScope.current_user == undefined || $rootScope.current_user == null) {
- Authorization.restoreUserInfo(); //user must have hit browser refresh
- }
- CheckLicense();
- }
-
- // Make the correct tab active
- var base = $location.path().replace(/^\//,'').split('/')[0];
- if (base == '') {
- base = 'home';
- }
- else {
- base.replace(/\_/g,' ');
- }
- $('.nav-tabs a[href="#' + base + '"]').tab('show');
+ when('/home/groups', {
+ templateUrl: urlPrefix + 'partials/subhome.html',
+ controller: 'HomeGroups'
+ }).
+
+ when('/home/hosts', {
+ templateUrl: urlPrefix + 'partials/subhome.html',
+ controller: 'HomeHosts'
+ }).
+
+ otherwise({
+ redirectTo: '/home'
+ });
+ }
+ ])
+ .run(['$cookieStore', '$rootScope', 'CheckLicense', '$location', 'Authorization', 'LoadBasePaths', 'ViewLicense',
+ 'Timer', 'ClearScope', 'HideStream',
+ function ($cookieStore, $rootScope, CheckLicense, $location, Authorization, LoadBasePaths, ViewLicense,
+ Timer, ClearScope, HideStream) {
+
+ LoadBasePaths();
+
+ $rootScope.breadcrumbs = [];
+ $rootScope.crumbCache = [];
+ $rootScope.sessionTimer = Timer.init();
+
+ $rootScope.$on("$routeChangeStart", function (event, next) {
+
+ // Before navigating away from current tab, make sure the primary view is visible
+ if ($('#stream-container').is(':visible')) {
+ HideStream();
+ }
+
+ // On each navigation request, check that the user is logged in
+ if (!/^\/(login|logout)/.test($location.path())) {
+ // capture most recent URL, excluding login/logout
+ $rootScope.lastPath = $location.path();
+ $cookieStore.put('lastPath', $location.path());
+ }
+
+ if (Authorization.isUserLoggedIn() === false) {
+ if (next.templateUrl !== (urlPrefix + 'partials/login.html')) {
+ $location.path('/login');
+ }
+ } else if ($rootScope.sessionTimer.isExpired()) {
+ if (next.templateUrl !== (urlPrefix + 'partials/login.html')) {
+ $rootScope.sessionTimer.expireSession();
+ $location.path('/login');
+ }
+ } else {
+ if ($rootScope.current_user === undefined || $rootScope.current_user === null) {
+ Authorization.restoreUserInfo(); //user must have hit browser refresh
+ }
+ CheckLicense();
+ }
+
+ // Make the correct tab active
+ var base = $location.path().replace(/^\//, '').split('/')[0];
+ if (base === '') {
+ base = 'home';
+ } else {
+ base.replace(/\_/g, ' ');
+ }
+ $('.nav-tabs a[href="#' + base + '"]').tab('show');
});
- if (!Authorization.getToken()) {
- // When the app first loads, redirect to login page
- $rootScope.sessionExpired = false;
- $cookieStore.put('sessionExpired', false);
- $location.path('/login');
- }
- else {
- // If browser refresh, set the user_is_superuser value
- $rootScope['user_is_superuser'] = Authorization.getUserInfo('is_superuser');
- }
-
- // If browser refresh, activate the correct tab
- var base = ($location.path().replace(/^\//,'').split('/')[0]);
- if (base == '') {
- base = 'home';
- $location.path('/home');
- }
- else {
- base.replace(/\_/g,' ');
- }
- $('.nav-tabs a[href="#' + base + '"]').tab('show');
-
- $rootScope.viewCurrentUser = function() {
- $location.path('/users/' + $rootScope.current_user.id);
+ if (!Authorization.getToken()) {
+ // When the app first loads, redirect to login page
+ $rootScope.sessionExpired = false;
+ $cookieStore.put('sessionExpired', false);
+ $location.path('/login');
+ } else {
+ // If browser refresh, set the user_is_superuser value
+ $rootScope.user_is_superuser = Authorization.getUserInfo('is_superuser');
}
- $rootScope.viewLicense = function() {
- //$location.path('/license');
- ViewLicense();
- }
- }]);
+ // If browser refresh, activate the correct tab
+ var base = ($location.path().replace(/^\//, '').split('/')[0]);
+ if (base === '') {
+ base = 'home';
+ $location.path('/home');
+ } else {
+ base.replace(/\_/g, ' ');
+ }
+ $('.nav-tabs a[href="#' + base + '"]').tab('show');
+
+ $rootScope.viewCurrentUser = function () {
+ $location.path('/users/' + $rootScope.current_user.id);
+ };
+
+ $rootScope.viewLicense = function () {
+ //$location.path('/license');
+ ViewLicense();
+ };
+ }
+ ]);
\ No newline at end of file
diff --git a/awx/ui/static/js/config.js b/awx/ui/static/js/config.js
index c7f6b47587..5fac0d9a38 100644
--- a/awx/ui/static/js/config.js
+++ b/awx/ui/static/js/config.js
@@ -1,4 +1,4 @@
-/************************************
+/**********************************************************************
*
* Copyright (c) 2014 AnsibleWorks, Inc.
*
@@ -8,19 +8,21 @@
*
*/
-var $AnsibleConfig =
-{
- tooltip_delay: {show: 500, hide: 100}, // Default number of milliseconds to delay displaying/hiding tooltips
+/*jshint unused:false */
- debug_mode: true, // Enable console logging messages
-
- password_strength: 45, // User password strength. Integer between 0 and 100, 100 being impossibly strong.
- // This value controls progress bar colors:
- // 0 to password_strength - 15 = red;
- // password_strength - 15 to password_strength = yellow
- // > password_strength = green
- // It also controls password validation. Passwords are rejected if the score is not > password_strength.
+var $AnsibleConfig = {
- session_timeout: 1800 // Number of seconds before an inactive session is automatically timed out and forced to log in again.
- // Separate from time out value set in API.
- }
+ tooltip_delay: {show: 500, hide: 100}, // Default number of milliseconds to delay displaying/hiding tooltips
+
+ debug_mode: true, // Enable console logging messages
+
+ password_strength: 45, // User password strength. Integer between 0 and 100, 100 being impossibly strong.
+ // This value controls progress bar colors:
+ // 0 to password_strength - 15 = red;
+ // password_strength - 15 to password_strength = yellow
+ // > password_strength = green
+ // It also controls password validation. Passwords are rejected if the score is not > password_strength.
+
+ session_timeout: 1800 // Number of seconds before an inactive session is automatically timed out and forced to log in again.
+ // Separate from time out value set in API.
+};
\ No newline at end of file
diff --git a/awx/ui/static/js/controllers/Credentials.js b/awx/ui/static/js/controllers/Credentials.js
index ef4a636035..7ba65e003c 100644
--- a/awx/ui/static/js/controllers/Credentials.js
+++ b/awx/ui/static/js/controllers/Credentials.js
@@ -1,12 +1,12 @@
-/************************************
+/*************************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
- *
* Credentials.js
*
* Controller functions for the Credential model.
*
*/
+
'use strict';
function CredentialsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, CredentialList,
@@ -114,10 +114,10 @@ function CredentialsList($scope, $rootScope, $location, $log, $routeParams, Rest
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!',
@@ -143,7 +143,7 @@ CredentialsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeP
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) {
+ GetChoices, Empty, KindChange, OwnerChange, FormSave) {
ClearScope('tree-form');
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
@@ -152,7 +152,6 @@ function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routePar
var form = CredentialForm,
generator = GenerateForm,
scope = generator.inject(form, { mode: 'add', related: false }),
- base = $location.path().replace(/^\//, '').split('/')[0],
defaultUrl = GetBasePath('credentials'),
url;
@@ -193,10 +192,10 @@ function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routePar
url = GetBasePath('users') + $routeParams.user_id + '/';
Rest.setUrl(url);
Rest.get()
- .success(function (data, status, headers, config) {
+ .success(function (data) {
scope.user_username = data.username;
})
- .error(function (data, status, headers, config) {
+ .error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve user. GET status: ' + status
});
});
@@ -210,10 +209,10 @@ function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routePar
url = GetBasePath('teams') + $routeParams.team_id + '/';
Rest.setUrl(url);
Rest.get()
- .success(function (data, status, headers, config) {
+ .success(function (data) {
scope.team_name = data.name;
})
- .error(function (data, status, headers, config) {
+ .error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve team. GET status: ' + status
});
});
@@ -289,7 +288,7 @@ function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routePar
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'
+ 'KindChange', 'OwnerChange', 'FormSave'
];
diff --git a/awx/ui/static/js/controllers/JobEvents.js b/awx/ui/static/js/controllers/JobEvents.js
index 7c9406dd0d..f62f0ff73f 100644
--- a/awx/ui/static/js/controllers/JobEvents.js
+++ b/awx/ui/static/js/controllers/JobEvents.js
@@ -249,13 +249,12 @@ JobEventsList.$inject = ['$filter', '$scope', '$rootScope', '$location', '$log',
'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,
+function JobEventsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobEventsForm, GenerateForm,
+ Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, FormatDate, EventView, Wait) {
+
+ ClearScope('htmlTemplate');
+
+ var form = JobEventsForm,
generator = GenerateForm,
scope = GenerateForm.inject(form, { mode: 'edit', related: true }),
defaultUrl = GetBasePath('base') + 'job_events/' + $routeParams.event_id + '/';
@@ -348,7 +347,7 @@ function JobEventsEdit($scope, $rootScope, $compile, $location, $log, $routePara
}
-JobEventsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobEventForm',
+JobEventsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobEventsForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', 'FormatDate',
'EventView', 'Wait'
];
\ No newline at end of file
diff --git a/awx/ui/static/js/forms/ActivityDetail.js b/awx/ui/static/js/forms/ActivityDetail.js
index 557e586219..e5b63ae77a 100644
--- a/awx/ui/static/js/forms/ActivityDetail.js
+++ b/awx/ui/static/js/forms/ActivityDetail.js
@@ -6,11 +6,10 @@
*
*/
angular.module('ActivityDetailDefinition', [])
- .value(
- 'ActivityDetailForm', {
-
+ .value('ActivityDetailForm', {
+
name: 'activity',
- editTitle: 'Activity Detail',
+ editTitle: 'Activity Detail',
well: false,
'class': 'horizontal-narrow',
formFieldSize: 'col-lg-10',
@@ -21,18 +20,18 @@ angular.module('ActivityDetailDefinition', [])
label: "Initiated by",
type: 'text',
readonly: true
- },
+ },
operation: {
label: 'Action',
type: 'text',
readonly: true
- },
+ },
changes: {
label: 'Changes',
type: 'textarea',
ngHide: "!changes || changes =='' || changes == 'null'",
readonly: true
- }
- }
+ }
+ }
}); //Form
diff --git a/awx/ui/static/js/forms/Credentials.js b/awx/ui/static/js/forms/Credentials.js
index eef3a5be53..31ec9dec2b 100644
--- a/awx/ui/static/js/forms/Credentials.js
+++ b/awx/ui/static/js/forms/Credentials.js
@@ -6,23 +6,22 @@
*
*/
angular.module('CredentialFormDefinition', [])
- .value(
- 'CredentialForm', {
-
- addTitle: 'Create Credential', //Legend in add mode
- editTitle: '{{ name }}', //Legend in edit mode
+ .value('CredentialForm', {
+
+ addTitle: 'Create Credential', //Legend in add mode
+ editTitle: '{{ name }}', //Legend in edit mode
name: 'credential',
well: true,
forceListeners: true,
-
+
actions: {
stream: {
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
mode: 'edit'
- }
- },
-
+ }
+ },
+
fields: {
name: {
label: 'Name',
@@ -30,27 +29,31 @@ angular.module('CredentialFormDefinition', [])
addRequired: true,
editRequired: true,
autocomplete: false
- },
- description: {
+ },
+ description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
- },
+ },
owner: {
label: "Does this credential belong to a team or user?",
type: 'radio_group',
ngChange: "ownerChange()",
- options: [
- { label: 'User', value: 'user', selected: true },
- { label: 'Team', value: 'team' }
- ],
- awPopOver: "A credential must be associated with either a user or a team. Choosing a user allows only the selected user access " +
+ options: [{
+ label: 'User',
+ value: 'user',
+ selected: true
+ }, {
+ label: 'Team',
+ value: 'team'
+ }],
+ awPopOver: "
A credential must be associated with either a user or a team. Choosing a user allows only the selected user access " +
"to the credential. Choosing a team shares the credential with all team members.
",
dataTitle: 'Owner',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
user: {
label: 'User that owns this credential',
type: 'lookup',
@@ -58,8 +61,11 @@ angular.module('CredentialFormDefinition', [])
sourceField: 'username',
ngClick: 'lookUpUser()',
ngShow: "owner == 'user'",
- awRequiredWhen: { variable: "user_required", init: "false" }
- },
+ awRequiredWhen: {
+ variable: "user_required",
+ init: "false"
+ }
+ },
team: {
label: 'Team that owns this credential',
type: 'lookup',
@@ -67,69 +73,84 @@ angular.module('CredentialFormDefinition', [])
sourceField: 'name',
ngClick: 'lookUpTeam()',
ngShow: "owner == 'team'",
- awRequiredWhen: { variable: "team_required", init: "false" }
- },
+ awRequiredWhen: {
+ variable: "team_required",
+ init: "false"
+ }
+ },
kind: {
label: 'Type',
excludeModal: true,
type: 'select',
ngOptions: 'kind.label for kind in credential_kind_options',
ngChange: 'kindChange()',
- addRequired: true,
+ addRequired: true,
editRequired: true,
- helpCollapse: [
- { hdr: 'Select a Credential Type',
- content: '\n' +
- 'AWS \n' +
- 'Access keys for Amazon Web Services used for inventory management or deployment. \n' +
- 'Machine \n' +
- 'Authentication for remote machine access. This can include SSH keys, usernames, passwords, ' +
- 'and sudo information. Machine credentials are used when submitting jobs to run playbooks against ' +
- 'remote hosts. ' +
- 'Rackspace \n' +
- 'Access information for Rackspace Cloud used for inventory management or deployment. \n' +
- 'SCM \n' +
- 'Used to check out and synchronize playbook repositories with a remote source control ' +
- 'management system such as Git, Subversion (svn), or Mercurial (hg). These credentials are ' +
- 'used on the Projects tab. \n' +
- ' \n'
- }]
- },
+ helpCollapse: [{
+ hdr: 'Select a Credential Type',
+ content: '\n' +
+ 'AWS \n' +
+ 'Access keys for Amazon Web Services used for inventory management or deployment. \n' +
+ 'Machine \n' +
+ 'Authentication for remote machine access. This can include SSH keys, usernames, passwords, ' +
+ 'and sudo information. Machine credentials are used when submitting jobs to run playbooks against ' +
+ 'remote hosts. ' +
+ 'Rackspace \n' +
+ 'Access information for Rackspace Cloud used for inventory management or deployment. \n' +
+ 'SCM \n' +
+ 'Used to check out and synchronize playbook repositories with a remote source control ' +
+ 'management system such as Git, Subversion (svn), or Mercurial (hg). These credentials are ' +
+ 'used on the Projects tab. \n' +
+ ' \n'
+ }]
+ },
access_key: {
label: 'Access Key',
type: 'text',
ngShow: "kind.value == 'aws'",
- awRequiredWhen: { variable: "aws_required", init: false },
+ awRequiredWhen: {
+ variable: "aws_required",
+ init: false
+ },
autocomplete: false,
apiField: 'username'
- },
+ },
secret_key: {
label: 'Secret Key',
type: 'password',
ngShow: "kind.value == 'aws'",
- awRequiredWhen: { variable: "aws_required", init: false },
+ awRequiredWhen: {
+ variable: "aws_required",
+ init: false
+ },
autocomplete: false,
ask: false,
clear: false,
apiField: 'passwowrd'
- },
+ },
"username": {
labelBind: 'usernameLabel',
type: 'text',
ngShow: "kind.value && kind.value !== 'aws'",
- awRequiredWhen: {variable: 'rackspace_required', init: false },
- autocomplete: false
+ awRequiredWhen: {
+ variable: 'rackspace_required',
+ init: false
},
+ autocomplete: false
+ },
"api_key": {
label: 'API Key',
type: 'password',
ngShow: "kind.value == 'rax'",
- awRequiredWhen: { variable: "rackspace_required", init: false },
+ awRequiredWhen: {
+ variable: "rackspace_required",
+ init: false
+ },
autocomplete: false,
ask: false,
clear: false,
apiField: 'passwowrd'
- },
+ },
"password": {
label: 'Password',
type: 'password',
@@ -141,7 +162,7 @@ angular.module('CredentialFormDefinition', [])
clear: false,
associated: 'password_confirm',
autocomplete: false
- },
+ },
"password_confirm": {
label: 'Confirm Password',
type: 'password',
@@ -151,7 +172,7 @@ angular.module('CredentialFormDefinition', [])
awPassMatch: true,
associated: 'password',
autocomplete: false
- },
+ },
"ssh_password": {
label: 'SSH Password',
type: 'password',
@@ -163,7 +184,7 @@ angular.module('CredentialFormDefinition', [])
clear: true,
associated: 'ssh_password_confirm',
autocomplete: false
- },
+ },
"ssh_password_confirm": {
label: 'Confirm SSH Password',
type: 'password',
@@ -173,7 +194,7 @@ angular.module('CredentialFormDefinition', [])
awPassMatch: true,
associated: 'ssh_password',
autocomplete: false
- },
+ },
"ssh_key_data": {
labelBind: 'sshKeyDataLabel',
type: 'textarea',
@@ -182,7 +203,7 @@ angular.module('CredentialFormDefinition', [])
editRequired: false,
'class': 'ssh-key-field',
rows: 10
- },
+ },
"ssh_key_unlock": {
label: 'Key Password',
type: 'password',
@@ -192,9 +213,9 @@ angular.module('CredentialFormDefinition', [])
ngChange: "clearPWConfirm('ssh_key_unlock_confirm')",
associated: 'ssh_key_unlock_confirm',
ask: true,
- askShow: "kind.value == 'ssh'", //Only allow ask for machine credentials
+ askShow: "kind.value == 'ssh'", //Only allow ask for machine credentials
clear: true
- },
+ },
"ssh_key_unlock_confirm": {
label: 'Confirm Key Password',
type: 'password',
@@ -203,7 +224,7 @@ angular.module('CredentialFormDefinition', [])
editRequired: false,
awPassMatch: true,
associated: 'ssh_key_unlock'
- },
+ },
"sudo_username": {
label: 'Sudo Username',
type: 'text',
@@ -211,7 +232,7 @@ angular.module('CredentialFormDefinition', [])
addRequired: false,
editRequired: false,
autocomplete: false
- },
+ },
"sudo_password": {
label: 'Sudo Password',
type: 'password',
@@ -223,7 +244,7 @@ angular.module('CredentialFormDefinition', [])
clear: true,
associated: 'sudo_password_confirm',
autocomplete: false
- },
+ },
"sudo_password_confirm": {
label: 'Confirm Sudo Password',
type: 'password',
@@ -233,24 +254,21 @@ angular.module('CredentialFormDefinition', [])
awPassMatch: true,
associated: 'sudo_password',
autocomplete: false
- }
- },
-
- buttons: { //for now always generates tags
- save: {
- label: 'Save',
- ngClick: 'formSave()', //$scope.function to call on click, optional
- ngDisabled: true //Disable when $pristine or $invalid, optional
- },
- reset: {
- ngClick: 'formReset()',
- ngDisabled: true //Disabled when $pristine
- }
- },
-
- related: { //related colletions (and maybe items?)
-
}
-
- }); //InventoryForm
+ },
+ buttons: {
+ save: {
+ label: 'Save',
+ ngClick: 'formSave()', //$scope.function to call on click, optional
+ ngDisabled: true //Disable when $pristine or $invalid, optional
+ },
+ reset: {
+ ngClick: 'formReset()',
+ ngDisabled: true //Disabled when $pristine
+ }
+ },
+
+ related: {}
+
+ });
\ No newline at end of file
diff --git a/awx/ui/static/js/forms/Groups.js b/awx/ui/static/js/forms/Groups.js
index 4976ef0410..8bf627a669 100644
--- a/awx/ui/static/js/forms/Groups.js
+++ b/awx/ui/static/js/forms/Groups.js
@@ -4,12 +4,11 @@
* Groups.js
* Form definition for Group model
*
- *
+ *
*/
angular.module('GroupFormDefinition', [])
- .value(
- 'GroupForm', {
-
+ .value('GroupForm', {
+
addTitle: 'Create Group',
editTitle: 'Edit Group',
showTitle: true,
@@ -18,12 +17,15 @@ angular.module('GroupFormDefinition', [])
well: true,
formLabelSize: 'col-lg-3',
formFieldSize: 'col-lg-9',
-
- tabs: [
- { name: 'properties', label: 'Properties'},
- { name: 'source', label: 'Source' }
- ],
-
+
+ tabs: [{
+ name: 'properties',
+ label: 'Properties'
+ }, {
+ name: 'source',
+ label: 'Source'
+ }],
+
fields: {
name: {
label: 'Name',
@@ -31,19 +33,19 @@ angular.module('GroupFormDefinition', [])
addRequired: true,
editRequired: true,
tab: 'properties'
- },
- description: {
+ },
+ description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false,
tab: 'properties'
- },
+ },
variables: {
label: 'Variables',
type: 'textarea',
addRequired: false,
- editRequird: false,
+ editRequird: false,
rows: 6,
'default': '---',
dataTitle: 'Group Variables',
@@ -59,24 +61,27 @@ angular.module('GroupFormDefinition', [])
'View YAML examples at docs.ansible.com
',
dataContainer: 'body',
tab: 'properties'
- },
+ },
source: {
label: 'Source',
type: 'select',
ngOptions: 'source.label for source in source_type_options',
ngChange: 'sourceChange()',
- addRequired: false,
+ addRequired: false,
editRequired: false,
//'default': { label: 'Manual', value: '' },
tab: 'source'
- },
+ },
source_path: {
label: 'Script Path',
ngShow: "source && source.value == 'file'",
type: 'text',
- awRequiredWhen: {variable: "sourcePathRequired", init: "false" },
- tab: 'source'
+ awRequiredWhen: {
+ variable: "sourcePathRequired",
+ init: "false"
},
+ tab: 'source'
+ },
credential: {
label: 'Cloud Credential',
type: 'lookup',
@@ -84,10 +89,10 @@ angular.module('GroupFormDefinition', [])
sourceModel: 'credential',
sourceField: 'name',
ngClick: 'lookUpCredential()',
- addRequired: false,
+ addRequired: false,
editRequired: false,
tab: 'source'
- },
+ },
source_regions: {
label: 'Regions',
type: 'text',
@@ -102,13 +107,13 @@ angular.module('GroupFormDefinition', [])
"
",
dataContainer: 'body',
tab: 'source'
- },
+ },
source_vars: {
label: 'Source Variables',
ngShow: "source && (source.value == 'file' || source.value == 'ec2')",
type: 'textarea',
addRequired: false,
- editRequird: false,
+ editRequird: false,
rows: 6,
'default': '---',
parseTypeName: 'envParseType',
@@ -126,80 +131,73 @@ angular.module('GroupFormDefinition', [])
'View YAML examples at docs.ansible.com
',
dataContainer: 'body',
tab: 'source'
- },
+ },
checkbox_group: {
label: 'Update Options',
type: 'checkbox_group',
ngShow: "source && (source.value !== '' && source.value !== null)",
tab: 'source',
- fields: [
- {
- name: 'overwrite',
- label: 'Overwrite',
- type: 'checkbox',
- ngShow: "source.value !== '' && source.value !== null",
- addRequired: false,
- editRequired: false,
- awPopOver: 'When checked all child groups and hosts not found on the remote source will be deleted from ' +
- 'the local inventory.
Unchecked any local child hosts and groups not found on the external source will ' +
- 'remain untouched by the inventory update process.
',
- dataTitle: 'Overwrite',
- dataContainer: 'body',
- dataPlacement: 'right',
- labelClass: 'checkbox-options'
- },
- {
- name: 'overwrite_vars',
- label: 'Overwrite Variables',
- type: 'checkbox',
- ngShow: "source.value !== '' && source.value !== null",
- addRequired: false,
- editRequired: false,
- awPopOver: 'If checked, all variables for child groups and hosts will be removed and replaced by those ' +
- 'found on the external source.
When not checked a merge will be performed, combining local variables with ' +
- 'those found on the external source.
',
- dataTitle: 'Overwrite Variables',
- dataContainer: 'body',
- dataPlacement: 'right',
- labelClass: 'checkbox-options'
- },
- {
- name: 'update_on_launch',
- label: 'Update on Launch',
- type: 'checkbox',
- ngShow: "source.value !== '' && source.value !== null",
- addRequired: false,
- editRequired: false,
- awPopOver: 'Each time a job runs using this inventory, refresh the inventory from the selected source before ' +
- 'executing job tasks.
',
- dataTitle: 'Update on Launch',
- dataContainer: 'body',
- dataPlacement: 'right',
- labelClass: 'checkbox-options'
- }
- ]
- }
- },
+ fields: [{
+ name: 'overwrite',
+ label: 'Overwrite',
+ type: 'checkbox',
+ ngShow: "source.value !== '' && source.value !== null",
+ addRequired: false,
+ editRequired: false,
+ awPopOver: 'When checked all child groups and hosts not found on the remote source will be deleted from ' +
+ 'the local inventory.
Unchecked any local child hosts and groups not found on the external source will ' +
+ 'remain untouched by the inventory update process.
',
+ dataTitle: 'Overwrite',
+ dataContainer: 'body',
+ dataPlacement: 'right',
+ labelClass: 'checkbox-options'
+ }, {
+ name: 'overwrite_vars',
+ label: 'Overwrite Variables',
+ type: 'checkbox',
+ ngShow: "source.value !== '' && source.value !== null",
+ addRequired: false,
+ editRequired: false,
+ awPopOver: 'If checked, all variables for child groups and hosts will be removed and replaced by those ' +
+ 'found on the external source.
When not checked a merge will be performed, combining local variables with ' +
+ 'those found on the external source.
',
+ dataTitle: 'Overwrite Variables',
+ dataContainer: 'body',
+ dataPlacement: 'right',
+ labelClass: 'checkbox-options'
+ }, {
+ name: 'update_on_launch',
+ label: 'Update on Launch',
+ type: 'checkbox',
+ ngShow: "source.value !== '' && source.value !== null",
+ addRequired: false,
+ editRequired: false,
+ awPopOver: 'Each time a job runs using this inventory, refresh the inventory from the selected source before ' +
+ 'executing job tasks.
',
+ dataTitle: 'Update on Launch',
+ dataContainer: 'body',
+ dataPlacement: 'right',
+ labelClass: 'checkbox-options'
+ }]
+ }
+ },
+
+ buttons: {
- buttons: { //for now always generates tags
-
labelClass: 'col-lg-3',
controlClass: 'col-lg-5',
- save: {
- ngClick: 'formSave()', //$scope.function to call on click, optional
- ngDisabled: true //Disable when $pristine or $invalid, optional
- },
- reset: {
- ngClick: 'formReset()',
- ngDisabled: true //Disabled when $pristine
- }
+ save: {
+ ngClick: 'formSave()',
+ ngDisabled: true
},
-
- related: { //related colletions (and maybe items?)
-
+ reset: {
+ ngClick: 'formReset()',
+ ngDisabled: true //Disabled when $pristine
}
+ },
- });
+ related: { }
+ });
\ No newline at end of file
diff --git a/awx/ui/static/js/forms/HostGroups.js b/awx/ui/static/js/forms/HostGroups.js
index e51ab01b65..3b8aa490cb 100644
--- a/awx/ui/static/js/forms/HostGroups.js
+++ b/awx/ui/static/js/forms/HostGroups.js
@@ -7,14 +7,13 @@
*
*/
angular.module('HostGroupsFormDefinition', [])
- .value(
- 'HostGroupsForm', {
+ .value('HostGroupsForm', {
- editTitle: 'Host Groups', //Legend in edit mode
- name: 'host', //Form name attribute
- well: false, //Wrap the form with TB well
+ editTitle: 'Host Groups',
+ name: 'host',
+ well: false,
formLabelSize: 'col-lg-3',
- formFieldSize: 'col-lg-9',
+ formFieldSize: 'col-lg-9',
fields: {
groups: {
@@ -26,30 +25,28 @@ angular.module('HostGroupsFormDefinition', [])
editRequired: true,
awPopOver: "Provide a host name, ip address, or ip address:port. Examples include:
" +
"myserver.domain.com " +
- "127.0.0.1 " +
+ "127.0.0.1 " +
"10.1.0.140:25 " +
"server.example.com:25" +
- " ",
+ "",
dataTitle: 'Host Name',
dataPlacement: 'right',
dataContainer: '#form-modal .modal-content'
- }
- },
+ }
+ },
buttons: { //for now always generates tags
- save: {
- ngClick: 'formSave()', //$scope.function to call on click, optional
- ngDisabled: true //Disable when $pristine or $invalid, optional
- },
- reset: {
- ngClick: 'formReset()',
- ngDisabled: true //Disabled when $pristine
- }
+ save: {
+ ngClick: 'formSave()',
+ ngDisabled: true
},
-
- related: { //related colletions (and maybe items?)
-
+ reset: {
+ ngClick: 'formReset()',
+ ngDisabled: true
}
+ },
+
+ related: { }
}); //UserForm
diff --git a/awx/ui/static/js/forms/Hosts.js b/awx/ui/static/js/forms/Hosts.js
index 4431c992ed..e056811ed1 100644
--- a/awx/ui/static/js/forms/Hosts.js
+++ b/awx/ui/static/js/forms/Hosts.js
@@ -4,18 +4,17 @@
* Hosts.js
* Form definition for Host model
*
- *
+ *
*/
angular.module('HostFormDefinition', [])
- .value(
- 'HostForm', {
-
- addTitle: 'Create Host', //Legend in add mode
- editTitle: '{{ name }}', //Legend in edit mode
- name: 'host', //Form name attribute
- well: false, //Wrap the form with TB well
+ .value('HostForm', {
+
+ addTitle: 'Create Host',
+ editTitle: '{{ name }}',
+ name: 'host',
+ well: false,
formLabelSize: 'col-lg-3',
- formFieldSize: 'col-lg-9',
+ formFieldSize: 'col-lg-9',
fields: {
name: {
@@ -24,21 +23,21 @@ angular.module('HostFormDefinition', [])
addRequired: true,
editRequired: true,
awPopOver: "Provide a host name, ip address, or ip address:port. Examples include:
" +
- "myserver.domain.com " +
- "127.0.0.1 " +
- "10.1.0.140:25 " +
- "server.example.com:25" +
- " ",
+ "myserver.domain.com " +
+ "127.0.0.1 " +
+ "10.1.0.140:25 " +
+ "server.example.com:25" +
+ " ",
dataTitle: 'Host Name',
dataPlacement: 'right',
dataContainer: '#form-modal .modal-content'
- },
- description: {
+ },
+ description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
- },
+ },
enabled: {
label: 'Enabled?',
type: 'checkbox',
@@ -51,12 +50,12 @@ angular.module('HostFormDefinition', [])
dataPlacement: 'right',
dataContainer: '#form-modal .modal-content',
ngDisabled: 'has_inventory_sources == true'
- },
+ },
variables: {
label: 'Variables',
type: 'textarea',
addRequired: false,
- editRequird: false,
+ editRequird: false,
rows: 6,
"class": "modal-input-xlarge",
"default": "---",
@@ -70,28 +69,25 @@ angular.module('HostFormDefinition', [])
dataTitle: 'Host Variables',
dataPlacement: 'right',
dataContainer: '#form-modal .modal-content'
- },
+ },
inventory: {
type: 'hidden',
- includeOnEdit: true,
+ includeOnEdit: true,
includeOnAdd: true
- }
- },
+ }
+ },
buttons: { //for now always generates tags
- save: {
- ngClick: 'formSave()', //$scope.function to call on click, optional
- ngDisabled: true //Disable when $pristine or $invalid, optional
- },
- reset: {
- ngClick: 'formReset()',
- ngDisabled: true //Disabled when $pristine
- }
+ save: {
+ ngClick: 'formSave()', //$scope.function to call on click, optional
+ ngDisabled: true //Disable when $pristine or $invalid, optional
},
-
- related: { //related colletions (and maybe items?)
-
+ reset: {
+ ngClick: 'formReset()',
+ ngDisabled: true //Disabled when $pristine
}
+ },
- });
+ related: {}
+ });
diff --git a/awx/ui/static/js/forms/Inventories.js b/awx/ui/static/js/forms/Inventories.js
index 8a4538f99c..bd39083f9c 100644
--- a/awx/ui/static/js/forms/Inventories.js
+++ b/awx/ui/static/js/forms/Inventories.js
@@ -4,12 +4,11 @@
* Inventories.js
* Form definition for User model
*
- *
+ *
*/
angular.module('InventoryFormDefinition', [])
- .value(
- 'InventoryForm', {
-
+ .value('InventoryForm', {
+
addTitle: 'Create Inventory',
editTitle: '{{ inventory_name | capitalize }}',
name: 'inventory',
@@ -24,8 +23,8 @@ angular.module('InventoryFormDefinition', [])
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
- }
- },
+ }
+ },
fields: {
inventory_name: {
@@ -35,29 +34,32 @@ angular.module('InventoryFormDefinition', [])
addRequired: true,
editRequired: true,
capitalize: false
- },
- inventory_description: {
+ },
+ inventory_description: {
realName: 'description',
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
- },
+ },
organization: {
label: 'Organization',
type: 'lookup',
sourceModel: 'organization',
sourceField: 'name',
ngClick: 'lookUpOrganization()',
- awRequiredWhen: {variable: "organizationrequired", init: "true" }
- },
+ awRequiredWhen: {
+ variable: "organizationrequired",
+ init: "true"
+ }
+ },
inventory_variables: {
realName: 'variables',
label: 'Variables',
type: 'textarea',
'class': 'span12',
addRequired: false,
- editRequird: false,
+ editRequird: false,
parseTypeName: 'inventoryParseType',
rows: 6,
"default": "---",
@@ -71,23 +73,22 @@ angular.module('InventoryFormDefinition', [])
dataTitle: 'Inventory Variables',
dataPlacement: 'right',
dataContainer: 'body'
- }
- },
+ }
+ },
- buttons: { //for now always generates tags
- save: {
- ngClick: 'formSave()', //$scope.function to call on click, optional
- ngDisabled: true //Disable when $pristine or $invalid, optional
- },
- reset: {
- ngClick: 'formReset()',
- ngDisabled: true //Disabled when $pristine
- }
+ buttons: {
+ save: {
+ ngClick: 'formSave()',
+ ngDisabled: true
},
+ reset: {
+ ngClick: 'formReset()',
+ ngDisabled: true
+ }
+ },
related: {
- }
-
- }); //InventoryForm
+ }
+ });
\ No newline at end of file
diff --git a/awx/ui/static/js/forms/InventoryGroups.js b/awx/ui/static/js/forms/InventoryGroups.js
deleted file mode 100644
index f743792996..0000000000
--- a/awx/ui/static/js/forms/InventoryGroups.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/*********************************************
- * Copyright (c) 2014 AnsibleWorks, Inc.
- *
- * InventoryGroups.js
- * Form definition for Groups model
- *
- *
- */
-angular.module('InventoryGroupsFormDefinition', [])
- .value(
- 'InventoryGroupsForm', {
-
- type: 'groupsview',
- title: "groupTitle",
- editTitle: 'Groups',
- iterator: 'group',
-
- fields: {
- },
-
- actions: {
- },
-
- fieldActions: {
- }
-
- }); //InventoryGroupsForm
\ No newline at end of file
diff --git a/awx/ui/static/js/forms/InventoryHosts.js b/awx/ui/static/js/forms/InventoryHosts.js
deleted file mode 100644
index 901b818e98..0000000000
--- a/awx/ui/static/js/forms/InventoryHosts.js
+++ /dev/null
@@ -1,147 +0,0 @@
-/*********************************************
- * Copyright (c) 2014 AnsibleWorks, Inc.
- *
- * InventoryHosts.js
- * Form definition for Hosts model
- *
- *
- */
-angular.module('InventoryHostsFormDefinition', [])
- .value(
- 'InventoryHostsForm', {
-
- type: 'hostsview',
- title: "groupTitle",
- editTitle: 'Hosts',
- iterator: 'host',
-
- fields: {
- name: {
- key: true,
- label: 'Name',
- ngClick: "editHost(\{\{ host.id \}\}, '\{\{ host.name \}\}')"
- },
- active_failures: {
- label: 'Job Status',
- ngHref: "\{\{ host.activeFailuresLink \}\}",
- awToolTip: "\{\{ host.badgeToolTip \}\}",
- dataPlacement: 'top',
- badgeNgHref: '\{\{ host.activeFailuresLink \}\}',
- badgeIcon: "\{\{ 'icon-failures-' + host.has_active_failures \}\}",
- badgePlacement: 'left',
- badgeToolTip: "\{\{ host.badgeToolTip \}\}",
- badgeTipPlacement: 'top',
- searchable: false,
- nosort: true
- },
- enabled_flag: {
- label: 'Enabled',
- badgeIcon: "\{\{ 'icon-enabled-' + host.enabled \}\}",
- badgePlacement: 'left',
- badgeToolTip: "\{\{ host.enabledToolTip \}\}",
- badgeTipPlacement: "top",
- badgeTipWatch: "host.enabledToolTip",
- ngClick: "toggle_host_enabled(\{\{ host.id \}\}, \{\{ host.has_inventory_sources \}\})",
- searchable: false,
- showValue: false
- },
- groups: {
- label: 'Groups',
- searchable: true,
- sourceModel: 'groups',
- sourceField: 'name',
- nosort: true
- },
- enabled: {
- label: 'Disabled?',
- searchSingleValue: true,
- searchType: 'boolean',
- searchValue: 'false',
- searchOnly: true
- },
- has_active_failures: {
- label: 'Has failed jobs?',
- searchSingleValue: true,
- searchType: 'boolean',
- searchValue: 'true',
- searchOnly: true
- },
- has_inventory_sources: {
- label: 'Has external source?',
- searchSingleValue: true,
- searchType: 'boolean',
- searchValue: 'true',
- searchOnly: true
- }
- },
-
- actions: {
- add: {
- label: 'Copy',
- ngClick: "addHost()",
- ngHide: "hostAddHide",
- awToolTip: "Copy an existing host to the selected group",
- dataPlacement: 'top',
- 'class': 'btn-xs btn-success',
- icon: 'icon-check'
- },
- create: {
- label: 'Create New',
- ngClick: 'createHost()',
- ngHide: 'hostCreateHide',
- awToolTip: 'Create a new host and add it to the selected group',
- dataPlacement: 'top',
- 'class': 'btn-xs btn-success',
- icon: 'icon-plus'
- },
- help: {
- dataPlacement: 'top',
- icon: "icon-question-sign",
- mode: 'all',
- 'class': 'btn-xs btn-info btn-help',
- awToolTip: "Need help getting started?
" +
- "
Click here for help with this page
",
- iconSize: 'large',
- ngClick: "showHelp()",
- id: "hosts-page-help"
- },
- stream: {
- 'class': "btn-primary btn-xs activity-btn",
- ngClick: "showActivity()",
- awToolTip: "View Activity Stream",
- dataPlacement: "top",
- icon: "icon-comments-alt",
- mode: 'edit',
- iconSize: 'large'
- }
- },
-
- fieldActions: {
-
- ViewJobs: {
- type: 'DropDown',
- label: 'Jobs',
- icon: 'icon-zoom-in',
- "class": "btn-default btn-xs",
- options: [
- { ngClick: "allJobs(\{\{ host.id \}\})", label: 'All', ngShow: 'host.last_job' },
- { ngClick: "allHostSummaries(\{\{ host.id \}\},'\{\{ host.name \}\}', \{\{ inventory_id \}\})", label: 'All summaries',
- ngShow: 'host.last_job' },
- { ngClick: 'viewJobs(\{\{ host.last_job \}\})', label: 'Latest', ngShow: 'host.last_job' },
- { ngClick: "viewLastEvents(\{\{ host.id \}\}, '\{\{ host.last_job \}\}', '\{\{ host.name \}\}', " +
- "'\{\{ host.summary_fields.last_job.name \}\}')", label: 'Latest events', ngShow: 'host.last_job' },
- { ngClick: "viewLastSummary(\{\{ host.id \}\}, '\{\{ host.last_job \}\}', '\{\{ host.name \}\}', " +
- "'\{\{ host.summary_fields.last_job.name \}\}')", label: 'Latest summary', ngShow: 'host.last_job' },
- { ngClick: "", label: 'No job data available', ngShow: 'host.last_job == null' }
- ]
- },
-
- "delete": {
- ngClick: "deleteHost(\{\{ host.id \}\},'\{\{ host.name \}\}')",
- icon: 'icon-trash',
- "class": 'btn-xs btn-danger',
- awToolTip: 'Delete host'
- }
- }
-
- }); //InventoryHostsForm
diff --git a/awx/ui/static/js/forms/InventoryStatus.js b/awx/ui/static/js/forms/InventoryStatus.js
deleted file mode 100644
index 7705c44e98..0000000000
--- a/awx/ui/static/js/forms/InventoryStatus.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/*********************************************
- * Copyright (c) 2014 AnsibleWorks, Inc.
- *
- * InventoryStatus.js
- * Form definition for Inventory Status -JSON view
- *
- *
- */
-angular.module('InventoryStatusDefinition', [])
- .value(
- 'InventoryStatusForm', {
-
- name: 'inventory_update',
- editTitle: 'Inventory Status',
- well: false,
- 'class': 'horizontal-narrow',
-
- fields: {
- license_error: {
- type: 'alertblock',
- 'class': 'alert-info',
- alertTxt: 'The invenvtory update process exceeded the available number of licensed hosts. ' +
- 'View your license ' +
- 'for more information.',
- ngShow: 'license_error',
- closeable: true
- },
- created: {
- label: 'Created',
- type: 'text',
- readonly: true
- },
- status: {
- label: 'Status',
- type: 'text',
- readonly: true,
- 'class': 'nowrap mono-space resizable',
- rows: '{{ status_rows }}'
- },
- result_stdout: {
- label: 'Std Out',
- type: 'textarea',
- ngShow: 'result_stdout',
- 'class': 'nowrap mono-space resizable',
- readonly: true,
- rows: '{{ stdout_rows }}'
- },
- result_traceback: {
- label: 'Traceback',
- type: 'textarea',
- ngShow: 'result_traceback',
- 'class': 'nowrap mono-space resizable',
- readonly: true,
- rows: '{{ traceback_rows }}'
- }
- }
- }); //Form
\ No newline at end of file
diff --git a/awx/ui/static/js/forms/JobEventData.js b/awx/ui/static/js/forms/JobEventData.js
index 453a2cbd59..df5e163dcc 100644
--- a/awx/ui/static/js/forms/JobEventData.js
+++ b/awx/ui/static/js/forms/JobEventData.js
@@ -7,10 +7,9 @@
*
*/
angular.module('JobEventDataDefinition', [])
- .value(
- 'JobEventDataForm', {
+ .value('JobEventDataForm', {
- editTitle: '{{ id }} - {{ event_display }}', //Legend in edit mode
+ editTitle: '{{ id }} - {{ event_display }}',
name: 'job_events',
well: false,
'class': 'horizontal-narrow',
@@ -22,7 +21,7 @@ angular.module('JobEventDataDefinition', [])
readonly: true,
rows: 18,
'class': 'modal-input-xxlarge'
- }
}
+ }
}); //Form
diff --git a/awx/ui/static/js/forms/JobEvents.js b/awx/ui/static/js/forms/JobEvents.js
new file mode 100644
index 0000000000..6146e74820
--- /dev/null
+++ b/awx/ui/static/js/forms/JobEvents.js
@@ -0,0 +1,144 @@
+/*********************************************
+ * Copyright (c) 2014 AnsibleWorks, Inc.
+ *
+ * JobEventsForm.js
+ *
+ */
+angular.module('JobEventsFormDefinition', [])
+ .value('JobEventsForm', {
+
+ name: 'job_events',
+ well: false,
+ forceListeners: true,
+
+ fields: {
+ status: {
+ labelClass: 'job-{{ status }}',
+ type: 'custom',
+ section: 'Event',
+ control: " {{ status }}
"
+ },
+ id: {
+ label: 'ID',
+ type: 'text',
+ readonly: true,
+ section: 'Event',
+ 'class': 'span1'
+ },
+ created: {
+ label: 'Created On',
+ type: 'text',
+ section: 'Event',
+ readonly: true
+ },
+ host: {
+ label: 'Host',
+ type: 'text',
+ readonly: true,
+ section: 'Event',
+ ngShow: "host !== ''"
+ },
+ play: {
+ label: 'Play',
+ type: 'text',
+ readonly: true,
+ section: 'Event',
+ ngShow: "play !== ''"
+ },
+ task: {
+ label: 'Task',
+ type: 'text',
+ readonly: true,
+ section: 'Event',
+ ngShow: "task !== ''"
+ },
+ rc: {
+ label: 'Return Code',
+ type: 'text',
+ readonly: true,
+ section: 'Results',
+ 'class': 'span1',
+ ngShow: "rc !== ''"
+ },
+ msg: {
+ label: 'Msg',
+ type: 'textarea',
+ readonly: true,
+ section: 'Results',
+ 'class': 'nowrap',
+ ngShow: "msg !== ''",
+ rows: 10
+ },
+ stdout: {
+ label: 'Std Out',
+ type: 'textarea',
+ readonly: true,
+ section: 'Results',
+ 'class': 'nowrap',
+ ngShow: "stdout !== ''",
+ rows: 10
+ },
+ stderr: {
+ label: 'Std Err',
+ type: 'textarea',
+ readonly: true,
+ section: 'Results',
+ 'class': 'nowrap',
+ ngShow: "stderr !== ''",
+ rows: 10
+ },
+ results: {
+ label: 'Results',
+ type: 'textarea',
+ section: 'Results',
+ readonly: true,
+ 'class': 'nowrap',
+ ngShow: "results !== ''",
+ rows: 10
+ },
+ start: {
+ label: 'Start',
+ type: 'text',
+ readonly: true,
+ section: 'Timing',
+ ngShow: "start !== ''"
+ },
+ traceback: {
+ label: false,
+ type: 'textarea',
+ readonly: true,
+ section: 'Traceback',
+ 'class': 'nowrap',
+ ngShow: "traceback !== ''",
+ rows: 10
+ },
+ end: {
+ label: 'End',
+ type: 'text',
+ readonly: true,
+ section: 'Timing',
+ ngShow: "end !== ''"
+ },
+ delta: {
+ label: 'Elapsed',
+ type: 'text',
+ readonly: true,
+ section: 'Timing',
+ ngShow: "delta !== ''"
+ },
+ module_name: {
+ label: 'Name',
+ type: 'text',
+ readonly: true,
+ section: 'Module',
+ ngShow: "module_name !== ''"
+ },
+ module_args: {
+ label: 'Args',
+ type: 'text',
+ readonly: true,
+ section: 'Module',
+ ngShow: "module_args !== ''"
+ }
+ }
+ });
\ No newline at end of file
diff --git a/awx/ui/static/js/forms/JobSummary.js b/awx/ui/static/js/forms/JobSummary.js
index 9a7be7cbe2..929b3b7240 100644
--- a/awx/ui/static/js/forms/JobSummary.js
+++ b/awx/ui/static/js/forms/JobSummary.js
@@ -7,8 +7,7 @@
*
*/
angular.module('JobSummaryDefinition', [])
- .value(
- 'JobSummary', {
+ .value('JobSummary', {
editTitle: '{{ id }} - {{ name }}',
name: 'jobs',
@@ -21,12 +20,12 @@ angular.module('JobSummaryDefinition', [])
control: 'Status ' +
' {{ status }}
',
readonly: true
- },
+ },
created: {
label: 'Created On',
type: 'text',
readonly: true
- },
+ },
result_stdout: {
label: 'Standard Out',
type: 'textarea',
@@ -35,7 +34,7 @@ angular.module('JobSummaryDefinition', [])
rows: '{{ stdout_rows }}',
'class': 'nowrap mono-space resizable',
ngShow: 'result_stdout != ""'
- },
+ },
result_traceback: {
label: 'Traceback',
type: 'textarea',
@@ -44,7 +43,6 @@ angular.module('JobSummaryDefinition', [])
rows: '{{ traceback_rows }}',
'class': 'nowrap mono-space resizable',
ngShow: 'result_traceback != ""'
- }
+ }
}
-
});
\ No newline at end of file
diff --git a/awx/ui/static/js/forms/JobTemplates.js b/awx/ui/static/js/forms/JobTemplates.js
index 6bffeb246b..45ef4de50f 100644
--- a/awx/ui/static/js/forms/JobTemplates.js
+++ b/awx/ui/static/js/forms/JobTemplates.js
@@ -7,11 +7,10 @@
*
*/
angular.module('JobTemplateFormDefinition', [])
- .value(
- 'JobTemplateForm', {
+ .value('JobTemplateForm', {
- addTitle: 'Create Job Templates', //Legend in add mode
- editTitle: '{{ name }}', //Legend in edit mode
+ addTitle: 'Create Job Templates',
+ editTitle: '{{ name }}',
name: 'job_templates',
twoColumns: true,
well: true,
@@ -25,8 +24,8 @@ angular.module('JobTemplateFormDefinition', [])
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
- }
- },
+ }
+ },
fields: {
name: {
@@ -35,20 +34,20 @@ angular.module('JobTemplateFormDefinition', [])
addRequired: true,
editRequired: true,
column: 1
- },
- description: {
+ },
+ description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false,
column: 1
- },
+ },
job_type: {
label: 'Job Type',
type: 'select',
ngOptions: 'type.label for type in job_type_options',
"default": 0,
- addRequired: true,
+ addRequired: true,
editRequired: true,
column: 1,
awPopOver: "When this template is submitted as a job, setting the type to run will execute the playbook, running tasks " +
@@ -57,7 +56,7 @@ angular.module('JobTemplateFormDefinition', [])
dataTitle: 'Job Type',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
inventory: {
label: 'Inventory',
type: 'lookup',
@@ -70,7 +69,7 @@ angular.module('JobTemplateFormDefinition', [])
dataTitle: 'Inventory',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
project: {
label: 'Project',
type: 'lookup',
@@ -83,7 +82,7 @@ angular.module('JobTemplateFormDefinition', [])
dataTitle: 'Project',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
playbook: {
label: 'Playbook',
type:'select',
@@ -95,29 +94,29 @@ angular.module('JobTemplateFormDefinition', [])
dataTitle: 'Playbook',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
credential: {
label: 'Machine Credential',
type: 'lookup',
sourceModel: 'credential',
sourceField: 'name',
ngClick: 'lookUpCredential()',
- addRequired: false,
+ addRequired: false,
editRequired: false,
column: 1,
- awPopOver: "
Select the credential you want the job to use when accessing the remote hosts. Choose the credential containing " +
+ awPopOver: "
Select the credential you want the job to use when accessing the remote hosts. Choose the credential containing " +
" the username and SSH key or password that Ansbile will need to log into the remote hosts.
",
dataTitle: 'Credential',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
cloud_credential: {
label: 'Cloud Credential',
type: 'lookup',
sourceModel: 'cloud_credential',
sourceField: 'name',
ngClick: 'lookUpCloudcredential()',
- addRequired: false,
+ addRequired: false,
editRequired: false,
column: 1,
awPopOver: "Selecting an optional cloud credential in the job template will pass along the access credentials to the " +
@@ -125,16 +124,16 @@ angular.module('JobTemplateFormDefinition', [])
dataTitle: 'Cloud Credential',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
forks: {
label: 'Forks',
id: 'forks-number',
- type: 'number',
+ type: 'number',
integer: true,
min: 0,
- spinner: true,
+ spinner: true,
"default": '0',
- addRequired: false,
+ addRequired: false,
editRequired: false,
'class': "input-small",
column: 1,
@@ -144,11 +143,11 @@ angular.module('JobTemplateFormDefinition', [])
dataTitle: 'Forks',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
limit: {
label: 'Limit',
- type: 'text',
- addRequired: false,
+ type: 'text',
+ addRequired: false,
editRequired: false,
column: 1,
awPopOver: "
Provide a host pattern to further constrain the list of hosts that will be managed or affected by the playbook. " +
@@ -157,26 +156,26 @@ angular.module('JobTemplateFormDefinition', [])
dataTitle: 'Limit',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
verbosity: {
label: 'Verbosity',
type: 'select',
ngOptions: 'v.label for v in verbosity_options',
"default": 0,
- addRequired: true,
+ addRequired: true,
editRequired: true,
column: 1,
awPopOver: "
Control the level of output ansible will produce as the playbook executes.
",
dataTitle: 'Verbosity',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
variables: {
label: 'Extra Variables',
type: 'textarea',
rows: 6,
"class": 'span12',
- addRequired: false,
+ addRequired: false,
editRequired: false,
"default": "---",
column: 2,
@@ -189,13 +188,13 @@ angular.module('JobTemplateFormDefinition', [])
dataTitle: 'Extra Variables',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
job_tags: {
label: 'Job Tags',
- type: 'textarea',
- rows: 1,
- addRequired: false,
- editRequired: false,
+ type: 'textarea',
+ rows: 1,
+ addRequired: false,
+ editRequired: false,
'class': 'span12',
column: 2,
awPopOver: "Provide a comma separated list of tags.
\n" +
@@ -203,26 +202,25 @@ angular.module('JobTemplateFormDefinition', [])
"For example, you might have a task consisiting of a long list of actions. Tag values can be assigned to each action. " +
"Suppose the actions have been assigned tag values of "configuration", "packages" and "install".
" +
"If you just want to run the "configuration" and "packages" actions, you would enter the following here " +
- "in the Job Tags field:<\p>\n" +
- "
configuration,packages \n",
+ "in the Job Tags field:\nconfiguration,packages \n",
dataTitle: "Job Tags",
dataPlacement: "right",
dataContainer: "body"
- },
+ },
allow_callbacks: {
label: 'Allow Callbacks',
type: 'checkbox',
- addRequired: false,
+ addRequired: false,
editRequird: false,
trueValue: 'true',
falseValue: 'false',
ngChange: "toggleCallback('host_config_key')",
column: 2,
- awPopOver: "Create a callback URL a host can use to contact Tower and request a configuration update " +
+ awPopOver: "
Create a callback URL a host can use to contact Tower and request a configuration update " +
"using the job template. The URL will look like the following:
\n" +
"http://your.server.com:999/api/v1/job_templates/1/callback/
" +
"The request from the host must be a POST. Here is an example using curl:
\n" +
- "curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
+ "
curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
"http://your.server.com:999/api/v1/job_templates/1/callback/
\n" +
"Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address " +
"in one of your defined inventories, the request will be denied.
" +
@@ -230,11 +228,11 @@ angular.module('JobTemplateFormDefinition', [])
dataPlacement: 'right',
dataTitle: 'Callback URL',
dataContainer: "body"
- },
+ },
callback_url: {
- label: 'Callback URL',
+ label: 'Callback URL',
type: 'text',
- addRequired: false,
+ addRequired: false,
editRequired: false,
readonly: true,
column: 2,
@@ -242,7 +240,7 @@ angular.module('JobTemplateFormDefinition', [])
'class': 'span12',
awPopOver: "Using this URL a host can contact Tower and request a configuration update using the job " +
"template. The request from the host must be a POST. Here is an example using curl:
\n" +
- "curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
+ "
curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
"http://your.server.com:999/api/v1/job_templates/1/callback/
\n" +
"Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address " +
"in one of your defined inventories, the request will be denied.
" +
@@ -250,7 +248,7 @@ angular.module('JobTemplateFormDefinition', [])
dataPlacement: 'right',
dataTitle: 'Callback URL',
dataContainer: "body"
- },
+ },
host_config_key: {
label: 'Host Config Key',
type: 'text',
@@ -259,25 +257,25 @@ angular.module('JobTemplateFormDefinition', [])
column: 2,
awPopOver: "When contacting the Tower server using the callback URL, the calling host must authenticate by including " +
"this key in the POST data of the request. Here's an example using curl:
\n" +
- "curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
+ "
curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
"http://your.server.com:999/api/v1/job_templates/1/callback/
\n",
dataPlacement: 'right',
dataContainer: "body"
- }
- },
+ }
+ },
buttons: { //for now always generates tags
- save: {
+ save: {
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
- },
- reset: {
+ },
+ reset: {
ngClick: 'formReset()',
ngDisabled: true //Disabled when $pristine
- }
- },
+ }
+ },
- related: { //related colletions (and maybe items?)
+ related: {
jobs: {
type: 'collection',
@@ -295,54 +293,55 @@ angular.module('JobTemplateFormDefinition', [])
awToolTip: "Reset the search filter",
ngClick: "resetSearch('job')",
iconSize: 'large'
- }
- },
+ }
+ },
fields: {
id: {
label: 'Job ID',
key: true,
desc: true,
- searchType: 'int'
- },
+ searchType: 'int'
+ },
created: {
label: 'Date',
link: false,
searchable: false
- },
+ },
status: {
label: 'Status',
- "class": 'job-\{\{ job.status \}\}',
+ "class": 'job-{{ job.status }}',
searchType: 'select',
- linkTo: "\{\{ job.statusLinkTo \}\}",
+ linkTo: "{{}} job.statusLinkTo }}",
searchOptions: [
{ name: "new", value: "new" },
{ name: "waiting", value: "waiting" },
{ name: "pending", value: "pending" },
- { name: "running", value: "running" },
+ { name: "running", value: "running" },
{ name: "successful", value: "successful" },
{ name: "error", value: "error" },
{ name: "failed", value: "failed" },
- { name: "canceled", value: "canceled" } ],
- badgeIcon: 'fa icon-job-\{\{ job.status \}\}',
+ { name: "canceled", value: "canceled" }
+ ],
+ badgeIcon: 'fa icon-job-{{ job.status }}',
badgePlacement: 'left',
- badgeToolTip: "\{\{ job.statusBadgeToolTip \}\}",
+ badgeToolTip: "{{ job.statusBadgeToolTip }}",
badgeTipPlacement: 'top',
- badgeNgHref: "\{\{ job.statusLinkTo \}\}",
- awToolTip: "\{\{ job.statusBadgeToolTip \}\}",
+ badgeNgHref: "{{ job.statusLinkTo }}",
+ awToolTip: "{{ job.statusBadgeToolTip }}",
dataPlacement: 'top'
- }
- },
+ }
+ },
fieldActions: {
edit: {
label: 'View',
- ngClick: "edit('jobs', \{\{ job.id \}\}, '\{\{ job.name \}\}')",
+ ngClick: "edit('jobs', job.id, job.name)",
icon: 'icon-zoom-in'
- }
}
}
}
+ }
}); //InventoryForm
diff --git a/awx/ui/static/js/forms/Jobs.js b/awx/ui/static/js/forms/Jobs.js
index 6b60223d78..e2dd84f4dc 100644
--- a/awx/ui/static/js/forms/Jobs.js
+++ b/awx/ui/static/js/forms/Jobs.js
@@ -7,9 +7,8 @@
* @dict
*/
angular.module('JobFormDefinition', [])
- .value(
- 'JobForm', {
-
+ .value('JobForm', {
+
addTitle: 'Create Job',
editTitle: '{{ id }} - {{ name }}',
name: 'jobs',
@@ -26,19 +25,19 @@ angular.module('JobFormDefinition', [])
icon: 'icon-zoom-in',
active: true,
ngShow: "job_id !== null"
- },
+ },
events: {
href: "/#/jobs/{{ job_id }}/job_events",
label: 'Events',
icon: 'icon-list-ul'
- },
- hosts: {
+ },
+ hosts: {
href: "/#/jobs/{{ job_id }}/job_host_summaries",
label: 'Host Summary',
icon: 'icon-laptop'
- }
- },
-
+ }
+ },
+
fields: {
name: {
label: 'Job Template',
@@ -47,20 +46,20 @@ angular.module('JobFormDefinition', [])
editRequired: false,
readonly: true,
column: 1
- },
- description: {
+ },
+ description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false,
column: 1
- },
+ },
job_type: {
label: 'Job Type',
type: 'select',
ngOptions: 'type.label for type in job_type_options',
"default": 'run',
- addRequired: true,
+ addRequired: true,
editRequired: true,
awPopOver: "When this template is submitted as a job, setting the type to run will execute the playbook, running tasks " +
" on the selected hosts.
Setting the type to check will not execute the playbook. Instead, ansible will check playbook " +
@@ -69,7 +68,7 @@ angular.module('JobFormDefinition', [])
dataPlacement: 'right',
dataContainer: 'body',
column: 1
- },
+ },
inventory: {
label: 'Inventory',
type: 'lookup',
@@ -83,7 +82,7 @@ angular.module('JobFormDefinition', [])
dataTitle: 'Inventory',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
project: {
label: 'Project',
type: 'lookup',
@@ -97,42 +96,42 @@ angular.module('JobFormDefinition', [])
dataTitle: 'Project',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
playbook: {
label: 'Playbook',
- type:'select',
+ type: 'select',
ngOptions: 'book for book in playbook_options',
id: 'playbook-select',
- addRequired: true,
+ addRequired: true,
editRequired: true,
column: 1,
awPopOver: "
Select the playbook to be executed by this job.
",
dataTitle: 'Playbook',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
credential: { // FIXME: Lookup only credentials with kind=ssh
label: 'Credential',
type: 'lookup',
sourceModel: 'credential',
sourceField: 'name',
ngClick: 'lookUpCredential()',
- addRequired: false,
+ addRequired: false,
editRequired: false,
column: 1,
- awPopOver: "Select the credential you want the job to use when accessing the remote hosts. Choose the credential containing " +
- " the username and SSH key or password that Ansbile will need to log into the remote hosts.
",
+ awPopOver: "Select the credential you want the job to use when accessing the remote hosts. Choose the credential containing " +
+ " the username and SSH key or password that Ansbile will need to log into the remote hosts.
",
dataTitle: 'Credential',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
cloud_credential: { // FIXME: Lookup only credentials with kind=aws/rax
label: 'Cloud Credential',
type: 'lookup',
sourceModel: 'cloud_credential',
sourceField: 'name',
ngClick: 'lookUpCredential()',
- addRequired: false,
+ addRequired: false,
editRequired: false,
column: 1,
awPopOver: "Selecting an optional cloud credential in the job template will pass along the access credentials to the " +
@@ -140,17 +139,17 @@ angular.module('JobFormDefinition', [])
dataTitle: 'Cloud Credential',
dataPlacement: 'right',
dataContainer: "body"
- },
+ },
forks: {
label: 'Forks',
id: 'forks-number',
- type: 'number',
+ type: 'number',
integer: true,
min: 0,
- spinner: true,
+ spinner: true,
"class": 'input-small',
"default": '0',
- addRequired: false,
+ addRequired: false,
editRequired: false,
column: 1,
disabled: true,
@@ -158,43 +157,43 @@ angular.module('JobFormDefinition', [])
dataContainer: 'body',
dataTitle: 'Forks',
dataPlacement: 'right'
- },
+ },
limit: {
label: 'Limit',
- type: 'text',
- addRequired: false,
+ type: 'text',
+ addRequired: false,
editRequired: false,
column: 1,
awPopOver: "
Provide a host pattern to further constrain the list of hosts that will be managed or affected by the playbook. " +
"Multiple patterns can be separated by ; : or ,
For more information and examples see the " +
- "Selecting Targets section under Inventory and Patterns " +
+ "Selecting Targets section under Inventory and Patterns " +
" in the Ansible documentation.
",
dataContainer: 'body',
dataTitle: 'Limit',
dataPlacement: 'right'
- },
+ },
verbosity: {
label: 'Verbosity',
type: 'select',
ngOptions: 'v.label for v in verbosity_options',
"default": 0,
- addRequired: true,
+ addRequired: true,
editRequired: true,
column: 1,
awPopOver: "Control the level of output ansible will produce as the playbook executes.
",
dataTitle: 'Verbosity',
dataPlacement: 'right',
dataContainer: 'body'
- },
+ },
variables: {
label: 'Extra Variables',
type: 'textarea',
rows: 6,
"class": 'span12',
- addRequired: false,
+ addRequired: false,
editRequired: false,
column: 2,
- awPopOver: "Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter " +
+ awPopOver: "
Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter " +
"for ansible-playbook. Provide key/value pairs using either YAML or JSON.
" +
"JSON: \n" +
"{ \"somevar\": \"somevalue\", \"password\": \"magic\" } \n" +
@@ -203,13 +202,13 @@ angular.module('JobFormDefinition', [])
dataTitle: 'Extra Variables',
dataContainer: 'body',
dataPlacement: 'right'
- },
+ },
job_tags: {
label: 'Job Tags',
- type: 'textarea',
- rows: 1,
- addRequired: false,
- editRequired: false,
+ type: 'textarea',
+ rows: 1,
+ addRequired: false,
+ editRequired: false,
'class': 'span12',
column: 2,
awPopOver: "Provide a comma separated list of tags.
\n" +
@@ -217,27 +216,27 @@ angular.module('JobFormDefinition', [])
"For example, you might have a task consisiting of a long list of actions. Tag values can be assigned to each action. " +
"Suppose the actions have been assigned tag values of "configuration", "packages" and "install".
" +
"If you just want to run the "configuration" and "packages" actions, you would enter the following here " +
- "in the Job Tags field:<\p>\n" +
+ "in the Job Tags field:
\n" +
"configuration,packages \n",
dataTitle: "Job Tags",
dataContainer: 'body',
dataPlacement: "right"
- },
+ },
allow_callbacks: {
label: 'Allow Callbacks',
type: 'checkbox',
- addRequired: false,
+ addRequired: false,
editRequird: false,
trueValue: 'true',
falseValue: 'false',
ngChange: "toggleCallback('host_config_key')",
"class": "span12",
column: 2,
- awPopOver: "Create a callback URL a host can use to contact Tower and request a configuration update " +
+ awPopOver: "
Create a callback URL a host can use to contact Tower and request a configuration update " +
"using the job template. The URL will look like the following:
\n" +
"http://your.server.com:999/api/v1/job_templates/1/callback/
" +
"The request from the host must be a POST. Here is an example using curl:
\n" +
- "curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
+ "
curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
"http://your.server.com:999/api/v1/job_templates/1/callback/
\n" +
"Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address " +
"in one of your defined inventories, the request will be denied.
" +
@@ -245,11 +244,11 @@ angular.module('JobFormDefinition', [])
dataPlacement: 'right',
dataContainer: 'body',
dataTitle: 'Callback URL'
- },
+ },
callback_url: {
- label: 'Callback URL',
+ label: 'Callback URL',
type: 'text',
- addRequired: false,
+ addRequired: false,
editRequired: false,
readonly: true,
column: 2,
@@ -257,7 +256,7 @@ angular.module('JobFormDefinition', [])
'class': 'span12',
awPopOver: "Using this URL a host can contact Tower and request a configuration update using the job " +
"template. The request from the host must be a POST. Here is an example using curl:
\n" +
- "curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
+ "
curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
"http://your.server.com:999/api/v1/job_templates/1/callback/
\n" +
"Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address " +
"in one of your defined inventories, the request will be denied.
" +
@@ -265,7 +264,7 @@ angular.module('JobFormDefinition', [])
dataPlacement: 'right',
dataContainer: 'body',
dataTitle: 'Callback URL'
- },
+ },
host_config_key: {
label: 'Host Config Key',
type: 'text',
@@ -274,64 +273,65 @@ angular.module('JobFormDefinition', [])
column: 2,
awPopOver: "When contacting Tower using the callback URL, the calling host must authenticate by including " +
"this key in the POST data of the request. Here's an example using curl:
\n" +
- "curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
+ "
curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
"http://your.server.com:999/api/v1/job_templates/1/callback/
\n",
dataPlacement: 'right',
dataContainer: 'body'
- }
- },
+ }
+ },
- buttons: { //for now always generates tags
- save: {
- label: 'Save',
+ buttons: {
+ save: {
+ label: 'Save',
icon: 'icon-ok',
"class": 'btn-success',
- ngClick: 'formSave()', //$scope.function to call on click, optional
- ngDisabled: true //Disable when $pristine or $invalid, optional
- },
- reset: {
+ ngClick: 'formSave()',
+ ngDisabled: true
+ },
+ reset: {
ngClick: 'formReset()',
label: 'Reset',
icon: 'icon-undo',
'class': 'btn btn-default',
- ngDisabled: true //Disabled when $pristine
- }
- },
+ ngDisabled: true
+ }
+ },
statusFields: {
status: {
//label: 'Job Status',
type: 'custom',
- control: 'Status \{\{ status \}\}
',
+ control: "Status " +
+ " {{ status }}
",
readonly: true
- },
+ },
created: {
label: 'Created On',
type: 'text',
readonly: true
- },
+ },
result_stdout: {
- label: 'Standard Out',
+ label: 'Standard Out',
type: 'textarea',
readonly: true,
xtraWide: true,
- rows: "\{\{ stdout_rows \}\}",
+ rows: "{{ stdout_rows }}",
"class": 'nowrap mono-space',
ngShow: "result_stdout != ''"
- },
+ },
result_traceback: {
label: 'Traceback',
type: 'textarea',
xtraWide: true,
readonly: true,
- rows: "\{\{ traceback_rows \}\}",
+ rows: "{{ traceback_rows }}",
"class": 'nowrap mono-space',
ngShow: "result_traceback != ''"
- }
- },
+ }
+ },
statusActions: {
- refresh: {
+ refresh: {
dataPlacement: 'top',
icon: "icon-refresh",
iconSize: 'large',
@@ -340,8 +340,7 @@ angular.module('JobFormDefinition', [])
'class': 'btn-xs btn-primary',
awToolTip: "Refresh the page",
ngClick: "refresh()"
- }
}
-
- }); //Form
+ }
+ });
\ No newline at end of file
diff --git a/awx/ui/static/js/forms/LicenseForm.js b/awx/ui/static/js/forms/LicenseForm.js
new file mode 100644
index 0000000000..cc0b3e6822
--- /dev/null
+++ b/awx/ui/static/js/forms/LicenseForm.js
@@ -0,0 +1,84 @@
+/*********************************************
+ * Copyright (c) 2014 AnsibleWorks, Inc.
+ *
+ * LicenseForm.js
+ *
+ *
+ */
+
+'use strict';
+
+angular.module('LicenseFormDefinition', [])
+ .value('LicenseForm', {
+
+ name: 'license',
+ well: false,
+ forceListeners: true,
+
+ fields: {
+ license_status: {
+ type: 'custom',
+ control: " " +
+ "{{ license_status }}
",
+ readonly: true,
+ section: 'License'
+ },
+ license_key: {
+ label: 'Key',
+ type: 'textarea',
+ 'class': 'modal-input-xlarge',
+ readonly: true,
+ section: 'License'
+ },
+ license_date: {
+ label: 'Expires On',
+ type: 'text',
+ readonly: true,
+ section: 'License'
+ },
+ time_remaining: {
+ label: 'Time Left',
+ type: 'text',
+ readonly: true,
+ section: 'License'
+ },
+ available_instances: {
+ label: 'Available',
+ type: 'text',
+ readonly: true,
+ section: 'Managed Hosts'
+ },
+ current_instances: {
+ label: 'Used',
+ type: 'text',
+ readonly: true,
+ section: 'Managed Hosts'
+ },
+ free_instances: {
+ label: 'Remaining',
+ type: 'text',
+ readonly: true,
+ section: 'Managed Hosts',
+ controlNGClass: 'free_instances_class',
+ labelNGClass: 'free_instances_class'
+ },
+ company_name: {
+ label: 'Company',
+ type: 'text',
+ readonly: true,
+ section: 'Contact Info'
+ },
+ contact_name: {
+ label: 'Contact',
+ type: 'text',
+ readonly: true,
+ section: 'Contact Info'
+ },
+ contact_email: {
+ label: 'Contact Email',
+ type: 'text',
+ readonly: true,
+ section: 'Contact Info'
+ }
+ }
+ });
\ No newline at end of file
diff --git a/awx/ui/static/js/forms/Organizations.js b/awx/ui/static/js/forms/Organizations.js
index 3992a0938b..8348b7600c 100644
--- a/awx/ui/static/js/forms/Organizations.js
+++ b/awx/ui/static/js/forms/Organizations.js
@@ -4,16 +4,15 @@
* Organization.js
* Form definition for Organization model
*
- *
+ *
*/
angular.module('OrganizationFormDefinition', [])
- .value(
- 'OrganizationForm', {
-
- addTitle: 'Create Organization', //Title in add mode
- editTitle: '{{ name }}', //Title in edit mode
- name: 'organization', //entity or model name in singular form
- well: true, //Wrap the form with TB well/
+ .value('OrganizationForm', {
+
+ addTitle: 'Create Organization', //Title in add mode
+ editTitle: '{{ name }}', //Title in edit mode
+ name: 'organization', //entity or model name in singular form
+ well: true,
actions: {
stream: {
@@ -24,8 +23,8 @@ angular.module('OrganizationFormDefinition', [])
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
- }
- },
+ }
+ },
fields: {
name: {
@@ -34,120 +33,118 @@ angular.module('OrganizationFormDefinition', [])
addRequired: true,
editRequired: true,
capitalize: false
- },
- description: {
+ },
+ description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
- }
- },
+ }
+ },
- buttons: { //for now always generates tags
- save: {
- ngClick: 'formSave()', //$scope.function to call on click, optional
- ngDisabled: true //Disable when $pristine or $invalid, optional
- },
- reset: {
+ buttons: { //for now always generates tags
+ save: {
+ ngClick: 'formSave()', //$scope.function to call on click, optional
+ ngDisabled: true //Disable when $pristine or $invalid, optional
+ },
+ reset: {
ngClick: 'formReset()',
- ngDisabled: true //Disabled when $pristine
- }
- },
+ ngDisabled: true //Disabled when $pristine
+ }
+ },
- related: { //related colletions (and maybe items?)
+ related: {
- users: {
+ users: {
type: 'collection',
title: 'Users',
iterator: 'user',
open: false,
-
- actions: {
+
+ actions: {
add: {
ngClick: "add('users')",
label: 'Add',
icon: 'icon-plus',
awToolTip: 'Add a new user'
- }
- },
-
+ }
+ },
+
fields: {
username: {
key: true,
label: 'Username'
- },
+ },
first_name: {
label: 'First Name'
- },
+ },
last_name: {
label: 'Last Name'
- }
- },
-
- fieldActions: {
- edit: {
- label: 'Edit',
- ngClick: "edit('users', \{\{ user.id \}\}, '\{\{ user.username \}\}')",
- icon: 'icon-edit',
- 'class': 'btn-default',
- awToolTip: 'Edit user'
- },
- "delete": {
- label: 'Delete',
- ngClick: "delete('users', \{\{ user.id \}\}, '\{\{ user.username \}\}', 'users')",
- icon: 'icon-trash',
- "class": 'btn-danger',
- awToolTip: 'Remove user'
- }
}
},
- admins: { // Assumes a plural name (e.g. things)
+ fieldActions: {
+ edit: {
+ label: 'Edit',
+ ngClick: "edit('users', user.id, user.username)",
+ icon: 'icon-edit',
+ 'class': 'btn-default',
+ awToolTip: 'Edit user'
+ },
+ "delete": {
+ label: 'Delete',
+ ngClick: "delete('users', user.id, user.username, 'users')",
+ icon: 'icon-trash',
+ "class": 'btn-danger',
+ awToolTip: 'Remove user'
+ }
+ }
+ },
+
+ admins: { // Assumes a plural name (e.g. things)
type: 'collection',
title: 'Administrators',
- iterator: 'admin', // Singular form of name (e.g. thing)
- open: false, // Open accordion on load?
+ iterator: 'admin', // Singular form of name (e.g. thing)
+ open: false, // Open accordion on load?
base: '/users',
- actions: { // Actions displayed top right of list
+ actions: { // Actions displayed top right of list
add: {
ngClick: "add('admins')",
icon: 'icon-plus',
label: 'Add',
awToolTip: 'Add new administrator'
- }
- },
+ }
+ },
fields: {
username: {
key: true,
label: 'Username'
- },
+ },
first_name: {
label: 'First Name'
- },
+ },
last_name: {
label: 'Last Name'
- }
- },
- fieldActions: { // Actions available on each row
+ }
+ },
+ fieldActions: { // Actions available on each row
edit: {
label: 'Edit',
- ngClick: "edit('users', \{\{ admin.id \}\}, '\{\{ admin.username \}\}')",
+ ngClick: "edit('users', admin.id, admin.username)",
icon: 'icon-edit',
awToolTip: 'Edit administrator',
'class': 'btn-default'
- },
+ },
"delete": {
label: 'Delete',
- ngClick: "delete('admins', \{\{ admin.id \}\}, '\{\{ admin.username \}\}', 'administrators')",
+ ngClick: "delete('admins', admin.id, admin.username, 'administrators')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Remove administrator'
- }
}
}
-
}
- }); //OrganizationForm
+ }
-
\ No newline at end of file
+ }); //OrganizationForm
diff --git a/awx/ui/static/js/forms/Permissions.js b/awx/ui/static/js/forms/Permissions.js
index 289aa345b5..f9c8c69fa5 100644
--- a/awx/ui/static/js/forms/Permissions.js
+++ b/awx/ui/static/js/forms/Permissions.js
@@ -5,60 +5,63 @@
*
* Form definition for Projects model
*
- *
+ *
*/
angular.module('PermissionFormDefinition', [])
- .value(
- 'PermissionsForm', {
-
- addTitle: 'Add Permission', //Title in add mode
- editTitle: '{{ name }}', //Title in edit mode
- name: 'permission', //entity or model name in singular form
- well: true, //Wrap the form with TB well
- forceListeners: true,
+ .value('PermissionsForm', {
+
+ addTitle: 'Add Permission', //Title in add mode
+ editTitle: '{{ name }}', //Title in edit mode
+ name: 'permission', //entity or model name in singular form
+ well: true, //Wrap the form with TB well
+ forceListeners: true,
stream: {
- 'class': "btn-primary btn-xs activity-btn",
- ngClick: "showActivity()",
- awToolTip: "View Activity Stream",
- dataPlacement: "top",
- icon: "icon-comments-alt",
- mode: 'edit',
- iconSize: 'large'
- },
-
+ 'class': "btn-primary btn-xs activity-btn",
+ ngClick: "showActivity()",
+ awToolTip: "View Activity Stream",
+ dataPlacement: "top",
+ icon: "icon-comments-alt",
+ mode: 'edit',
+ iconSize: 'large'
+ },
+
fields: {
category: {
label: 'Permission Type',
labelClass: 'prepend-asterisk',
type: 'radio_group',
- options: [
- { label: 'Inventory', value: 'Inventory', selected: true },
- { label: 'Deployment', value: 'Deploy'}
- ],
+ options: [{
+ label: 'Inventory',
+ value: 'Inventory',
+ selected: true
+ }, {
+ label: 'Deployment',
+ value: 'Deploy'
+ }],
ngChange: 'selectCategory()'
- },
+ },
name: {
label: 'Name',
type: 'text',
addRequired: true,
editRequired: true,
capitalize: false
- },
- description: {
+ },
+ description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
- },
+ },
user: {
- label: 'User',
+ label: 'User',
type: 'hidden'
- },
+ },
team: {
label: 'Team',
type: 'hidden'
- },
+ },
project: {
label: 'Project',
type: 'lookup',
@@ -66,44 +69,65 @@ angular.module('PermissionFormDefinition', [])
sourceField: 'name',
ngShow: "category == 'Deploy'",
ngClick: 'lookUpProject()',
- awRequiredWhen: { variable: "projectrequired", init: "false" }
- },
+ awRequiredWhen: {
+ variable: "projectrequired",
+ init: "false"
+ }
+ },
inventory: {
label: 'Inventory',
type: 'lookup',
sourceModel: 'inventory',
sourceField: 'name',
ngClick: 'lookUpInventory()',
- awRequiredWhen: {variable: "inventoryrequired", init: "true" }
- },
+ awRequiredWhen: {
+ variable: "inventoryrequired",
+ init: "true"
+ }
+ },
permission_type: {
label: 'Permission',
labelClass: 'prepend-asterisk',
type: 'radio_group',
- options: [
- {label: 'Read', value: 'read', ngShow: "category == 'Inventory'" },
- {label: 'Write', value: 'write', ngShow: "category == 'Inventory'" },
- {label: 'Admin', value: 'admin', ngShow: "category == 'Inventory'" },
- {label: 'Run', value: 'run', ngShow: "category == 'Deploy'" },
- {label: 'Check', value: 'check', ngShow: "category == 'Deploy'" }
- ],
- helpCollapse: [{ hdr: 'Permission', ngBind: 'permissionTypeHelp' }]
- }
- },
-
- buttons: { //for now always generates tags
- save: {
- ngClick: 'formSave()', //$scope.function to call on click, optional
- ngDisabled: true //Disable when $pristine or $invalid, optional
- },
- reset: {
- ngClick: 'formReset()',
- ngDisabled: true //Disabled when $pristine
- }
- },
-
- related: { //related colletions (and maybe items?)
-
+ options: [{
+ label: 'Read',
+ value: 'read',
+ ngShow: "category == 'Inventory'"
+ }, {
+ label: 'Write',
+ value: 'write',
+ ngShow: "category == 'Inventory'"
+ }, {
+ label: 'Admin',
+ value: 'admin',
+ ngShow: "category == 'Inventory'"
+ }, {
+ label: 'Run',
+ value: 'run',
+ ngShow: "category == 'Deploy'"
+ }, {
+ label: 'Check',
+ value: 'check',
+ ngShow: "category == 'Deploy'"
+ }],
+ helpCollapse: [{
+ hdr: 'Permission',
+ ngBind: 'permissionTypeHelp'
+ }]
}
+ },
+
+ buttons: {
+ save: {
+ ngClick: 'formSave()',
+ ngDisabled: true
+ },
+ reset: {
+ ngClick: 'formReset()',
+ ngDisabled: true
+ }
+ },
+
+ related: { }
}); // Form
\ No newline at end of file
diff --git a/awx/ui/static/js/forms/ProjectStatus.js b/awx/ui/static/js/forms/ProjectStatus.js
index 8de59fbcc4..cd6ba683a5 100644
--- a/awx/ui/static/js/forms/ProjectStatus.js
+++ b/awx/ui/static/js/forms/ProjectStatus.js
@@ -7,17 +7,16 @@
*
*/
angular.module('ProjectStatusDefinition', [])
- .value(
- 'ProjectStatusForm', {
+ .value('ProjectStatusForm', {
name: 'project_update',
- editTitle: 'SCM Status',
+ editTitle: 'SCM Status',
well: false,
'class': 'horizontal-narrow',
fields: {
created: {
- label: 'Created',
+ label: 'Created',
type: 'text',
readonly: true
},
@@ -27,7 +26,7 @@ angular.module('ProjectStatusDefinition', [])
readonly: true
},
result_stdout: {
- label: 'Std Out',
+ label: 'Std Out',
type: 'textarea',
ngShow: "result_stdout",
'class': 'mono-space',
@@ -35,7 +34,7 @@ angular.module('ProjectStatusDefinition', [])
rows: 15
},
result_traceback: {
- label: 'Traceback',
+ label: 'Traceback',
type: 'textarea',
ngShow: "result_traceback",
'class': 'mono-space',
diff --git a/awx/ui/static/js/forms/Projects.js b/awx/ui/static/js/forms/Projects.js
index 04c0e07ca1..b1f8e2cbb3 100644
--- a/awx/ui/static/js/forms/Projects.js
+++ b/awx/ui/static/js/forms/Projects.js
@@ -5,16 +5,15 @@
*
* Form definition for Projects model
*
- *
+ *
*/
angular.module('ProjectFormDefinition', [])
- .value(
- 'ProjectsForm', {
-
- addTitle: 'Create Project', // Title in add mode
- editTitle: '{{ name }}', // Title in edit mode
- name: 'project', // entity or model name in singular form
- well: true, // Wrap the form with TB well
+ .value('ProjectsForm', {
+
+ addTitle: 'Create Project', // Title in add mode
+ editTitle: '{{ name }}', // Title in edit mode
+ name: 'project', // entity or model name in singular form
+ well: true, // Wrap the form with TB well
forceListeners: true,
actions: {
@@ -26,8 +25,8 @@ angular.module('ProjectFormDefinition', [])
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
- }
- },
+ }
+ },
fields: {
name: {
@@ -36,13 +35,13 @@ angular.module('ProjectFormDefinition', [])
addRequired: true,
editRequired: true,
capitalize: false
- },
- description: {
+ },
+ description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
- },
+ },
organization: {
label: 'Organization',
type: 'lookup',
@@ -52,35 +51,38 @@ angular.module('ProjectFormDefinition', [])
editRequired: false,
excludeMode: 'edit',
ngClick: 'lookUpOrganization()',
- awRequiredWhen: {variable: "organizationrequired", init: "true" },
+ awRequiredWhen: {
+ variable: "organizationrequired",
+ init: "true"
+ },
awPopOver: 'A project must have at least one organization. Pick one organization now to create the project, and then after ' +
- 'the project is created you can add additional organizations.
Only super users and organization administrators are allowed ' +
- 'to make changes to projects. Associating one or more organizations to a project determins which organizations admins have ' +
- 'access to modify the project.',
+ 'the project is created you can add additional organizations.
Only super users and organization administrators are allowed ' +
+ 'to make changes to projects. Associating one or more organizations to a project determins which organizations admins have ' +
+ 'access to modify the project.',
dataTitle: 'Organization',
dataContainer: 'body',
dataPlacement: 'right'
- },
+ },
scm_type: {
label: 'SCM Type',
type: 'select',
ngOptions: 'type.label for type in scm_type_options',
ngChange: 'scmChange()',
- addRequired: true,
+ addRequired: true,
editRequired: true
- },
+ },
missing_path_alert: {
- type: 'alertblock',
- "class": 'alert-info',
+ type: 'alertblock',
+ "class": 'alert-info',
ngShow: "showMissingPlaybooksAlert && scm_type.value == ''",
alertTxt: '
WARNING: There are no unassigned playbook directories in the base ' +
'project path {{ base_dir }}. Either the projects directory is empty, or all of the contents are already assigned to ' +
- 'other projects. New projects can be checked out from source control by ' +
+ 'other projects. New projects can be checked out from source control by ' +
'changing the SCM type option rather than specifying checkout paths manually. To continue with manual setup, log into ' +
'the Tower host and ensure content is present in a subdirectory under {{ base_dir }}. Run "chown -R awx" on the content ' +
'directory to ensure Tower can read the playbooks.
',
closeable: false
- },
+ },
base_dir: {
label: 'Project Base Path',
type: 'textarea',
@@ -88,61 +90,69 @@ angular.module('ProjectFormDefinition', [])
showonly: true,
ngShow: "scm_type.value == ''",
awPopOver: 'Base path used for locating playbooks. Directories found inside this path will be listed in the playbook directory drop-down. ' +
- 'Together the base path and selected playbook directory provide the full path used to locate playbooks.
' +
- 'Use PROJECTS_ROOT in your environment settings file to determine the base path value.
',
+ 'Together the base path and selected playbook directory provide the full path used to locate playbooks.' +
+ 'Use PROJECTS_ROOT in your environment settings file to determine the base path value.
',
dataTitle: 'Project Base Path',
dataContainer: 'body',
dataPlacement: 'right'
- },
+ },
local_path: {
label: 'Playbook Directory',
type: 'select',
id: 'local-path-select',
ngOptions: 'path.label for path in project_local_paths',
- awRequiredWhen: { variable: "pathRequired", init: false },
+ awRequiredWhen: {
+ variable: "pathRequired",
+ init: false
+ },
ngShow: "scm_type.value == '' && !showMissingPlaybooksAlert",
awPopOver: 'Select from the list of directories found in the base path.' +
- 'Together the base path and the playbook directory provide the full path used to locate playbooks.
' +
- 'Use PROJECTS_ROOT in your environment settings file to determine the base path value.
',
+ 'Together the base path and the playbook directory provide the full path used to locate playbooks.' +
+ 'Use PROJECTS_ROOT in your environment settings file to determine the base path value.
',
dataTitle: 'Project Path',
dataContainer: 'body',
dataPlacement: 'right'
- },
+ },
scm_url: {
label: 'SCM URL',
type: 'text',
ngShow: "scm_type && scm_type.value !== ''",
- awRequiredWhen: { variable: "scmRequired", init: false },
- helpCollapse: [
- { hdr: 'GIT URLs',
- content: 'Example URLs for GIT SCM include:
https://github.com/ansible/ansible.git ' +
- 'git@github.com:ansible/ansible.git git://servername.example.com/ansible.git ' +
- 'Note: If using SSH protocol for GitHub or Bitbucket, enter in the SSH key only, ' +
- 'do not enter a username (other than git). Additionally, GitHub and Bitbucket do not support password authentication when using ' +
- 'SSH protocol. GIT read only protocol (git://) does not use username or password information.',
- show: "scm_type.value == 'git'" },
- { hdr: 'SVN URLs',
- content: '
Example URLs for Subversion SCM include:
' +
- 'https://github.com/ansible/ansible svn://servername.example.com/path ' +
- 'svn+ssh://servername.example.com/path ',
- show: "scm_type.value == 'svn'" },
- { hdr: 'Mercurial URLs',
- content: 'Example URLs for Mercurial SCM include:
' +
- 'https://bitbucket.org/username/project ssh://hg@bitbucket.org/username/project ' +
- 'ssh://server.example.com/path ' +
- 'Note: Mercurial does not support password authentication for SSH. ' +
- 'If applicable, add the username, password and key below. Do not put the username and key in the URL. ' +
- 'If using Bitbucket and SSH, do not supply your Bitbucket username.',
- show: "scm_type.value == 'hg'" }
- ]
+ awRequiredWhen: {
+ variable: "scmRequired",
+ init: false
},
+ helpCollapse: [{
+ hdr: 'GIT URLs',
+ content: '
Example URLs for GIT SCM include:
https://github.com/ansible/ansible.git ' +
+ 'git@github.com:ansible/ansible.git git://servername.example.com/ansible.git ' +
+ 'Note: If using SSH protocol for GitHub or Bitbucket, enter in the SSH key only, ' +
+ 'do not enter a username (other than git). Additionally, GitHub and Bitbucket do not support password authentication when using ' +
+ 'SSH protocol. GIT read only protocol (git://) does not use username or password information.',
+ show: "scm_type.value == 'git'"
+ }, {
+ hdr: 'SVN URLs',
+ content: '
Example URLs for Subversion SCM include:
' +
+ 'https://github.com/ansible/ansible svn://servername.example.com/path ' +
+ 'svn+ssh://servername.example.com/path ',
+ show: "scm_type.value == 'svn'"
+ }, {
+ hdr: 'Mercurial URLs',
+ content: 'Example URLs for Mercurial SCM include:
' +
+ 'https://bitbucket.org/username/project ssh://hg@bitbucket.org/username/project ' +
+ 'ssh://server.example.com/path ' +
+ 'Note: Mercurial does not support password authentication for SSH. ' +
+ 'If applicable, add the username, password and key below. Do not put the username and key in the URL. ' +
+ 'If using Bitbucket and SSH, do not supply your Bitbucket username.',
+ show: "scm_type.value == 'hg'"
+ }]
+ },
scm_branch: {
labelBind: "scmBranchLabel",
type: 'text',
ngShow: "scm_type && scm_type.value !== ''",
addRequired: false,
editRequired: false
- },
+ },
credential: {
label: 'SCM Credential',
type: 'lookup',
@@ -150,111 +160,105 @@ angular.module('ProjectFormDefinition', [])
sourceModel: 'credential',
sourceField: 'name',
ngClick: 'lookUpCredential()',
- addRequired: false,
+ addRequired: false,
editRequired: false
- },
+ },
checkbox_group: {
label: 'SCM Update Options',
type: 'checkbox_group',
ngShow: "scm_type && scm_type.value !== ''",
- fields: [
- {
- name: 'scm_clean',
- label: 'Clean',
- type: 'checkbox',
- addRequired: false,
- editRequired: false,
- awPopOver: '
Remove any local modifications prior to performing an update.
',
- dataTitle: 'SCM Clean',
- dataContainer: 'body',
- dataPlacement: 'right',
- labelClass: 'checkbox-options'
- },
- {
- name: 'scm_delete_on_update',
- label: 'Delete on Update',
- type: 'checkbox',
- addRequired: false,
- editRequired: false,
- awPopOver: 'Delete the local repository in its entirety prior to performing an update.
Depending on the size of the ' +
- 'repository this may significantly increase the amount of time required to complete an update.
',
- dataTitle: 'SCM Delete',
- dataContainer: 'body',
- dataPlacement: 'right',
- labelClass: 'checkbox-options'
- },
- {
- name: 'scm_update_on_launch',
- label: 'Update on Launch',
- type: 'checkbox',
- addRequired: false,
- editRequired: false,
- awPopOver: 'Each time a job runs using this project, perform an update to the local repository prior to starting the job.
',
- dataTitle: 'SCM Update',
- dataContainer: 'body',
- dataPlacement: 'right',
- labelClass: 'checkbox-options'
- }
- ]
- }
- },
+ fields: [{
+ name: 'scm_clean',
+ label: 'Clean',
+ type: 'checkbox',
+ addRequired: false,
+ editRequired: false,
+ awPopOver: 'Remove any local modifications prior to performing an update.
',
+ dataTitle: 'SCM Clean',
+ dataContainer: 'body',
+ dataPlacement: 'right',
+ labelClass: 'checkbox-options'
+ }, {
+ name: 'scm_delete_on_update',
+ label: 'Delete on Update',
+ type: 'checkbox',
+ addRequired: false,
+ editRequired: false,
+ awPopOver: 'Delete the local repository in its entirety prior to performing an update.
Depending on the size of the ' +
+ 'repository this may significantly increase the amount of time required to complete an update.
',
+ dataTitle: 'SCM Delete',
+ dataContainer: 'body',
+ dataPlacement: 'right',
+ labelClass: 'checkbox-options'
+ }, {
+ name: 'scm_update_on_launch',
+ label: 'Update on Launch',
+ type: 'checkbox',
+ addRequired: false,
+ editRequired: false,
+ awPopOver: 'Each time a job runs using this project, perform an update to the local repository prior to starting the job.
',
+ dataTitle: 'SCM Update',
+ dataContainer: 'body',
+ dataPlacement: 'right',
+ labelClass: 'checkbox-options'
+ }]
+ }
+ },
- buttons: { //for now always generates tags
- save: {
- ngClick: 'formSave()', //$scope.function to call on click, optional
- ngDisabled: true //Disable when $pristine or $invalid, optional
- },
- reset: {
+ buttons: {
+ save: {
+ ngClick: 'formSave()',
+ ngDisabled: true
+ },
+ reset: {
ngClick: 'formReset()',
- ngDisabled: true //Disabled when $pristine
- }
- },
+ ngDisabled: true
+ }
+ },
- related: { //related colletions (and maybe items?)
+ related: {
organizations: {
type: 'collection',
title: 'Organizations',
iterator: 'organization',
open: false,
- actions: {
+ actions: {
add: {
ngClick: "add('organizations')",
icon: 'icon-plus',
label: 'Add',
awToolTip: 'Add an organization'
- }
- },
+ }
+ },
fields: {
name: {
key: true,
label: 'Name'
- },
+ },
description: {
label: 'Description'
- }
- },
+ }
+ },
fieldActions: {
edit: {
label: 'Edit',
- ngClick: "edit('organizations', \{\{ organization.id \}\}, '\{\{ organization.name \}\}')",
+ ngClick: "edit('organizations', organization.id, organization.name)",
icon: 'icon-edit',
awToolTip: 'Edit the organization',
'class': 'btn btn-default'
- },
+ },
"delete": {
label: 'Delete',
- ngClick: "delete('organizations', \{\{ organization.id \}\}, '\{\{ organization.name \}\}', 'organizations')",
+ ngClick: "delete('organizations', organization.id, organization.name, 'organizations')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Delete the organization'
- }
}
}
}
+ }
- }); // Form
-
-
+ }); // Form
\ No newline at end of file
diff --git a/awx/ui/static/js/forms/Teams.js b/awx/ui/static/js/forms/Teams.js
index b1329c330c..0645e6bdc5 100644
--- a/awx/ui/static/js/forms/Teams.js
+++ b/awx/ui/static/js/forms/Teams.js
@@ -4,14 +4,13 @@
* Teams.js
* Form definition for Team model
*
- *
+ *
*/
angular.module('TeamFormDefinition', [])
- .value(
- 'TeamForm', {
-
- addTitle: 'Create Team', //Legend in add mode
- editTitle: '{{ name }}', //Legend in edit mode
+ .value('TeamForm', {
+
+ addTitle: 'Create Team', //Legend in add mode
+ editTitle: '{{ name }}', //Legend in edit mode
name: 'team',
well: true,
collapse: true,
@@ -28,8 +27,8 @@ angular.module('TeamFormDefinition', [])
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
- }
- },
+ }
+ },
fields: {
name: {
@@ -38,228 +37,230 @@ angular.module('TeamFormDefinition', [])
addRequired: true,
editRequired: true,
capitalize: false
- },
- description: {
+ },
+ description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
- },
+ },
organization: {
label: 'Organization',
type: 'lookup',
sourceModel: 'organization',
sourceField: 'name',
ngClick: 'lookUpOrganization()',
- awRequiredWhen: {variable: "teamrequired", init: "true" }
+ awRequiredWhen: {
+ variable: "teamrequired",
+ init: "true"
}
- },
+ }
+ },
- buttons: { //for now always generates tags
- save: {
- ngClick: 'formSave()', //$scope.function to call on click, optional
- ngDisabled: true //Disable when $pristine or $invalid, optional
- },
- reset: {
+ buttons: {
+ save: {
+ ngClick: 'formSave()',
+ ngDisabled: true
+ },
+ reset: {
ngClick: 'formReset()',
- ngDisabled: true //Disabled when $pristine
- }
- },
+ ngDisabled: true
+ }
+ },
- related: { //related colletions (and maybe items?)
-
- credentials: {
+ related: {
+
+ credentials: {
type: 'collection',
title: 'Credentials',
iterator: 'credential',
open: false,
- actions: {
+ actions: {
add: {
ngClick: "add('credentials')",
icon: 'icon-plus',
label: 'Add',
add: 'Add a new credential'
- }
- },
-
+ }
+ },
+
fields: {
name: {
key: true,
label: 'Name'
- },
+ },
description: {
label: 'Description'
- }
- },
-
+ }
+ },
+
fieldActions: {
edit: {
label: 'Edit',
- ngClick: "edit('credentials', \{\{ credential.id \}\}, '\{\{ credential.name \}\}')",
+ ngClick: "edit('credentials', credential.id, credential.name)",
icon: 'icon-edit',
awToolTip: 'Modify the credential',
'class': 'btn btn-default'
- },
+ },
"delete": {
label: 'Delete',
- ngClick: "delete('credentials', \{\{ credential.id \}\}, '\{\{ credential.name \}\}', 'credentials')",
+ ngClick: "delete('credentials', credential.id, credential.name, 'credentials')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Remove the credential'
- }
}
- },
+ }
+ },
permissions: {
type: 'collection',
title: 'Permissions',
iterator: 'permission',
open: false,
-
- actions: {
+
+ actions: {
add: {
ngClick: "add('permissions')",
icon: 'icon-plus',
label: 'Add',
awToolTip: 'Add a permission for this user',
ngShow: 'PermissionAddAllowed'
- }
- },
+ }
+ },
fields: {
name: {
- key: true,
+ key: true,
label: 'Name',
- ngClick: "edit('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}')"
- },
+ ngClick: "edit('permissions', permission.id, permission.name)"
+ },
inventory: {
label: 'Inventory',
sourceModel: 'inventory',
sourceField: 'name',
ngBind: 'permission.summary_fields.inventory.name'
- },
+ },
project: {
label: 'Project',
sourceModel: 'project',
sourceField: 'name',
ngBind: 'permission.summary_fields.project.name'
- },
- permission_type: {
- label: 'Permission'
- }
},
-
+ permission_type: {
+ label: 'Permission'
+ }
+ },
+
fieldActions: {
edit: {
label: 'Edit',
- ngClick: "edit('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}')",
+ ngClick: "edit('permissions', permission.id, permission.name)",
icon: 'icon-edit',
awToolTip: 'Edit the permission',
'class': 'btn btn-default'
- },
-
+ },
+
"delete": {
label: 'Delete',
- ngClick: "delete('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}', 'permissions')",
+ ngClick: "delete('permissions', permission.id, permission.name, 'permissions')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Delete the permission',
ngShow: 'PermissionAddAllowed'
- }
}
+ }
- },
+ },
- projects: {
+ projects: {
type: 'collection',
title: 'Projects',
iterator: 'project',
open: false,
- actions: {
+ actions: {
add: {
ngClick: "add('projects')",
icon: 'icon-plus',
label: 'Add'
- }
- },
-
+ }
+ },
+
fields: {
name: {
key: true,
label: 'Name'
- },
+ },
description: {
label: 'Description'
- }
- },
-
- fieldActions: {
- edit: {
- label: 'Edit',
- ngClick: "edit('projects', \{\{ project.id \}\}, '\{\{ project.name \}\}')",
- icon: 'icon-edit',
- awToolTip: 'Modify the project',
- 'class': 'btn btn-default'
- },
- "delete": {
- label: 'Delete',
- ngClick: "delete('projects', \{\{ project.id \}\}, '\{\{ project.name \}\}', 'projects')",
- icon: 'icon-trash',
- "class": 'btn-danger',
- awToolTip: 'Remove the project'
- }
}
},
- users: {
+ fieldActions: {
+ edit: {
+ label: 'Edit',
+ ngClick: "edit('projects', project.id, project.name)",
+ icon: 'icon-edit',
+ awToolTip: 'Modify the project',
+ 'class': 'btn btn-default'
+ },
+ "delete": {
+ label: 'Delete',
+ ngClick: "delete('projects', project.id, project.name, 'projects')",
+ icon: 'icon-trash',
+ "class": 'btn-danger',
+ awToolTip: 'Remove the project'
+ }
+ }
+ },
+
+ users: {
type: 'collection',
title: 'Users',
iterator: 'user',
open: false,
- actions: {
+ actions: {
add: {
ngClick: "add('users')",
icon: 'icon-plus',
label: 'Add',
awToolTip: 'Add a user'
- }
- },
-
+ }
+ },
+
fields: {
username: {
key: true,
label: 'Username'
- },
+ },
first_name: {
label: 'First Name'
- },
+ },
last_name: {
label: 'Last Name'
- }
- },
-
+ }
+ },
+
fieldActions: {
edit: {
label: 'Edit',
- ngClick: "edit('users', \{\{ user.id \}\}, '\{\{ user.username \}\}')",
+ ngClick: "edit('users', user.id, user.username)",
icon: 'icon-edit',
awToolTip: 'Edit user',
'class': 'btn btn-default'
- },
+ },
"delete": {
label: 'Delete',
- ngClick: "delete('users', \{\{ user.id \}\}, '\{\{ user.username \}\}', 'users')",
+ ngClick: "delete('users', user.id, user.username, 'users')",
icon: 'icon-terash',
"class": 'btn-danger',
awToolTip: 'Remove user'
- }
}
}
-
}
-
- }); //InventoryForm
+ }
+
+ }); //InventoryForm
\ No newline at end of file
diff --git a/awx/ui/static/js/forms/Users.js b/awx/ui/static/js/forms/Users.js
index 13e16da6e9..5baa3e8257 100644
--- a/awx/ui/static/js/forms/Users.js
+++ b/awx/ui/static/js/forms/Users.js
@@ -4,16 +4,15 @@
* Users.js
* Form definition for User model
*
- *
+ *
*/
angular.module('UserFormDefinition', [])
- .value(
- 'UserForm', {
-
- addTitle: 'Create User', //Legend in add mode
- editTitle: '{{ username }}', //Legend in edit mode
- name: 'user', //Form name attribute
- well: true, //Wrap the form with TB well
+ .value('UserForm', {
+
+ addTitle: 'Create User',
+ editTitle: '{{ username }}',
+ name: 'user',
+ well: true,
forceListeners: true,
actions: {
@@ -25,31 +24,31 @@ angular.module('UserFormDefinition', [])
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
- }
- },
+ }
+ },
fields: {
- first_name: {
+ first_name: {
label: 'First Name',
type: 'text',
addRequired: true,
editRequired: true,
capitalize: true
- },
- last_name: {
+ },
+ last_name: {
label: 'Last Name',
type: 'text',
addRequired: true,
editRequired: true,
capitalize: true
- },
+ },
email: {
label: 'Email',
type: 'email',
addRequired: true,
editRequired: true,
autocomplete: false
- },
+ },
organization: {
label: 'Organization',
type: 'lookup',
@@ -57,14 +56,20 @@ angular.module('UserFormDefinition', [])
sourceField: 'name',
ngClick: 'lookUpOrganization()',
excludeMode: 'edit',
- awRequiredWhen: { variable: "orgrequired", init: true }
- },
+ awRequiredWhen: {
+ variable: "orgrequired",
+ init: true
+ }
+ },
username: {
label: 'Username',
type: 'text',
- awRequiredWhen: { variable: "not_ldap_user", init: true },
- autocomplete: false
+ awRequiredWhen: {
+ variable: "not_ldap_user",
+ init: true
},
+ autocomplete: false
+ },
password: {
label: 'Password',
type: 'password',
@@ -74,7 +79,7 @@ angular.module('UserFormDefinition', [])
ngChange: "clearPWConfirm('password_confirm')",
autocomplete: false,
chkPass: true
- },
+ },
password_confirm: {
label: 'Confirm Password',
type: 'password',
@@ -84,7 +89,7 @@ angular.module('UserFormDefinition', [])
awPassMatch: true,
associated: 'password',
autocomplete: false
- },
+ },
is_superuser: {
label: 'Superuser (User has full system administration privileges.)',
type: 'checkbox',
@@ -92,171 +97,169 @@ angular.module('UserFormDefinition', [])
falseValue: 'false',
"default": 'false',
ngShow: "current_user['is_superuser'] == true"
- },
- ldap_user: {
- label: 'Created by LDAP',
+ },
+ ldap_user: {
+ label: 'Created by LDAP',
type: 'checkbox',
readonly: true
- }
- },
+ }
+ },
- buttons: { //for now always generates tags
- save: {
- ngClick: 'formSave()', //$scope.function to call on click, optional
- ngDisabled: true //Disable when $pristine or $invalid, optional
- },
- reset: {
+ buttons: {
+ save: {
+ ngClick: 'formSave()',
+ ngDisabled: true
+ },
+ reset: {
ngClick: 'formReset()',
- ngDisabled: true //Disabled when $pristine
- }
- },
+ ngDisabled: true
+ }
+ },
+
+ related: {
- related: { //related colletions (and maybe items?)
-
credentials: {
type: 'collection',
title: 'Credentials',
iterator: 'credential',
open: false,
- actions: {
+ actions: {
add: {
ngClick: "add('credentials')",
icon: 'icon-plus',
label: 'Add',
awToolTip: 'Add a credential for this user'
- }
- },
+ }
+ },
fields: {
name: {
key: true,
label: 'Name'
- },
+ },
description: {
label: 'Description'
- }
- },
+ }
+ },
fieldActions: {
edit: {
label: 'Edit',
- ngClick: "edit('credentials', \{\{ credential.id \}\}, '\{\{ credential.name \}\}')",
+ ngClick: "edit('credentials', credential.id, credential.name)",
icon: 'icon-edit',
awToolTip: 'Edit the credential',
'class': 'btn btn-default'
- },
+ },
"delete": {
label: 'Delete',
- ngClick: "delete('credentials', \{\{ credential.id \}\}, '\{\{ credential.name \}\}', 'credentials')",
+ ngClick: "delete('credentials', credential.id, credential.name, 'credentials')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Delete the credential'
- }
}
- },
-
+ }
+ },
+
permissions: {
type: 'collection',
title: 'Permissions',
iterator: 'permission',
open: false,
-
- actions: {
+
+ actions: {
add: {
ngClick: "add('permissions')",
icon: 'icon-plus',
label: 'Add',
awToolTip: 'Add a permission for this user',
ngShow: 'PermissionAddAllowed'
- }
- },
+ }
+ },
fields: {
name: {
- key: true,
+ key: true,
label: 'Name',
- ngClick: "edit('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}')"
- },
+ ngClick: "edit('permissions', permission.id, permission.name)"
+ },
inventory: {
label: 'Inventory',
sourceModel: 'inventory',
sourceField: 'name',
ngBind: 'permission.summary_fields.inventory.name'
- },
+ },
project: {
label: 'Project',
sourceModel: 'project',
sourceField: 'name',
ngBind: 'permission.summary_fields.project.name'
- },
+ },
permission_type: {
label: 'Permission'
- }
-
- },
-
+ }
+
+ },
+
fieldActions: {
edit: {
label: 'Edit',
- ngClick: "edit('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}')",
+ ngClick: "edit('permissions', permission.id, permission.name)",
icon: 'icon-edit',
awToolTip: 'Edit the permission',
'class': 'btn btn-default'
- },
-
+ },
+
"delete": {
label: 'Delete',
- ngClick: "delete('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}', 'permissions')",
+ ngClick: "delete('permissions', permission.id, permission.name, 'permissions')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Delete the permission',
ngShow: 'PermissionAddAllowed'
- }
}
+ }
- },
-
- admin_of_organizations: { // Assumes a plural name (e.g. things)
+ },
+
+ admin_of_organizations: { // Assumes a plural name (e.g. things)
type: 'collection',
title: 'Admin of Organizations',
- iterator: 'adminof', // Singular form of name (e.g. thing)
- open: false, // Open accordion on load?
+ iterator: 'adminof', // Singular form of name (e.g. thing)
+ open: false, // Open accordion on load?
base: '/organizations',
-
- actions: {
- },
+
+ actions: {},
fields: {
name: {
key: true,
label: 'Name'
- },
+ },
description: {
label: 'Description'
- }
}
- },
+ }
+ },
- organizations: {
+ organizations: {
type: 'collection',
title: 'Organizations',
iterator: 'organization',
open: false,
-
- actions: {
- },
+
+ actions: {},
fields: {
name: {
key: true,
label: 'Name'
- },
+ },
description: {
label: 'Description'
- }
}
- },
+ }
+ },
teams: {
type: 'collection',
@@ -264,19 +267,18 @@ angular.module('UserFormDefinition', [])
iterator: 'team',
open: false,
- actions: {
- },
+ actions: {},
fields: {
name: {
key: true,
label: 'Name'
- },
+ },
description: {
label: 'Description'
- }
}
- },
+ }
+ },
projects: {
type: 'collection',
@@ -284,21 +286,19 @@ angular.module('UserFormDefinition', [])
iterator: 'project',
open: false,
- actions: {
- },
+ actions: {},
fields: {
name: {
key: true,
label: 'Name'
- },
+ },
description: {
label: 'Description'
- }
}
}
-
}
- }); //UserForm
+ }
+ }); //UserForm
\ No newline at end of file
diff --git a/awx/ui/static/js/help/InventoryGroups.js b/awx/ui/static/js/help/InventoryGroups.js
index cdf01a5e3f..91e494bff9 100644
--- a/awx/ui/static/js/help/InventoryGroups.js
+++ b/awx/ui/static/js/help/InventoryGroups.js
@@ -1,65 +1,86 @@
/*********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
- * InventoryGroups.js
+ * InventoryGroups.js
*
* Help object for inventory groups/hosts page.
*
* @dict
*/
+'use strict';
+
angular.module('InventoryGroupsHelpDefinition', [])
- .value(
- 'InventoryGroupsHelp', {
+ .value('InventoryGroupsHelp', {
story: {
hdr: 'Building your inventory',
width: 510,
height: 560,
- steps: [
- {
+ steps: [{
intro: 'Start by creating a group:',
- img: { src: 'groups001.png', maxWidth: 338 , maxHeight: 222 },
+ img: {
+ src: 'groups001.png',
+ maxWidth: 338,
+ maxHeight: 222
+ },
box: "Click on the groups list (the left side of the page) to add a new group.",
autoOffNotice: true
- },
- {
+ }, {
intro: 'Enter group properties:',
- img: { src: 'groups002.png', maxWidth: 443, maxHeight: 251 },
+ img: {
+ src: 'groups002.png',
+ maxWidth: 443,
+ maxHeight: 251
+ },
box: 'Enter the group name, a description and any inventory variables. Variables can be entered using either JSON or YAML syntax. ' +
- 'For more on inventory variables, see ' +
- 'docs.ansible.com/intro_inventory.html '
- },
- {
+ 'For more on inventory variables, see ' +
+ 'docs.ansible.com/intro_inventory.html '
+ }, {
intro: 'Cloud inventory: select cloud source',
- img: { src: 'groups003.png', maxWidth: 412, maxHeight: 215 },
+ img: {
+ src: 'groups003.png',
+ maxWidth: 412,
+ maxHeight: 215
+ },
box: "For a cloud inventory, choose the cloud provider from the list and select your credentials. If you have not already setup " +
- "credentials for the provider, you will need to do that first on the Credentials tab."
- },
- {
+ "credentials for the provider, you will need to do that first on the Credentials tab."
+ }, {
intro: 'Cloud inventory: synchronize Tower with the cloud',
- img: { src: 'groups004.png', maxWidth: 261, maxHeight: 221 },
+ img: {
+ src: 'groups004.png',
+ maxWidth: 261,
+ maxHeight: 221
+ },
box: "To pull the cloud inventory into Tower, initiate an inventory sync by clicking ."
- },
- {
+ }, {
intro: "Groups can have subgroups:",
- img: { src: 'groups005.png', maxWidth: 430, maxHeight: 206 },
+ img: {
+ src: 'groups005.png',
+ maxWidth: 430,
+ maxHeight: 206
+ },
box: "First, select a group. Then click to create a new group. The new group " +
- "will be added to the selected group.
"
- },
- {
+ "will be added to the selected group."
+ }, {
intro: 'Copy or move groups:',
- img: { src: 'groups006.png', maxWidth: 263, maxHeight: 211 },
- box: "Copy or move a group by dragging and dropping its name onto another group name. A dialog will appear " +
- "asking if the group should be coppied or moved.
"
+ img: {
+ src: 'groups006.png',
+ maxWidth: 263,
+ maxHeight: 211
},
- {
+ box: "Copy or move a group by dragging and dropping its name onto another group name. A dialog will appear " +
+ "asking if the group should be coppied or moved.
"
+ }, {
intro: 'Adding hosts:',
- img: { src: 'groups007.png', maxWidth: 466, maxHeight: 178 },
- box: "First, select a Group. " +
- "Then click on the hosts list (the right side of the page) to create a host. " +
- "The new host will be part of the selected group.
Note hosts cannot be added to the All Hosts group.
"
- }
- ]
- }
- });
+ img: {
+ src: 'groups007.png',
+ maxWidth: 466,
+ maxHeight: 178
+ },
+ box: "First, select a Group. " +
+ "Then click on the hosts list (the right side of the page) to create a host. " +
+ "The new host will be part of the selected group.
Note hosts cannot be added to the All Hosts group.
"
+ }]
+ }
+ });
diff --git a/awx/ui/static/js/help/InventoryHosts.js b/awx/ui/static/js/help/InventoryHosts.js
deleted file mode 100644
index 35515c133b..0000000000
--- a/awx/ui/static/js/help/InventoryHosts.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/*********************************************
- * Copyright (c) 2014 AnsibleWorks, Inc.
- *
- * InventoryHosts.js
- * Help object for Inventory-> Hosts page.
- *
- *
- */
-angular.module('InventoryHostsHelpDefinition', [])
- .value(
- 'InventoryHostsHelp', {
- story: {
- hdr: 'Managing Hosts',
- steps: {
- step1: {
- intro: 'Start by selecting a group:',
- img: { src: 'help003.png', maxWidth: 315 , maxHeight: 198 },
- box: "On the group selector, click the name of a group. Hosts contained in the group" +
- " will appear on the right.",
- height: 500
- }
- }
- }
- });
\ No newline at end of file
diff --git a/awx/ui/static/js/helpers/Access.js b/awx/ui/static/js/helpers/Access.js
index 6f0604e119..527e7dabaf 100644
--- a/awx/ui/static/js/helpers/Access.js
+++ b/awx/ui/static/js/helpers/Access.js
@@ -4,102 +4,103 @@
* helpers/Access.js
*
* Routines for checking user access and license state
- *
+ *
*/
-angular.module('AccessHelper', ['RestServices', 'Utilities', 'ngCookies'])
- .factory('CheckAccess', ['$rootScope', 'Alert', 'Rest', 'GetBasePath','ProcessErrors',
- function($rootScope, Alert, Rest, GetBasePath, ProcessErrors) {
- return function(params) {
- // set PermissionAddAllowed to true or false based on user access. admins and org admins are granted
- // accesss.
- var me = $rootScope.current_user;
- var scope = params.scope;
+'use strict';
- if (me.is_superuser) {
- scope.PermissionAddAllowed = true;
- }
- else {
- if (me.related.admin_of_organizations) {
- Rest.setUrl(me.related.admin_of_organizations);
- Rest.get()
- .success( function(data, status, headers, config) {
- if (data.results.length > 0) {
- scope.PermissionAddAllowed = true;
- }
- else {
- scope.PermissionAddAllowed = false;
- }
- })
- .error( function(data, status, headers, config) {
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Call to ' + me.related.admin_of_organizations +
- ' failed. DELETE returned status: ' + status });
- });
- }
- }
- //if (!access) {
- // Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
- //}
- //return access;
- }
- }])
-
- .factory('CheckLicense', ['$rootScope', '$cookieStore', 'Alert', '$location', 'Authorization',
- function($rootScope, $cookieStore, Alert, $location, Authorization) {
- return function() {
- // Check license status and alert the user, if needed
- var status = 'success';
- var hdr, msg;
- var license = $cookieStore.get('license');
-
- var purchase_msg = 'To purchase a license or extend an existing license ' +
- 'visit the Ansible online store , ' +
- 'or visit support.ansible.com for assistance.
';
+angular.module('AccessHelper', ['RestServices', 'Utilities', 'ngCookies'])
+ .factory('CheckAccess', ['$rootScope', 'Alert', 'Rest', 'GetBasePath', 'ProcessErrors',
+ function ($rootScope, Alert, Rest, GetBasePath, ProcessErrors) {
+ return function (params) {
+ // set PermissionAddAllowed to true or false based on user access. admins and org admins are granted
+ // accesss.
+ var me = $rootScope.current_user,
+ scope = params.scope;
- if (license && !Authorization.licenseTested()) {
- // This is our first time evaluating the license
- license['tested'] = true;
- $cookieStore.remove('license');
- $cookieStore.put('license', license);
- $rootScope.license_tested = true;
- if (license['valid_key'] !== undefined && license['valid_key'] == false) {
- // The license is invalid. Stop the user from logging in.
- status = 'alert-danger';
- hdr = 'License Error';
- msg = 'There is a problem with the /etc/awx/license file on your Tower server. Check to make sure Tower can access ' +
- 'the file.
' + purchase_msg;
- Alert(hdr, msg, status, null, false, true);
- }
- else if (license['demo'] !== undefined && license['demo'] == true) {
- // demo
- status = 'alert-info';
- hdr = 'Tower Demo';
- msg = 'Thank you for trying Ansible Tower. You can use this edition to manage up to 10 hosts free.
' +
- purchase_msg;
- Alert(hdr, msg, status);
- }
- if (license['date_expired'] !== undefined && license['date_expired'] == true) {
- // expired
- status = 'alert-info';
- hdr = 'License Expired';
- msg = 'Your Ansible Tower License has expired and is no longer compliant. You can continue, but you will be ' +
- 'unable to add any additional hosts.
' + purchase_msg;
- Alert(hdr, msg, status);
- }
- else if (license['date_warning'] !== undefined && license['date_warning'] == true) {
- status = 'alert-info';
- hdr = 'License Warning';
- msg = 'Your Ansible Tower license is about to expire!
' + purchase_msg;
- Alert(hdr, msg, status);
- }
- if (license['free_instances'] !== undefined && parseInt(license['free_instances']) <= 0) {
- status = 'alert-info';
- hdr = 'License Warning';
- msg = 'Your Ansible Tower license has reached capacity for the number of managed ' +
- 'hosts allowed. You will not be able to add any additional hosts.
' + purchase_msg;
- Alert(hdr, msg, status, null, true);
- }
+ if (me.is_superuser) {
+ scope.PermissionAddAllowed = true;
+ } else {
+ if (me.related.admin_of_organizations) {
+ Rest.setUrl(me.related.admin_of_organizations);
+ Rest.get()
+ .success(function (data) {
+ if (data.results.length > 0) {
+ scope.PermissionAddAllowed = true;
+ } else {
+ scope.PermissionAddAllowed = false;
+ }
+ })
+ .error(function (data, status) {
+ ProcessErrors(scope, data, status, null, {
+ hdr: 'Error!',
+ msg: 'Call to ' + me.related.admin_of_organizations +
+ ' failed. DELETE returned status: ' + status
+ });
+ });
+ }
+ }
+ //if (!access) {
+ // Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
+ //}
+ //return access;
+ };
}
+ ])
+
+.factory('CheckLicense', ['$rootScope', '$cookieStore', 'Alert', '$location', 'Authorization',
+ function ($rootScope, $cookieStore, Alert, $location, Authorization) {
+ return function () {
+ // Check license status and alert the user, if needed
+ var status = 'success',
+ hdr, msg,
+ license = $cookieStore.get('license'),
+ purchase_msg = 'To purchase a license or extend an existing license ' +
+ 'visit the Ansible online store , ' +
+ 'or visit support.ansible.com for assistance.
';
+
+ if (license && !Authorization.licenseTested()) {
+ // This is our first time evaluating the license
+ license.tested = true;
+ $cookieStore.remove('license');
+ $cookieStore.put('license', license);
+ $rootScope.license_tested = true;
+ if (license.valid_key !== undefined && license.valid_key === false) {
+ // The license is invalid. Stop the user from logging in.
+ status = 'alert-danger';
+ hdr = 'License Error';
+ msg = 'There is a problem with the /etc/awx/license file on your Tower server. Check to make sure Tower can access ' +
+ 'the file.
' + purchase_msg;
+ Alert(hdr, msg, status, null, false, true);
+ } else if (license.demo !== undefined && license.demo === true) {
+ // demo
+ status = 'alert-info';
+ hdr = 'Tower Demo';
+ msg = 'Thank you for trying Ansible Tower. You can use this edition to manage up to 10 hosts free.
' +
+ purchase_msg;
+ Alert(hdr, msg, status);
+ }
+ if (license.date_expired !== undefined && license.date_expired === true) {
+ // expired
+ status = 'alert-info';
+ hdr = 'License Expired';
+ msg = 'Your Ansible Tower License has expired and is no longer compliant. You can continue, but you will be ' +
+ 'unable to add any additional hosts.
' + purchase_msg;
+ Alert(hdr, msg, status);
+ } else if (license.date_warning !== undefined && license.date_warning === true) {
+ status = 'alert-info';
+ hdr = 'License Warning';
+ msg = 'Your Ansible Tower license is about to expire!
' + purchase_msg;
+ Alert(hdr, msg, status);
+ }
+ if (license.free_instances !== undefined && parseInt(license.free_instances) <= 0) {
+ status = 'alert-info';
+ hdr = 'License Warning';
+ msg = 'Your Ansible Tower license has reached capacity for the number of managed ' +
+ 'hosts allowed. You will not be able to add any additional hosts.
' + purchase_msg;
+ Alert(hdr, msg, status, null, true);
+ }
+ }
+ };
}
- }]);
+]);
\ No newline at end of file
diff --git a/awx/ui/static/js/helpers/Children.js b/awx/ui/static/js/helpers/Children.js
index fc3fcbeac9..4bc3701c69 100644
--- a/awx/ui/static/js/helpers/Children.js
+++ b/awx/ui/static/js/helpers/Children.js
@@ -3,78 +3,62 @@
*
* ChildrenHelper
*
- * Used in job_events to expand/collapse children by setting the
+ * Used in job_events to expand/collapse children by setting the
* 'show' attribute of each job_event in the set of job_events.
* See the filter in job_events.js list.
*
*/
-
-angular.module('ChildrenHelper', ['RestServices', 'Utilities'])
- .factory('ToggleChildren', ['Alert', 'Rest', 'GetBasePath','ProcessErrors','FormatDate',
- function(Alert, Rest, GetBasePath, ProcessErrors, FormatDate) {
- return function(params) {
-
- var scope = params.scope;
- var list = params.list;
- var id = params.id;
- var set = scope[list.name]; // set is now a pointer to scope[list.name]
-
- function expand(node) {
- set[node]['ngicon'] = 'fa fa-minus-square-o node-toggle';
- for (var i = node + 1; i < set.length; i++) {
- if (set[i].parent == set[node].id) {
- set[i]['show'] = true;
- //if (set[i].related.children) {
- // expand(i);
- //}
- }
- }
- }
- function collapse(node) {
- set[node]['ngicon'] = 'fa fa-plus-square-o node-toggle';
- for (var i = node + 1; i < set.length; i++) {
- if (set[i].parent == set[node].id) {
- set[i]['show'] = false;
- if (set[i]['related']['children']) {
- collapse(i);
- }
- }
- }
- }
+'use strict';
- // Scan the array list and find the clicked element
- var clicked;
- var found = false;
- for (var i = 0; i < set.length && found == false; i++){
- if (set[i].id == id) {
- clicked = i;
- found = true;
+angular.module('ChildrenHelper', ['RestServices', 'Utilities'])
+ .factory('ToggleChildren', [ function () {
+ return function (params) {
+
+ var scope = params.scope,
+ list = params.list,
+ id = params.id,
+ set = scope[list.name],
+ i, clicked, found = false;
+
+ function expand(node) {
+ var i;
+ set[node].ngicon = 'fa fa-minus-square-o node-toggle';
+ for (i = node + 1; i < set.length; i++) {
+ if (set[i].parent === set[node].id) {
+ set[i].show = true;
+ }
+ }
}
- }
- // Expand or collapse children based on clicked element's icon
- if (/plus-square-o/.test(set[clicked]['ngicon'])) {
- // Expand: lookup and display children
- expand(clicked);
- }
- else if (/minus-square-o/.test(set[clicked]['ngicon'])) {
- collapse(clicked);
- }
+
+ function collapse(node) {
+ var i;
+ set[node].ngicon = 'fa fa-plus-square-o node-toggle';
+ for (i = node + 1; i < set.length; i++) {
+ if (set[i].parent === set[node].id) {
+ set[i].show = false;
+ if (set[i].related.children) {
+ collapse(i);
+ }
+ }
+ }
+ }
+
+ // Scan the array list and find the clicked element
+ for (i = 0; i < set.length && found === false; i++) {
+ if (set[i].id === id) {
+ clicked = i;
+ found = true;
+ }
+ }
+
+ // Expand or collapse children based on clicked element's icon
+ if (/plus-square-o/.test(set[clicked].ngicon)) {
+ // Expand: lookup and display children
+ expand(clicked);
+ } else if (/minus-square-o/.test(set[clicked].ngicon)) {
+ collapse(clicked);
+ }
+ };
}
- }]);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+]);
\ No newline at end of file
diff --git a/awx/ui/static/js/helpers/Credentials.js b/awx/ui/static/js/helpers/Credentials.js
index 4bd57bd3a0..7503ab16cf 100644
--- a/awx/ui/static/js/helpers/Credentials.js
+++ b/awx/ui/static/js/helpers/Credentials.js
@@ -7,176 +7,185 @@
*
*/
-angular.module('CredentialsHelper', ['Utilities'])
-
- .factory('KindChange', [ 'Empty', function(Empty) {
- return function(params) {
-
- var scope = params.scope;
- var form = params.form;
- var reset = params.reset;
+'use strict';
- // Put things in a default state
- scope['usernameLabel'] = 'Username';
- scope['aws_required'] = false;
- scope['rackspace_required'] = false;
- scope['sshKeyDataLabel'] = 'SSH Private Key';
-
- if (!Empty(scope['kind'])) {
- // Apply kind specific settings
- switch(scope['kind'].value) {
+angular.module('CredentialsHelper', ['Utilities'])
+
+.factory('KindChange', ['Empty',
+ function (Empty) {
+ return function (params) {
+
+ var scope = params.scope,
+ reset = params.reset,
+ collapse, id;
+
+ // Put things in a default state
+ scope.usernameLabel = 'Username';
+ scope.aws_required = false;
+ scope.rackspace_required = false;
+ scope.sshKeyDataLabel = 'SSH Private Key';
+
+ if (!Empty(scope.kind)) {
+ // Apply kind specific settings
+ switch (scope.kind.value) {
case 'aws':
- scope['aws_required'] = true;
- break;
- case 'rax':
- scope['rackspace_required'] = true;
+ scope.aws_required = true;
+ break;
+ case 'rax':
+ scope.rackspace_required = true;
break;
case 'ssh':
- scope['usernameLabel'] = 'SSH Username';
- break;
- case 'scm':
- scope['sshKeyDataLabel'] = 'SCM Private Key';
+ scope.usernameLabel = 'SSH Username';
+ break;
+ case 'scm':
+ scope.sshKeyDataLabel = 'SCM Private Key';
break;
- }
- }
-
- // Reset all the field values related to Kind.
- if (reset) {
- scope['access_key'] = null;
- scope['secret_key'] = null;
- scope['api_key'] = null;
- scope['username'] = null;
- scope['password'] = null;
- scope['password_confirm'] = null;
- scope['ssh_key_data'] = null;
- scope['ssh_key_unlock'] = null;
- scope['ssh_key_unlock_confirm'] = null;
- scope['sudo_username'] = null;
- scope['sudo_password'] = null;
- scope['sudo_password_confirm'] = null;
- }
-
- // Collapse or open help widget based on whether scm value is selected
- var collapse = $('#credential_kind').parent().find('.panel-collapse').first();
- var id = collapse.attr('id');
- if (!Empty(scope.kind) && scope.kind.value !== '') {
- if ( $('#' + id + '-icon').hasClass('icon-minus') ) {
- scope.accordionToggle('#' + id);
- }
- }
- else {
- if ( $('#' + id + '-icon').hasClass('icon-plus') ) {
- scope.accordionToggle('#' + id);
- }
- }
-
- }
- }])
-
-
- .factory('OwnerChange', [ function() {
- return function(params) {
- var scope = params.scope;
- var owner = scope['owner'];
- if (owner == 'team') {
- scope['team_required'] = true;
- scope['user_required'] = false;
- scope['user'] = null;
- scope['user_username'] = null;
- }
- else {
- scope['team_required'] = false;
- scope['user_required'] = true;
- scope['team'] = null;
- scope['team_name'] = null;
- }
-
- }
- }])
-
-
- .factory('FormSave', ['$location', 'Rest', 'ProcessErrors', 'Empty', 'GetBasePath', 'CredentialForm', 'ReturnToCaller', 'Wait',
- function($location, Rest, ProcessErrors, Empty, GetBasePath, CredentialForm, ReturnToCaller, Wait) {
- return function(params) {
- var scope = params.scope;
- var mode = params.mode; // add or edit
- var form = CredentialForm;
- var data = {}
-
- for (var fld in form.fields) {
- if (fld !== 'access_key' && fld !== 'secret_key' && fld !== 'ssh_username' &&
- fld !== 'ssh_password') {
- if (scope[fld] === null) {
- data[fld] = "";
- }
- else {
- data[fld] = scope[fld];
}
}
- }
-
- if (!Empty(scope.team)) {
- data.team = scope.team;
- data.user = "";
- }
- else {
- data.user = scope.user;
- data.team = "";
- }
- data['kind'] = scope['kind'].value;
+ // Reset all the field values related to Kind.
+ if (reset) {
+ scope.access_key = null;
+ scope.secret_key = null;
+ scope.api_key = null;
+ scope.username = null;
+ scope.password = null;
+ scope.password_confirm = null;
+ scope.ssh_key_data = null;
+ scope.ssh_key_unlock = null;
+ scope.ssh_key_unlock_confirm = null;
+ scope.sudo_username = null;
+ scope.sudo_password = null;
+ scope.sudo_password_confirm = null;
+ }
- switch (data['kind']) {
- case 'ssh':
- data['password'] = scope['ssh_password'];
- break;
+ // Collapse or open help widget based on whether scm value is selected
+ collapse = $('#credential_kind').parent().find('.panel-collapse').first();
+ id = collapse.attr('id');
+ if (!Empty(scope.kind) && scope.kind.value !== '') {
+ if ($('#' + id + '-icon').hasClass('icon-minus')) {
+ scope.accordionToggle('#' + id);
+ }
+ } else {
+ if ($('#' + id + '-icon').hasClass('icon-plus')) {
+ scope.accordionToggle('#' + id);
+ }
+ }
+
+ };
+ }
+])
+
+
+.factory('OwnerChange', [
+ function () {
+ return function (params) {
+ var scope = params.scope,
+ owner = scope.owner;
+ if (owner === 'team') {
+ scope.team_required = true;
+ scope.user_required = false;
+ scope.user = null;
+ scope.user_username = null;
+ } else {
+ scope.team_required = false;
+ scope.user_required = true;
+ scope.team = null;
+ scope.team_name = null;
+ }
+ };
+ }
+])
+
+
+.factory('FormSave', ['$location', 'Alert', 'Rest', 'ProcessErrors', 'Empty', 'GetBasePath', 'CredentialForm', 'ReturnToCaller', 'Wait',
+ function ($location, Alert, Rest, ProcessErrors, Empty, GetBasePath, CredentialForm, ReturnToCaller, Wait) {
+ return function (params) {
+ var scope = params.scope,
+ mode = params.mode,
+ form = CredentialForm,
+ data = {}, fld, url;
+
+ for (fld in form.fields) {
+ if (fld !== 'access_key' && fld !== 'secret_key' && fld !== 'ssh_username' &&
+ fld !== 'ssh_password') {
+ if (scope[fld] === null) {
+ data[fld] = "";
+ } else {
+ data[fld] = scope[fld];
+ }
+ }
+ }
+
+ if (!Empty(scope.team)) {
+ data.team = scope.team;
+ data.user = "";
+ } else {
+ data.user = scope.user;
+ data.team = "";
+ }
+
+ data.kind = scope.kind.value;
+
+ switch (data.kind) {
+ case 'ssh':
+ data.password = scope.ssh_password;
+ break;
case 'aws':
- data['username'] = scope['access_key'];
- data['password'] = scope['secret_key'];
+ data.username = scope.access_key;
+ data.password = scope.secret_key;
break;
case 'rax':
- data['password'] = scope['api_key'];
+ data.password = scope.api_key;
break;
- }
-
- if (Empty(data.team) && Empty(data.user)) {
- Alert('Missing User or Team', 'You must provide either a User or a Team. If this credential will only be accessed by a specific ' +
- 'user, select a User. To allow a team of users to access this credential, select a Team.', 'alert-danger');
- }
- else {
- Wait('start');
- if (mode == 'add') {
- var url = (!Empty(data.team)) ? GetBasePath('teams') + data.team + '/credentials/' :
- GetBasePath('users') + data.user + '/credentials/';
- Rest.setUrl(url);
- Rest.post(data)
- .success( function(data, status, headers, config) {
- Wait('stop');
- var base = $location.path().replace(/^\//,'').split('/')[0];
- (base == 'credentials') ? ReturnToCaller() : ReturnToCaller(1);
- })
- .error( function(data, status, headers, config) {
- Wait('stop');
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to create new Credential. POST status: ' + status });
- });
}
- else {
- var url = GetBasePath('credentials') + scope.id + '/';
- Rest.setUrl(url);
- Rest.put(data)
- .success( function(data, status, headers, config) {
- Wait('stop');
- var base = $location.path().replace(/^\//,'').split('/')[0];
- (base == 'credentials') ? ReturnToCaller() : ReturnToCaller(1);
- })
- .error( function(data, status, headers, config) {
- Wait('stop');
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to update Credential. PUT status: ' + status });
- });
- }
- }
- }
- }]);
+ if (Empty(data.team) && Empty(data.user)) {
+ Alert('Missing User or Team', 'You must provide either a User or a Team. If this credential will only be accessed by a specific ' +
+ 'user, select a User. To allow a team of users to access this credential, select a Team.', 'alert-danger');
+ } else {
+ Wait('start');
+ if (mode === 'add') {
+ url = (!Empty(data.team)) ? GetBasePath('teams') + data.team + '/credentials/' :
+ GetBasePath('users') + data.user + '/credentials/';
+ Rest.setUrl(url);
+ Rest.post(data)
+ .success(function () {
+ Wait('stop');
+ var base = $location.path().replace(/^\//, '').split('/')[0];
+ if (base === 'credentials') {
+ ReturnToCaller();
+ }
+ ReturnToCaller(1);
+ })
+ .error(function (data, status) {
+ Wait('stop');
+ ProcessErrors(scope, data, status, form, {
+ hdr: 'Error!',
+ msg: 'Failed to create new Credential. POST status: ' + status
+ });
+ });
+ } else {
+ url = GetBasePath('credentials') + scope.id + '/';
+ Rest.setUrl(url);
+ Rest.put(data)
+ .success(function () {
+ Wait('stop');
+ var base = $location.path().replace(/^\//, '').split('/')[0];
+ if (base === 'credentials') {
+ ReturnToCaller();
+ }
+ ReturnToCaller(1);
+ })
+ .error(function (data, status) {
+ Wait('stop');
+ ProcessErrors(scope, data, status, form, {
+ hdr: 'Error!',
+ msg: 'Failed to update Credential. PUT status: ' + status
+ });
+ });
+ }
+ }
+ };
+ }
+]);
\ No newline at end of file
diff --git a/awx/ui/static/js/helpers/Events.js b/awx/ui/static/js/helpers/Events.js
index 7c554794a0..263b982b1d 100644
--- a/awx/ui/static/js/helpers/Events.js
+++ b/awx/ui/static/js/helpers/Events.js
@@ -6,194 +6,57 @@
* EventView - show the job_events form in a modal dialog
*
*/
-angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefinition'])
-.factory('EventView', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm',
- 'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'JobEventDataForm', 'Empty',
- function($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath,
- FormatDate, JobEventDataForm, Empty) {
- return function(params) {
-
- // We're going to manipulate the form object each time the user clicks on View button. We can't rely on what's
- // left of the form in memory each time. Instead we have to define the form from scratch, so for now we're
- // keeping it here inline rather than a separate file.
- //
- // Form manipulation is done to remove any empty values. In order for a section (or accordion) to not be drawn,
- // it needs to be removed prior to call jqueryui. Otherwise, attempting to hide accordion pieces after the
- // the accordion is rendered creates undesired behavior.
- var form = {
- name: 'job_events',
- well: false,
- forceListeners: true,
- fields: {
- status: {
- labelClass: 'job-\{\{ status \}\}',
- type: 'custom',
- section: 'Event',
- control: ' \{\{ status \}\}
'
- },
- id: {
- label: 'ID',
- type: 'text',
- readonly: true,
- section: 'Event',
- 'class': 'span1'
- },
- created: {
- label: 'Created On',
- type: 'text',
- section: 'Event',
- readonly: true
- },
- host: {
- label: 'Host',
- type: 'text',
- readonly: true,
- section: 'Event',
- ngShow: "host !== ''"
- },
- play: {
- label: 'Play',
- type: 'text',
- readonly: true,
- section: 'Event',
- ngShow: "play !== ''"
- },
- task: {
- label: 'Task',
- type: 'text',
- readonly: true,
- section: 'Event',
- ngShow: "task !== ''"
- },
- rc: {
- label: 'Return Code',
- type: 'text',
- readonly: true,
- section: 'Results',
- 'class': 'span1',
- ngShow: "rc !== ''"
- },
- msg: {
- label: 'Msg',
- type: 'textarea',
- readonly: true,
- section: 'Results',
- 'class': 'nowrap',
- ngShow: "msg !== ''",
- rows: 10
- },
- stdout: {
- label: 'Std Out',
- type: 'textarea',
- readonly: true,
- section: 'Results',
- 'class': 'nowrap',
- ngShow: "stdout !== ''",
- rows: 10
- },
- stderr: {
- label: 'Std Err',
- type: 'textarea',
- readonly: true,
- section: 'Results',
- 'class': 'nowrap',
- ngShow: "stderr !== ''",
- rows: 10
- },
- results: {
- label: 'Results',
- type: 'textarea',
- section: 'Results',
- readonly: true,
- 'class': 'nowrap',
- ngShow: "results !== ''",
- rows: 10
- },
- start: {
- label: 'Start',
- type: 'text',
- readonly: true,
- section: 'Timing',
- ngShow: "start !== ''"
- },
- traceback: {
- label: false,
- type: 'textarea',
- readonly: true,
- section: 'Traceback',
- 'class': 'nowrap',
- ngShow: "traceback !== ''",
- rows: 10
- },
- end: {
- label: 'End',
- type: 'text',
- readonly: true,
- section: 'Timing',
- ngShow: "end !== ''"
- },
- delta: {
- label: 'Elapsed',
- type: 'text',
- readonly: true,
- section: 'Timing',
- ngShow: "delta !== ''"
- },
- module_name: {
- label: 'Name',
- type: 'text',
- readonly: true,
- section: 'Module',
- ngShow: "module_name !== ''"
- },
- module_args: {
- label: 'Args',
- type: 'text',
- readonly: true,
- section: 'Module',
- ngShow: "module_args !== ''"
- }
- }
- };
+
+'use strict';
- var event_id = params.event_id;
- var generator = GenerateForm;
- var scope;
- var defaultUrl = GetBasePath('base') + 'job_events/' + event_id + '/';
-
- // Retrieve detail record and prepopulate the form
- Rest.setUrl(defaultUrl);
- Rest.get()
- .success( function(data, status, headers, config) {
-
- // If event_data is not available, remove fields that depend on it
- if ($.isEmptyObject(data['event_data']) || !data['event_data']['res'] || typeof data['event_data']['res'] == 'string') {
- for (var fld in form.fields) {
- switch(fld) {
- case 'start':
- case 'end':
- case 'delta':
- case 'msg':
- case 'stdout':
- case 'stderr':
- case 'msg':
- case 'results':
- case 'module_name':
- case 'module_args':
- case 'rc':
- delete form.fields[fld];
- break;
- }
- }
- }
-
- if ($.isEmptyObject(data['event_data']) || !data['event_data']['res'] || typeof data['event_data']['res'] != 'string') {
- delete form.fields['traceback'];
- }
-
- // Remove remaining form fields that do not have a corresponding data value
- for (var fld in form.fields) {
- switch (fld) {
+angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefinition', 'JobEventsFormDefinition'])
+
+ .factory('EventView', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm',
+ 'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'JobEventDataForm', 'Empty', 'JobEventsForm',
+ function ($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath,
+ FormatDate, JobEventDataForm, Empty, JobEventsForm) {
+ return function (params) {
+
+ var event_id = params.event_id,
+ generator = GenerateForm,
+ form = angular.copy(JobEventsForm),
+ scope,
+ defaultUrl = GetBasePath('base') + 'job_events/' + event_id + '/';
+
+ // Retrieve detail record and prepopulate the form
+ Rest.setUrl(defaultUrl);
+ Rest.get()
+ .success(function (data) {
+ var i, n, fld, rows, txt, cDate;
+
+ // If event_data is not available, remove fields that depend on it
+ if ($.isEmptyObject(data.event_data) || !data.event_data.res || typeof data.event_data.res === 'string') {
+ for (fld in form.fields) {
+ switch (fld) {
+ case 'start':
+ case 'end':
+ case 'delta':
+ case 'msg':
+ case 'stdout':
+ case 'stderr':
+ case 'msg':
+ case 'results':
+ case 'module_name':
+ case 'module_args':
+ case 'rc':
+ delete form.fields[fld];
+ break;
+ }
+ }
+ }
+
+ if ($.isEmptyObject(data.event_data) || !data.event_data.res || typeof data.event_data.res !== 'string') {
+ delete form.fields.traceback;
+ }
+
+ // Remove remaining form fields that do not have a corresponding data value
+ for (fld in form.fields) {
+ switch (fld) {
case 'start':
case 'end':
case 'delta':
@@ -202,114 +65,118 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
case 'stderr':
case 'msg':
case 'rc':
- if (data['event_data'] && data['event_data']['res'] && Empty(data['event_data']['res'][fld])) {
- delete form.fields[fld];
- }
- else {
- if (form.fields[fld].type == 'textarea') {
- var n = data['event_data']['res'][fld].match(/\n/g);
- var rows = (n) ? n.length : 1;
- rows = (rows > 10) ? 10 : rows;
- rows = (rows < 3) ? 3 : rows;
- form.fields[fld].rows = rows;
- }
+ if (data.event_data && data.event_data.res && Empty(data.event_data.res[fld])) {
+ delete form.fields[fld];
+ } else {
+ if (form.fields[fld].type === 'textarea') {
+ n = data.event_data.res[fld].match(/\n/g);
+ rows = (n) ? n.length : 1;
+ rows = (rows > 10) ? 10 : rows;
+ rows = (rows < 3) ? 3 : rows;
+ form.fields[fld].rows = rows;
+ }
}
break;
case 'results':
- if ( data['event_data'] && data['event_data']['res'] && data['event_data']['res'][fld] == undefined) {
- // not defined
- delete form.fields[fld];
- }
- else if (!Array.isArray(data['event_data']['res'][fld]) || data['event_data']['res'][fld].length == 0) {
- // defined, but empty
- delete form.fields[fld];
- }
- else {
- // defined and not empty, so attempt to size the textarea field
- var txt = '';
- for (var i=0; i < data['event_data']['res'][fld].length; i++) {
- txt += data['event_data']['res'][fld][i];
- }
- if (txt == '') {
- // there's an array, but the actual text is empty
- delete form.fields[fld];
- }
- else {
- var n = txt.match(/\n/g);
- var rows = (n) ? n.length : 1;
- rows = (rows > 10) ? 10 : rows;
- rows = (rows < 3) ? 3 : rows;
- form.fields[fld].rows = rows;
- }
+ if (data.event_data && data.event_data.res && data.event_data.res[fld] === undefined) {
+ // not defined
+ delete form.fields[fld];
+ } else if (!Array.isArray(data.event_data.res[fld]) || data.event_data.res[fld].length === 0) {
+ // defined, but empty
+ delete form.fields[fld];
+ } else {
+ // defined and not empty, so attempt to size the textarea field
+ txt = '';
+ for (i = 0; i < data.event_data.res[fld].length; i++) {
+ txt += data.event_data.res[fld][i];
+ }
+ if (txt === '') {
+ // there's an array, but the actual text is empty
+ delete form.fields[fld];
+ } else {
+ n = txt.match(/\n/g);
+ rows = (n) ? n.length : 1;
+ rows = (rows > 10) ? 10 : rows;
+ rows = (rows < 3) ? 3 : rows;
+ form.fields[fld].rows = rows;
+ }
}
break;
case 'module_name':
case 'module_args':
- if (data['event_data'] && data['event_data']['res']) {
- if (data['event_data']['res']['invocation'] === undefined ||
- data['event_data']['res']['invocation'][fld] === undefined) {
+ if (data.event_data && data.event_data.res) {
+ if (data.event_data.res.invocation === undefined ||
+ data.event_data.res.invocation[fld] === undefined) {
delete form.fields[fld];
}
}
break;
- }
- }
-
- // load the form
- scope = generator.inject(form, { mode: 'edit', modal: true, related: false});
- generator.reset();
- scope.formModalAction = function() {
- $('#form-modal').modal("hide");
- }
- scope.formModalActionLabel = 'OK';
- scope.formModalCancelShow = false;
- scope.formModalInfo = 'View JSON';
- $('#form-modal .btn-success').removeClass('btn-success').addClass('btn-none');
- $('#form-modal').addClass('skinny-modal');
- scope.formModalHeader = data['event_display'].replace(/^\u00a0*/g,'');
-
- // Respond to View JSON button
- scope.formModalInfoAction = function() {
- var generator = GenerateForm;
- var scope = generator.inject(JobEventDataForm, { mode: 'edit', modal: true, related: false,
- modal_selector: '#form-modal2', modal_body_id: 'form-modal2-body', modal_title_id: 'formModal2Header' });
- generator.reset();
- scope.formModal2Header = data['event_display'].replace(/^\u00a0*/g,'');
- scope.event_data = JSON.stringify(data['event_data'], null, '\t');
- scope.formModal2ActionLabel = 'OK';
- scope.formModal2CancelShow = false;
- scope.formModal2Info = false;
- scope.formModalInfo = 'View JSON';
- scope.formModal2Action = function() {
- $('#form-modal2').modal("hide");
}
- $('#form-modal2 .btn-success').removeClass('btn-success').addClass('btn-none');
}
- if (typeof data['event_data']['res'] == 'string') {
- scope['traceback'] = data['event_data']['res'];
- }
-
- for (var fld in form.fields) {
- switch(fld) {
+ // load the form
+ scope = generator.inject(form, {
+ mode: 'edit',
+ modal: true,
+ related: false
+ });
+ generator.reset();
+ scope.formModalAction = function () {
+ $('#form-modal').modal("hide");
+ };
+ scope.formModalActionLabel = 'OK';
+ scope.formModalCancelShow = false;
+ scope.formModalInfo = 'View JSON';
+ $('#form-modal .btn-success').removeClass('btn-success').addClass('btn-none');
+ $('#form-modal').addClass('skinny-modal');
+ scope.formModalHeader = data.event_display.replace(/^\u00a0*/g, '');
+
+ // Respond to View JSON button
+ scope.formModalInfoAction = function () {
+ var generator = GenerateForm,
+ scope = generator.inject(JobEventDataForm, {
+ mode: 'edit',
+ modal: true,
+ related: false,
+ modal_selector: '#form-modal2',
+ modal_body_id: 'form-modal2-body',
+ modal_title_id: 'formModal2Header'
+ });
+ generator.reset();
+ scope.formModal2Header = data.event_display.replace(/^\u00a0*/g, '');
+ scope.event_data = JSON.stringify(data.event_data, null, '\t');
+ scope.formModal2ActionLabel = 'OK';
+ scope.formModal2CancelShow = false;
+ scope.formModal2Info = false;
+ scope.formModalInfo = 'View JSON';
+ scope.formModal2Action = function () {
+ $('#form-modal2').modal("hide");
+ };
+ $('#form-modal2 .btn-success').removeClass('btn-success').addClass('btn-none');
+ };
+
+ if (typeof data.event_data.res === 'string') {
+ scope.traceback = data.event_data.res;
+ }
+
+ 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';
+ 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);
+ 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'];
+ if (data.summary_fields && data.summary_fields.host) {
+ scope.host = data.summary_fields.host.name;
}
break;
case 'id':
@@ -319,50 +186,50 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
break;
case 'start':
case 'end':
- if (data['event_data'] && data['event_data']['res'] && !Empty(data['event_data']['res'][fld])) {
- scope[fld] = data['event_data']['res'][fld];
+ if (data.event_data && data.event_data.res && !Empty(data.event_data.res[fld])) {
+ scope[fld] = data.event_data.res[fld];
}
break;
- case 'results':
- if (Array.isArray(data['event_data']['res'][fld]) && data['event_data']['res'][fld].length > 0 ) {
- var txt = '';
- for (var i=0; i < data['event_data']['res'][fld].length; i++) {
- txt += data['event_data']['res'][fld][i];
- }
- if (txt !== '') {
- scope[fld] = txt;
- }
+ case 'results':
+ if (Array.isArray(data.event_data.res[fld]) && data.event_data.res[fld].length > 0) {
+ txt = '';
+ for (i = 0; i < data.event_data.res[fld].length; i++) {
+ txt += data.event_data.res[fld][i];
+ }
+ if (txt !== '') {
+ scope[fld] = txt;
+ }
}
- break;
+ 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 (data.event_data && data.event_data.res && data.event_data.res[fld] !== undefined) {
+ scope[fld] = data.event_data.res[fld];
}
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];
+ if (data.event_data.res && data.event_data.res.invocation) {
+ scope[fld] = data.event_data.res.invocation[fld];
}
break;
+ }
+ }
+
+ if (!scope.$$phase) {
+ scope.$digest();
}
- }
-
- if (!scope.$$phase) {
- scope.$digest();
- }
})
- .error( function(data, status, headers, config) {
- $('#form-modal').modal("hide");
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to retrieve event: ' + event_id + '. GET status: ' + status });
+ .error(function (data, status) {
+ $('#form-modal').modal("hide");
+ ProcessErrors(scope, data, status, form, { hdr: 'Error!',
+ msg: 'Failed to retrieve event: ' + event_id + '. GET status: ' + status });
});
-
- }
- }]);
\ No newline at end of file
+ };
+ }
+ ]);
\ No newline at end of file
diff --git a/awx/ui/static/js/helpers/Groups.js b/awx/ui/static/js/helpers/Groups.js
index 559668efb3..fff2f946c8 100644
--- a/awx/ui/static/js/helpers/Groups.js
+++ b/awx/ui/static/js/helpers/Groups.js
@@ -4,19 +4,19 @@
* GroupsHelper
*
* Routines that handle group add/edit/delete on the Inventory tree widget.
- *
+ *
*/
-
+
'use strict';
-angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'GroupListDefinition',
- 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'AuthService', 'GroupsHelper',
- 'InventoryHelper', 'SelectionHelper', 'JobSubmissionHelper', 'RefreshHelper',
- 'PromptDialog', 'CredentialsListDefinition','InventoryTree'
- ])
+angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'GroupListDefinition', 'SearchHelper',
+ 'PaginationHelpers', 'ListGenerator', 'AuthService', 'GroupsHelper', 'InventoryHelper', 'SelectionHelper',
+ 'JobSubmissionHelper', 'RefreshHelper', 'PromptDialog', 'CredentialsListDefinition', 'InventoryTree'
+])
- .factory('GetSourceTypeOptions', [ 'Rest', 'ProcessErrors', 'GetBasePath', function(Rest, ProcessErrors, GetBasePath) {
- return function(params) {
+.factory('GetSourceTypeOptions', ['Rest', 'ProcessErrors', 'GetBasePath',
+ function (Rest, ProcessErrors, GetBasePath) {
+ return function (params) {
// Lookup options for source and build an array of drop-down choices
var scope = params.scope,
variable = params.variable;
@@ -24,161 +24,124 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
scope[variable] = [];
Rest.setUrl(GetBasePath('inventory_sources'));
Rest.options()
- .success( function(data) {
+ .success(function (data) {
var i, choices = data.actions.GET.source.choices;
- for (i=0; i < choices.length; i++) {
+ for (i = 0; i < choices.length; i++) {
if (choices[i][0] !== 'file') {
scope[variable].push({
- label: ( (choices[i][0] === '') ? 'Manual' : choices[i][1] ),
+ label: ((choices[i][0] === '') ? 'Manual' : choices[i][1]),
value: choices[i][0]
});
}
}
})
- .error( function(data, status) {
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Failed to retrieve options for inventory_sources.source. OPTIONS status: ' + status });
+ .error(function (data, status) {
+ ProcessErrors(scope, data, status, null, {
+ hdr: 'Error!',
+ msg: 'Failed to retrieve options for inventory_sources.source. OPTIONS status: ' + status
+ });
});
}
};
- }])
+ }
+])
- .factory('GetUpdateIntervalOptions', [ function() {
- return function() {
- return [
- { label: 'none', value: 0 },
- { label: '5 minutes', value: 5 },
- { label: '10 minutes', value: 10 },
- { label: '15 minutes', value: 15 },
- { label: '30 minutes', value: 30 },
- { label: '45 minutes', value: 45 },
- { label: '1 hour', value: 60 },
- { label: '2 hours', value: 120 },
- { label: '3 hours', value: 180 },
- { label: '4 hours', value: 240 },
- { label: '5 hours', value: 300 },
- { label: '6 hours', value: 360 },
- { label: '7 hours', value: 420 },
- { label: '8 hours', value: 480 },
- { label: '9 hours', value: 540 },
- { label: '10 hours', value: 600 },
- { label: '11 hours', value: 660 },
- { label: '12 hours', value: 720 },
- { label: '13 hours', value: 780 },
- { label: '14 hours', value: 840 },
- { label: '15 hours', value: 900 },
- { label: '16 hours', value: 960 },
- { label: '17 hours', value: 1020 },
- { label: '18 hours', value: 1080 },
- { label: '19 hours', value: 1140},
- { label: '20 hours', value: 1200 },
- { label: '21 hours', value: 1260 },
- { label: '22 hours', value: 1320 },
- { label: '23 hours', value: 1380 },
- { label: '24 hours', value: 1440 },
- { label: '48 hours', value: 1880 },
- { label: '72 hours', value: 4320 },
- { label: 'weekly (every 7 days)', value: 10080 },
- { label: 'monthly (every 30 days)', value: 43200 }
- ];
+.factory('ViewUpdateStatus', ['Rest', 'ProcessErrors', 'GetBasePath', 'ShowUpdateStatus', 'Alert', 'Wait', 'Empty', 'Find',
+ function (Rest, ProcessErrors, GetBasePath, ShowUpdateStatus, Alert, Wait, Empty, Find) {
+ return function (params) {
+
+ var scope = params.scope,
+ tree_id = params.tree_id,
+ group_id = params.group_id,
+ group = Find({ list: scope.groups, key: 'id', val: tree_id });
+
+ if (group) {
+ if (Empty(group.source)) {
+ Alert('Missing Configuration', 'The selected group is not configured for inventory sync. ' +
+ 'You must first edit the group, provide Source settings, and then run the sync process.', 'alert-info');
+ } else if (Empty(group.status) || group.status === "never updated") {
+ Alert('No Status Available', 'An inventory sync has not been performed for the selected group. Start the process by ' +
+ 'clicking the button.', 'alert-info');
+ } else {
+ Wait('start');
+ Rest.setUrl(group.related.inventory_source);
+ Rest.get()
+ .success(function (data) {
+ var url = (data.related.current_update) ? data.related.current_update : data.related.last_update;
+ ShowUpdateStatus({
+ group_name: data.summary_fields.group.name,
+ last_update: url,
+ license_error: ((data.summary_fields.last_update && data.summary_fields.last_update.license_error) ? true : false),
+ tree_id: tree_id,
+ group_id: group_id,
+ parent_scope: scope
+ });
+ })
+ .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
+ });
+ });
+ }
+ }
+
};
- }])
-
- .factory('ViewUpdateStatus', [ 'Rest', 'ProcessErrors', 'GetBasePath', 'ShowUpdateStatus', 'Alert', 'Wait', 'Empty', 'Find',
- function(Rest, ProcessErrors, GetBasePath, ShowUpdateStatus, Alert, Wait, Empty, Find) {
- return function(params) {
-
- var scope = params.scope;
- var tree_id = params.tree_id;
- var group_id = params.group_id;
- var found = false;
- var group = Find({ list: scope.groups, key: 'id', val: tree_id });
-
- if (group) {
- if (Empty(group.source)) {
- Alert('Missing Configuration', 'The selected group is not configured for inventory sync. ' +
- 'You must first edit the group, provide Source settings, and then run the sync process.', 'alert-info');
- }
- else if (Empty(group.status) || group.status == "never updated") {
- Alert('No Status Available', 'An inventory sync has not been performed for the selected group. Start the process by ' +
- 'clicking the button.', 'alert-info');
- }
- else {
- Wait('start');
- Rest.setUrl(group.related.inventory_source);
- Rest.get()
- .success( function(data, status, headers, config) {
- var url = (data.related.current_update) ? data.related.current_update : data.related.last_update;
- ShowUpdateStatus({
- group_name: data.summary_fields.group.name,
- last_update: url,
- license_error: ( (data.summary_fields.last_update && data.summary_fields.last_update.license_error) ? true : false ),
- tree_id: tree_id,
- group_id: group_id,
- parent_scope: scope
- });
- })
- .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 });
- });
- }
- }
+ }
+])
- }
- }])
-
- .factory('GetHostsStatusMsg', [ function() {
- return function(params) {
-
- var active_failures = params.active_failures;
- var total_hosts = params.total_hosts;
- var inventory_id = params.inventory_id;
- var group_id = params.group_id;
+.factory('GetHostsStatusMsg', [
+ function () {
+ return function (params) {
- var tip, failures, html_class;
+ var active_failures = params.active_failures,
+ total_hosts = params.total_hosts,
+ tip, failures, html_class;
- // Return values for use on host status indicator
-
- if (active_failures > 0) {
- tip = total_hosts + ( (total_hosts == 1) ? ' host' : ' hosts' ) + '. ' + active_failures + ' with failed jobs.';
- html_class = 'true';
- failures = true;
- }
- else {
- failures = false;
- if (total_hosts == 0) {
- // no hosts
- tip = "Group contains 0 hosts.";
- html_class = 'na';
- }
- else {
- // many hosts with 0 failures
- tip = total_hosts + ( (total_hosts == 1) ? ' host' : ' hosts' ) + '. No job failures';
- html_class = 'false';
- }
- }
+ // Return values for use on host status indicator
- return { tooltip: tip, failures: failures, 'class': html_class };
-
- }
- }])
+ if (active_failures > 0) {
+ tip = total_hosts + ((total_hosts === 1) ? ' host' : ' hosts') + '. ' + active_failures + ' with failed jobs.';
+ html_class = 'true';
+ failures = true;
+ } else {
+ failures = false;
+ if (total_hosts === 0) {
+ // no hosts
+ tip = "Group contains 0 hosts.";
+ html_class = 'na';
+ } else {
+ // many hosts with 0 failures
+ tip = total_hosts + ((total_hosts === 1) ? ' host' : ' hosts') + '. No job failures';
+ html_class = 'false';
+ }
+ }
- .factory('GetSyncStatusMsg', [ function() {
- return function(params) {
-
- var status = params.status;
+ return {
+ tooltip: tip,
+ failures: failures,
+ 'class': html_class
+ };
+ };
+ }
+])
- var launch_class = '';
- var launch_tip = 'Start sync process';
- var stat, stat_class, status_tip;
- stat = status;
- stat_class = 'icon-cloud-' + stat;
-
- switch (status) {
+.factory('GetSyncStatusMsg', [
+ function () {
+ return function (params) {
+
+ var status = params.status,
+ launch_class = '',
+ launch_tip = 'Start sync process',
+ stat, stat_class, status_tip;
+
+ stat = status;
+ stat_class = 'icon-cloud-' + stat;
+
+ switch (status) {
case 'never updated':
stat = 'never';
stat_class = 'icon-cloud-na disabled';
@@ -186,7 +149,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
break;
case 'none':
case '':
- launch_class = 'btn-disabled',
+ launch_class = 'btn-disabled';
stat = 'n/a';
stat_class = 'icon-cloud-na disabled';
status_tip = 'Cloud source not configured. Click to update.';
@@ -197,1019 +160,1017 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
break;
case 'successful':
status_tip = 'Sync completed. Click to view log.';
- break;
+ break;
case 'updating':
status_tip = 'Sync running';
break;
}
- return {
- 'class': stat_class,
- tooltip: status_tip,
- status: stat,
- 'launch_class': launch_class,
- 'launch_tip': launch_tip
- }
+ return {
+ 'class': stat_class,
+ tooltip: status_tip,
+ status: stat,
+ 'launch_class': launch_class,
+ 'launch_tip': launch_tip
+ };
+ };
+ }
+])
- }
- }])
+.factory('SourceChange', ['GetBasePath', 'CredentialList', 'LookUpInit', 'Empty',
+ function (GetBasePath, CredentialList, LookUpInit, Empty) {
+ return function (params) {
- .factory('SourceChange', [ 'GetBasePath', 'CredentialList', 'LookUpInit', 'Empty',
- function(GetBasePath, CredentialList, LookUpInit, Empty){
- return function(params) {
-
- var scope = params.scope;
- var form = params.form;
-
- if (!Empty(scope['source'])) {
- if (scope['source'].value == 'file') {
- scope.sourcePathRequired = true;
- }
- else {
- scope.sourcePathRequired = false;
- // reset fields
- scope.source_path = '';
- scope[form.name + '_form']['source_path'].$setValidity('required',true);
- }
- if (scope['source'].value == 'rax') {
- scope['source_region_choices'] = scope['rax_regions'];
- //$('#s2id_group_source_regions').select2('data', []);
- $('#s2id_group_source_regions').select2('data', [{ id: 'all', text: 'All' }]);
- }
- else if (scope['source'].value == 'ec2') {
- scope['source_region_choices'] = scope['ec2_regions'];
- //$('#s2id_group_source_regions').select2('data', []);
- $('#s2id_group_source_regions').select2('data', [{ id: 'all', text: 'All' }]);
- }
- if (scope['source'].value == 'rax' || scope['source'].value == 'ec2') {
- var kind = (scope.source.value == 'rax') ? 'rax' : 'aws';
- var url = GetBasePath('credentials') + '?cloud=true&kind=' + kind;
- LookUpInit({
- url: url,
- scope: scope,
- form: form,
- list: CredentialList,
- field: 'credential'
+ var scope = params.scope,
+ form = params.form,
+ kind, url;
+
+ if (!Empty(scope.source)) {
+ if (scope.source.value === 'file') {
+ scope.sourcePathRequired = true;
+ } else {
+ scope.sourcePathRequired = false;
+ // reset fields
+ scope.source_path = '';
+ scope[form.name + '_form'].source_path.$setValidity('required', true);
+ }
+ if (scope.source.value === 'rax') {
+ scope.source_region_choices = scope.rax_regions;
+ //$('#s2id_group_source_regions').select2('data', []);
+ $('#s2id_group_source_regions').select2('data', [{
+ id: 'all',
+ text: 'All'
+ }]);
+ } else if (scope.source.value === 'ec2') {
+ scope.source_region_choices = scope.ec2_regions;
+ //$('#s2id_group_source_regions').select2('data', []);
+ $('#s2id_group_source_regions').select2('data', [{
+ id: 'all',
+ text: 'All'
+ }]);
+ }
+ if (scope.source.value === 'rax' || scope.source.value === 'ec2') {
+ kind = (scope.source.value === 'rax') ? 'rax' : 'aws';
+ url = GetBasePath('credentials') + '?cloud=true&kind=' + kind;
+ LookUpInit({
+ url: url,
+ scope: scope,
+ form: form,
+ list: CredentialList,
+ field: 'credential'
});
+ }
}
- }
-
- }
- }])
+ };
+ }
+])
-
- // Cancel a pending or running inventory sync
- .factory('GroupsCancelUpdate', ['Rest', 'ProcessErrors', 'Alert', 'Wait', 'Find',
- function(Rest, ProcessErrors, Alert, Wait, Find) {
- return function(params) {
-
- var scope = params.scope;
- var id = params.tree_id;
- if (scope.removeCancelUpdate) {
- scope.removeCancelUpdate();
- }
- scope.removeCancelUpdate = scope.$on('CancelUpdate', function(e, url) {
- // Cancel the update process
- Rest.setUrl(url)
- Rest.post()
- .success( function(data, status, headers, config) {
- Wait('stop');
- Alert('Inventory Sync Cancelled', 'Your request to cancel the sync process was submitted to the task manger. ' +
- 'Click the button to monitor the status.', 'alert-info');
- })
- .error( function(data, status, headers, config) {
- Wait('stop');
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST status: ' + status });
- });
- });
+// Cancel a pending or running inventory sync
+.factory('GroupsCancelUpdate', ['Rest', 'ProcessErrors', 'Alert', 'Wait', 'Find',
+ function (Rest, ProcessErrors, Alert, Wait, Find) {
+ return function (params) {
- if (scope.removeCheckCancel) {
- scope.removeCheckCancel();
- }
- scope.removeCheckCancel = scope.$on('CheckCancel', function(e, last_update, current_update) {
- // Check that we have access to cancelling an update
- var url = (current_update) ? current_update : last_update;
- url += 'cancel/';
- Rest.setUrl(url);
- Rest.get()
- .success( function(data, status, headers, config) {
- if (data.can_cancel) {
- scope.$emit('CancelUpdate', url);
- }
- else {
+ var scope = params.scope,
+ id = params.tree_id,
+ group;
+
+ if (scope.removeCancelUpdate) {
+ scope.removeCancelUpdate();
+ }
+ scope.removeCancelUpdate = scope.$on('CancelUpdate', function (e, url) {
+ // Cancel the update process
+ Rest.setUrl(url);
+ Rest.post()
+ .success(function () {
Wait('stop');
- Alert('Cancel Inventory Sync', 'Either you do not have access or the sync process completed. ' +
- 'Click the button to view the latest status.', 'alert-info');
- }
+ Alert('Inventory Sync Cancelled', 'Your request to cancel the sync process was submitted to the task manger. ' +
+ 'Click the button to monitor the status.', 'alert-info');
})
- .error( function(data, status, headers, config) {
- Wait('stop');
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Call to ' + url + ' failed. GET status: ' + status });
+ .error(function (data, status) {
+ Wait('stop');
+ ProcessErrors(scope, data, status, null, {
+ hdr: 'Error!',
+ msg: 'Call to ' + url + ' failed. POST status: ' + status
+ });
});
});
- // Cancel the update process
- var group = Find({ list: scope.groups, key: 'id', val: id });
- scope.selected_tree_id = group.id;
- scope.selected_group_id = group.group_id;
-
- if (group && (group.status == 'updating' || group.status == 'pending')) {
- // We found the group, and there is a running update
- Wait('start');
- Rest.setUrl(group.related.inventory_source);
- Rest.get()
- .success( function(data, status, headers, config) {
- scope.$emit('CheckCancel', data.related.last_update, data.related.current_update);
+ if (scope.removeCheckCancel) {
+ scope.removeCheckCancel();
+ }
+ scope.removeCheckCancel = scope.$on('CheckCancel', function (e, last_update, current_update) {
+ // Check that we have access to cancelling an update
+ var url = (current_update) ? current_update : last_update;
+ url += 'cancel/';
+ Rest.setUrl(url);
+ Rest.get()
+ .success(function (data) {
+ if (data.can_cancel) {
+ scope.$emit('CancelUpdate', url);
+ } else {
+ Wait('stop');
+ Alert('Cancel Inventory Sync', 'Either you do not have access or the sync process completed. ' +
+ 'Click the button to view the latest status.', 'alert-info');
+ }
})
- .error( function(data, status, headers, config) {
- Wait('stop');
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Call to ' + group.related.inventory_source + ' failed. GET status: ' + status });
+ .error(function (data, status) {
+ Wait('stop');
+ ProcessErrors(scope, data, status, null, {
+ hdr: 'Error!',
+ msg: 'Call to ' + url + ' failed. GET status: ' + status
+ });
});
- }
- else {
- Alert('Cancel Inventory Sync', 'The sync process completed. Click the to' +
- ' view the latest status.', 'alert-info');
- }
-
- }
- }])
+ });
- .factory('GroupsAdd', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
- 'Prompt', 'ProcessErrors', 'GetBasePath', 'ParseTypeChange', 'GroupsEdit', 'Wait', 'GetChoices',
- 'GetSourceTypeOptions', 'LookUpInit', 'BuildTree', 'SourceChange', 'WatchInventoryWindowResize',
- function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
+ // Cancel the update process
+ group = Find({ list: scope.groups, key: 'id', val: id });
+ scope.selected_tree_id = group.id;
+ scope.selected_group_id = group.group_id;
+
+ if (group && (group.status === 'updating' || group.status === 'pending')) {
+ // We found the group, and there is a running update
+ Wait('start');
+ Rest.setUrl(group.related.inventory_source);
+ Rest.get()
+ .success(function (data) {
+ scope.$emit('CheckCancel', data.related.last_update, data.related.current_update);
+ })
+ .error(function (data, status) {
+ Wait('stop');
+ ProcessErrors(scope, data, status, null, {
+ hdr: 'Error!',
+ msg: 'Call to ' + group.related.inventory_source + ' failed. GET status: ' + status
+ });
+ });
+ } else {
+ Alert('Cancel Inventory Sync', 'The sync process completed. Click the to' +
+ ' view the latest status.', 'alert-info');
+ }
+
+ };
+ }
+])
+
+.factory('GroupsAdd', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
+ 'Prompt', 'ProcessErrors', 'GetBasePath', 'ParseTypeChange', 'GroupsEdit', 'Wait', 'GetChoices',
+ 'GetSourceTypeOptions', 'LookUpInit', 'BuildTree', 'SourceChange', 'WatchInventoryWindowResize',
+ function ($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, ParseTypeChange, GroupsEdit, Wait, GetChoices, GetSourceTypeOptions, LookUpInit, BuildTree,
SourceChange, WatchInventoryWindowResize) {
- return function(params) {
+ return function (params) {
- var inventory_id = params.inventory_id;
- var group_id = (params.group_id !== undefined) ? params.group_id : null;
- var parent_scope = params.scope;
-
- // Inject dynamic view
- var defaultUrl = (group_id !== null) ? GetBasePath('groups') + group_id + '/children/' :
- GetBasePath('inventory') + inventory_id + '/groups/';
- var form = GroupForm;
- var generator = GenerateForm;
- var scope = generator.inject(form, { mode: 'add', modal: true, related: false, show_modal: false });
- var groupCreated = false;
+ var inventory_id = params.inventory_id,
+ group_id = (params.group_id !== undefined) ? params.group_id : null,
+ parent_scope = params.scope,
+ defaultUrl = (group_id !== null) ? GetBasePath('groups') + group_id + '/children/' :
+ GetBasePath('inventory') + inventory_id + '/groups/',
+ form = GroupForm,
+ generator = GenerateForm,
+ scope = generator.inject(form, { mode: 'add', modal: true, related: false, show_modal: false }),
+ choicesReady;
- $('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success');
+ $('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success');
- scope.formModalActionLabel = 'Save';
- scope.formModalCancelShow = true;
- scope.parseType = 'yaml';
- scope.source = null;
- ParseTypeChange(scope);
-
- generator.reset();
- var master={};
+ scope.formModalActionLabel = 'Save';
+ scope.formModalCancelShow = true;
+ scope.parseType = 'yaml';
+ scope.source = null;
+ ParseTypeChange(scope);
- if (scope.removeAddTreeRefreshed) {
- scope.removeAddTreeRefreshed();
- }
- scope.removeAddTreeRefreshed = scope.$on('GroupTreeRefreshed', function(e) {
- $rootScope.formModalHeader = null;
- $rootScope.formModalCancleShow= null;
- $rootScope.formModalActionLabel = null;
- Wait('stop');
- $('#form-modal').modal('hide');
- scope.removeAddTreeRefreshed();
+ generator.reset();
+
+ if (scope.removeAddTreeRefreshed) {
+ scope.removeAddTreeRefreshed();
+ }
+ scope.removeAddTreeRefreshed = scope.$on('GroupTreeRefreshed', function () {
+ $rootScope.formModalHeader = null;
+ $rootScope.formModalCancleShow = null;
+ $rootScope.formModalActionLabel = null;
+ Wait('stop');
+ $('#form-modal').modal('hide');
+ scope.removeAddTreeRefreshed();
});
- if (scope.removeSaveComplete) {
- scope.removeSaveComplete();
- }
- scope.removeSaveComplete = scope.$on('SaveComplete', function(e, group_id, error) {
- if (!error) {
+ if (scope.removeSaveComplete) {
+ scope.removeSaveComplete();
+ }
+ scope.removeSaveComplete = scope.$on('SaveComplete', function (e, group_id, error) {
+ if (!error) {
+ if (scope.searchCleanup) {
+ scope.searchCleanup();
+ }
+ scope.formModalActionDisabled = false;
+ BuildTree({
+ scope: parent_scope,
+ inventory_id: inventory_id,
+ refresh: true,
+ new_group_id: group_id
+ });
+ WatchInventoryWindowResize();
+ }
+ });
+
+ if (scope.removeFormSaveSuccess) {
+ scope.removeFormSaveSuccess();
+ }
+ scope.removeFormSaveSuccess = scope.$on('formSaveSuccess', function (e, group_id, url) {
+
+ // Source data gets stored separately from the group. Validate and store Source
+ // related fields, then call SaveComplete to wrap things up.
+
+ var parseError = false,
+ data = {},
+ regions, r, i,
+ json_data;
+
+ // Update the selector tree with new group name, descr
+ //SetNodeName({ scope: scope['selectedNode'], group_id: group_id,
+ // name: scope.name, description: scope.description });
+
+ if (scope.source.value !== null && scope.source.value !== '') {
+ data.group = group_id;
+ data.source = scope.source.value;
+ data.source_path = scope.source_path;
+ data.credential = scope.credential;
+ data.overwrite = scope.overwrite;
+ data.overwrite_vars = scope.overwrite_vars;
+ data.update_on_launch = scope.update_on_launch;
+
+ // Create a string out of selected list of regions
+ regions = $('#s2id_group_source_regions').select2("data");
+ r = [];
+ for (i = 0; i < regions.length; i++) {
+ r.push(regions[i].id);
+ }
+ data.source_regions = r.join();
+
+ if (scope.source.value === 'ec2') {
+ // for ec2, validate variable data
+ try {
+ if (scope.envParseType === 'json') {
+ json_data = JSON.parse(scope.source_vars); //make sure JSON parses
+ } else {
+ json_data = jsyaml.load(scope.source_vars); //parse yaml
+ }
+
+ // Make sure our JSON is actually an object
+ if (typeof json_data !== 'object') {
+ throw "failed to return an object!";
+ }
+
+ // Send JSON as a string
+ if ($.isEmptyObject(json_data)) {
+ data.source_vars = "";
+ } else {
+ data.source_vars = JSON.stringify(json_data, undefined, '\t');
+ }
+ } catch (err) {
+ parseError = true;
+ scope.$emit('SaveComplete', true);
+ Alert("Error", "Error parsing extra variables. Parser returned: " + err);
+ }
+ }
+
+ if (!parseError) {
+ Rest.setUrl(url);
+ Rest.put(data)
+ .success(function () {
+ scope.$emit('SaveComplete', group_id, false);
+ })
+ .error(function (data, status) {
+ scope.$emit('SaveComplete', group_id, true);
+ ProcessErrors(scope, data, status, form, {
+ hdr: 'Error!',
+ msg: 'Failed to update group inventory source. PUT status: ' + status
+ });
+ });
+ }
+ } else {
+ // No source value
+ scope.$emit('SaveComplete', group_id, false);
+ }
+ });
+
+ // Cancel
+ scope.cancelModal = function () {
if (scope.searchCleanup) {
scope.searchCleanup();
}
- scope.formModalActionDisabled = false;
- BuildTree({ scope: parent_scope, inventory_id: inventory_id, refresh: true, new_group_id: group_id });
WatchInventoryWindowResize();
- }
- });
+ };
- if (scope.removeFormSaveSuccess) {
- scope.removeFormSaveSuccess();
- }
- scope.removeFormSaveSuccess = scope.$on('formSaveSuccess', function(e, group_id, url) {
-
- // Source data gets stored separately from the group. Validate and store Source
- // related fields, then call SaveComplete to wrap things up.
+ // Save
+ scope.formModalAction = function () {
+ var json_data, data;
+ Wait('start');
+ try {
+ scope.formModalActionDisabled = true;
- var parseError = false;
- var saveError = false;
-
- // Update the selector tree with new group name, descr
- //SetNodeName({ scope: scope['selectedNode'], group_id: group_id,
- // name: scope.name, description: scope.description });
+ // 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
+ }
- if (scope.source.value !== null && scope.source.value !== '') {
- var data = {
- group: group_id,
- source: scope['source'].value,
- source_path: scope['source_path'],
- credential: scope['credential'],
- overwrite: scope['overwrite'],
- overwrite_vars: scope['overwrite_vars'],
- update_on_launch: scope['update_on_launch']
- //update_interval: scope['update_interval'].value
+ // Make sure our JSON is actually an object
+ if (typeof json_data !== 'object') {
+ throw "failed to return an object!";
+ }
+
+ data = {
+ name: scope.name,
+ description: scope.description
};
- // Create a string out of selected list of regions
- var regions = $('#s2id_group_source_regions').select2("data");
- var r = [];
- for (var i=0; i < regions.length; i++) {
- r.push(regions[i].id);
- }
- data['source_regions'] = r.join();
-
- if (scope['source'].value == 'ec2') {
- // for ec2, validate variable data
- try {
- if (scope.envParseType == 'json') {
- var json_data = JSON.parse(scope.source_vars); //make sure JSON parses
- }
- else {
- var json_data = jsyaml.load(scope.source_vars); //parse yaml
- }
-
- // Make sure our JSON is actually an object
- if (typeof json_data !== 'object') {
- throw "failed to return an object!";
- }
-
- // Send JSON as a string
- if ($.isEmptyObject(json_data)) {
- data.source_vars = "";
- }
- else {
- data.source_vars = JSON.stringify(json_data, undefined, '\t');
- }
+ if (inventory_id) {
+ data.inventory = inventory_id;
}
- catch(err) {
- parseError = true;
- scope.$emit('SaveComplete', true);
- Alert("Error", "Error parsing extra variables. Parser returned: " + err);
+
+ if ($.isEmptyObject(json_data)) {
+ data.variables = "";
+ } else {
+ data.variables = JSON.stringify(json_data, undefined, '\t');
}
- }
- if (!parseError) {
- Rest.setUrl(url)
- Rest.put(data)
- .success( function(data, status, headers, config) {
- scope.$emit('SaveComplete', group_id, false);
- })
- .error( function(data, status, headers, config) {
- scope.$emit('SaveComplete', group_id, true);
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to update group inventory source. PUT status: ' + status });
- });
- }
- }
- else {
- // No source value
- scope.$emit('SaveComplete', group_id, false);
- }
- });
-
- // Cancel
- scope.cancelModal = function() {
- if (scope.searchCleanup) {
- scope.searchCleanup();
- }
- WatchInventoryWindowResize();
- }
-
- // Save
- scope.formModalAction = function() {
- Wait('start');
- try {
- scope.formModalActionDisabled = true;
-
- // Make sure we have valid variable data
- if (scope.parseType == 'json') {
- var json_data = JSON.parse(scope.variables); //make sure JSON parses
- }
- 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!";
- }
-
- var data = {
- name: scope['name'],
- description: scope['description']
- };
-
- if (inventory_id) {
- data['inventory'] = inventory_id;
- }
-
- if ($.isEmptyObject(json_data)) {
- data['variables'] = "";
- }
- else {
- data['variables'] = JSON.stringify(json_data, undefined, '\t');
- }
-
- Rest.setUrl(defaultUrl);
- Rest.post(data)
- .success( function(data, status, headers, config) {
- scope.$emit('formSaveSuccess', data.id, GetBasePath('inventory_sources') + data.id + '/');
- })
- .error( function(data, status, headers, config) {
- Wait('stop');
- scope.formModalActionDisabled = false;
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to add new group. POST returned status: ' + status });
+ Rest.setUrl(defaultUrl);
+ Rest.post(data)
+ .success(function (data) {
+ scope.$emit('formSaveSuccess', data.id, GetBasePath('inventory_sources') + data.id + '/');
+ })
+ .error(function (data, status) {
+ Wait('stop');
+ scope.formModalActionDisabled = false;
+ ProcessErrors(scope, data, status, form, { hdr: 'Error!',
+ msg: 'Failed to add new group. POST returned status: ' + status });
});
- }
- catch(err) {
- Wait('stop');
- scope.formModalActionDisabled = false;
- Alert("Error", "Error parsing group variables. Parser returned: " + err);
- }
- }
+ } catch (err) {
+ Wait('stop');
+ scope.formModalActionDisabled = false;
+ Alert("Error", "Error parsing group variables. Parser returned: " + err);
+ }
+ };
- scope.sourceChange = function() {
- SourceChange({
- scope: scope,
- form: GroupForm
- });
- }
+ scope.sourceChange = function () {
+ SourceChange({ scope: scope, form: GroupForm });
+ };
- var choicesReady = 0;
+ choicesReady = 0;
- if (scope.removeChoicesReady) {
- scope.removeChoicesReady();
- }
- scope.removeChoicesReady = scope.$on('choicesReadyGroup', function() {
- choicesReady++;
- if (choicesReady == 2) {
- $('#form-modal').modal('show');
- Wait('stop');
+ if (scope.removeChoicesReady) {
+ scope.removeChoicesReady();
}
+ scope.removeChoicesReady = scope.$on('choicesReadyGroup', function () {
+ choicesReady++;
+ if (choicesReady === 2) {
+ $('#form-modal').modal('show');
+ Wait('stop');
+ }
});
- // Load options for source regions
- GetChoices({
- scope: scope,
- url: GetBasePath('inventory_sources'),
- field: 'source_regions',
- variable: 'rax_regions',
- choice_name: 'rax_region_choices',
- callback: 'choicesReadyGroup'
+ // Load options for source regions
+ GetChoices({
+ scope: scope,
+ url: GetBasePath('inventory_sources'),
+ field: 'source_regions',
+ variable: 'rax_regions',
+ choice_name: 'rax_region_choices',
+ callback: 'choicesReadyGroup'
});
- GetChoices({
- scope: scope,
- url: GetBasePath('inventory_sources'),
- field: 'source_regions',
- variable: 'ec2_regions',
- choice_name: 'ec2_region_choices',
- callback: 'choicesReadyGroup'
+ GetChoices({
+ scope: scope,
+ url: GetBasePath('inventory_sources'),
+ field: 'source_regions',
+ variable: 'ec2_regions',
+ choice_name: 'ec2_region_choices',
+ callback: 'choicesReadyGroup'
});
- GetSourceTypeOptions({ scope: scope, variable: 'source_type_options' });
-
- Wait('start');
+ GetSourceTypeOptions({
+ scope: scope,
+ variable: 'source_type_options'
+ });
- }
- }])
+ Wait('start');
- .factory('GroupsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
- 'Prompt', 'ProcessErrors', 'GetBasePath', 'SetNodeName', 'ParseTypeChange', 'GetSourceTypeOptions', 'InventoryUpdate',
- 'GetUpdateIntervalOptions', 'LookUpInit', 'Empty', 'Wait', 'GetChoices', 'UpdateGroup', 'SourceChange', 'Find',
- 'WatchInventoryWindowResize',
- function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
+ };
+ }
+])
+
+.factory('GroupsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
+ 'Prompt', 'ProcessErrors', 'GetBasePath', 'SetNodeName', 'ParseTypeChange', 'GetSourceTypeOptions', 'InventoryUpdate',
+ 'LookUpInit', 'Empty', 'Wait', 'GetChoices', 'UpdateGroup', 'SourceChange', 'Find','WatchInventoryWindowResize',
+ function ($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, SetNodeName, ParseTypeChange, GetSourceTypeOptions, InventoryUpdate, GetUpdateIntervalOptions,
LookUpInit, Empty, Wait, GetChoices, UpdateGroup, SourceChange, Find, WatchInventoryWindowResize) {
- return function(params) {
-
- var parent_scope = params.scope;
- var group_id = params.group_id;
- var tree_id = params.tree_id;
- var inventory_id = params.inventory_id;
- var groups_reload = params.groups_reload;
-
- var generator = GenerateForm;
- var form = GroupForm;
- var defaultUrl = GetBasePath('groups') + group_id + '/';
- var master = {};
+ return function (params) {
- // Load the modal form
- var scope = generator.inject(form, { mode: 'edit', modal: true, related: false, show_modal: false });
- generator.reset();
-
- GetSourceTypeOptions({ scope: scope, variable: 'source_type_options' });
-
- scope.formModalActionLabel = 'Save';
- scope.formModalHeader = 'Group';
- scope.formModalCancelShow = true;
- scope.source = form.fields.source['default'];
- scope.parseType = 'yaml';
- scope[form.fields['source_vars'].parseTypeName] = 'yaml';
- scope.sourcePathRequired = false;
-
- ParseTypeChange(scope);
- ParseTypeChange(scope, 'source_vars', form.fields['source_vars'].parseTypeName);
-
- // After the group record is loaded, retrieve related data
- if (scope.groupLoadedRemove) {
- scope.groupLoadedRemove();
- }
- scope.groupLoadedRemove = scope.$on('groupLoaded', function() {
- if (scope.variable_url) {
- // get group variables
- Rest.setUrl(scope.variable_url);
- Rest.get()
- .success( function(data, status, headers, config) {
- if ($.isEmptyObject(data)) {
- scope.variables = "---";
- }
- else {
- scope.variables = jsyaml.safeDump(data);
- }
- Wait('stop');
- })
- .error( function(data, status, headers, config) {
- scope.variables = null;
- Wait('stop');
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to retrieve group variables. GET returned status: ' + status });
- });
+ var parent_scope = params.scope,
+ group_id = params.group_id,
+ tree_id = params.tree_id,
+ inventory_id = params.inventory_id,
+ groups_reload = params.groups_reload,
+ generator = GenerateForm,
+ form = GroupForm,
+ defaultUrl = GetBasePath('groups') + group_id + '/',
+ master = {},
+ choicesReady,
+ scope = generator.inject(form, { mode: 'edit', modal: true, related: false, show_modal: false });
+
+ generator.reset();
+
+ GetSourceTypeOptions({ scope: scope, variable: 'source_type_options' });
+
+ scope.formModalActionLabel = 'Save';
+ scope.formModalHeader = 'Group';
+ scope.formModalCancelShow = true;
+ scope.source = form.fields.source['default'];
+ scope.parseType = 'yaml';
+ scope[form.fields.source_vars.parseTypeName] = 'yaml';
+ scope.sourcePathRequired = false;
+
+ ParseTypeChange(scope);
+ ParseTypeChange(scope, 'source_vars', form.fields.source_vars.parseTypeName);
+
+ // After the group record is loaded, retrieve related data
+ if (scope.groupLoadedRemove) {
+ scope.groupLoadedRemove();
}
- else {
- scope.variables = "---";
- }
- master.variables = scope.variables;
+ scope.groupLoadedRemove = scope.$on('groupLoaded', function () {
+ if (scope.variable_url) {
+ // get group variables
+ Rest.setUrl(scope.variable_url);
+ Rest.get()
+ .success(function (data) {
+ if ($.isEmptyObject(data)) {
+ scope.variables = "---";
+ } else {
+ scope.variables = jsyaml.safeDump(data);
+ }
+ Wait('stop');
+ })
+ .error(function (data, status) {
+ scope.variables = null;
+ Wait('stop');
+ ProcessErrors(scope, data, status, form, {
+ hdr: 'Error!',
+ msg: 'Failed to retrieve group variables. GET returned status: ' + status
+ });
+ });
+ } else {
+ scope.variables = "---";
+ }
+ master.variables = scope.variables;
- if (scope.source_url) {
- // get source data
- Rest.setUrl(scope.source_url);
- Rest.get()
- .success( function(data, status, headers, config) {
- for (var fld in form.fields) {
- if (fld == 'checkbox_group') {
- for (var i = 0; i < form.fields[fld].fields.length; i++) {
- var flag = form.fields[fld].fields[i];
- if (data[flag.name] !== undefined) {
- scope[flag.name] = data[flag.name];
- master[flag.name] = scope[flag.name];
- }
- }
- }
- if (fld == 'source') {
- var found = false;
- for (var i=0; i < scope.source_type_options.length; i++) {
- if (scope.source_type_options[i].value == data['source']) {
- scope['source'] = scope.source_type_options[i];
- found = true;
- }
- }
- if (!found || scope['source'].value == "") {
- scope['groupUpdateHide'] = true;
- }
- else {
- scope['groupUpdateHide'] = false;
- }
- master['source'] = scope['source'];
- }
- else if (fld == 'update_interval') {
- if (data[fld] == '' || data[fld] == null || data[fld] == undefined) {
- data[fld] = 0;
- }
- for (var i=0; i < scope.update_interval_options.length; i++) {
- if (scope.update_interval_options[i].value ==
- data[fld]) {
- scope[fld] = scope.update_interval_options[i];
- }
- }
- }
- else if (fld == 'source_vars') {
- // Parse source_vars, converting to YAML.
- if ($.isEmptyObject(data.source_vars) || data.source_vars == "\{\}" ||
- data.source_vars == "null" || data.source_vars == "") {
- scope.source_vars = "---";
- }
- else {
- var json_obj = JSON.parse(data.source_vars);
- scope.source_vars = jsyaml.safeDump(json_obj);
- }
- master.source_vars = scope.variables;
- }
- else if (data[fld]) {
- scope[fld] = data[fld];
- master[fld] = scope[fld];
- }
-
- if (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];
- }
- }
-
- scope.sourceChange(); //set defaults that rely on source value
-
- if (data['source_regions']) {
- if (data['source'] == 'ec2' || data['source'] == 'rax') {
- var set = (data['source'] == 'ec2') ? scope['ec2_regions'] : scope['rax_regions'];
- var opts = [];
- var list = data['source_regions'].split(',');
- for (var i=0; i < list.length; i++) {
- for (var j=0; j < set.length; j++) {
- if (list[i] == set[j].value) {
- opts.push({ id: set[j].value, text: set[j].label });
+ if (scope.source_url) {
+ // get source data
+ Rest.setUrl(scope.source_url);
+ Rest.get()
+ .success(function (data) {
+ var fld, i, j, flag, found, json_obj, set, opts, list;
+ for (fld in form.fields) {
+ if (fld === 'checkbox_group') {
+ for (i = 0; i < form.fields[fld].fields.length; i++) {
+ flag = form.fields[fld].fields[i];
+ if (data[flag.name] !== undefined) {
+ scope[flag.name] = data[flag.name];
+ master[flag.name] = scope[flag.name];
}
}
}
- master['source_regions'] = opts;
- $('#s2id_group_source_regions').select2('data', opts);
+ if (fld === 'source') {
+ found = false;
+ for (i = 0; i < scope.source_type_options.length; i++) {
+ if (scope.source_type_options[i].value === data.source) {
+ scope.source = scope.source_type_options[i];
+ found = true;
+ }
+ }
+ if (!found || scope.source.value === "") {
+ scope.groupUpdateHide = true;
+ } else {
+ scope.groupUpdateHide = false;
+ }
+ master.source = scope.source;
+ } else if (fld === 'update_interval') {
+ if (data[fld] === '' || data[fld] === null || data[fld] === undefined) {
+ data[fld] = 0;
+ }
+ for (i = 0; i < scope.update_interval_options.length; i++) {
+ if (scope.update_interval_options[i].value === data[fld]) {
+ scope[fld] = scope.update_interval_options[i];
+ }
+ }
+ } else if (fld === 'source_vars') {
+ // Parse source_vars, converting to YAML.
+ if ($.isEmptyObject(data.source_vars) || data.source_vars === "{}" ||
+ data.source_vars === "null" || data.source_vars === "") {
+ scope.source_vars = "---";
+ } else {
+ json_obj = JSON.parse(data.source_vars);
+ scope.source_vars = jsyaml.safeDump(json_obj);
+ }
+ master.source_vars = scope.variables;
+ } else if (data[fld]) {
+ scope[fld] = data[fld];
+ master[fld] = scope[fld];
+ }
+
+ if (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];
+ }
}
- }
- else {
- // If empty, default to all
- master['source_regions'] = [{ id: 'all', text: 'All' }];
- }
- scope['group_update_url'] = data.related['update'];
- Wait('stop');
+
+ scope.sourceChange(); //set defaults that rely on source value
+
+ if (data.source_regions) {
+ if (data.source === 'ec2' || data.source === 'rax') {
+ set = (data.source === 'ec2') ? scope.ec2_regions : scope.rax_regions;
+ opts = [];
+ list = data.source_regions.split(',');
+ for (i = 0; i < list.length; i++) {
+ for (j = 0; j < set.length; j++) {
+ if (list[i] === set[j].value) {
+ opts.push({
+ id: set[j].value,
+ text: set[j].label
+ });
+ }
+ }
+ }
+ master.source_regions = opts;
+ $('#s2id_group_source_regions').select2('data', opts);
+ }
+ } else {
+ // If empty, default to all
+ master.source_regions = [{
+ id: 'all',
+ text: 'All'
+ }];
+ }
+ scope.group_update_url = data.related.update;
+ Wait('stop');
})
- .error( function(data, status, headers, config) {
- scope.source = "";
- Wait('stop');
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to retrieve inventory source. GET status: ' + status });
+ .error(function (data, status) {
+ scope.source = "";
+ Wait('stop');
+ ProcessErrors(scope, data, status, form, { hdr: 'Error!',
+ msg: 'Failed to retrieve inventory source. GET status: ' + status });
});
- }
+ }
});
- if (scope.removeChoicesComplete) {
- scope.removeChoicesComplete();
- }
- scope.removeChoicesComplete = scope.$on('choicesCompleteGroup', function() {
- // Retrieve detail record and prepopulate the form
- Rest.setUrl(defaultUrl);
- Rest.get()
- .success( function(data, status, headers, config) {
- for (var fld in form.fields) {
- if (data[fld]) {
- scope[fld] = data[fld];
- master[fld] = scope[fld];
+ if (scope.removeChoicesComplete) {
+ scope.removeChoicesComplete();
+ }
+ scope.removeChoicesComplete = scope.$on('choicesCompleteGroup', function () {
+ // Retrieve detail record and prepopulate the form
+ Rest.setUrl(defaultUrl);
+ Rest.get()
+ .success(function (data) {
+ for (var fld in form.fields) {
+ if (data[fld]) {
+ scope[fld] = data[fld];
+ master[fld] = scope[fld];
+ }
}
- }
- scope.variable_url = data.related.variable_data;
- scope.source_url = data.related.inventory_source;
- $('#form-modal').modal('show');
- scope.$emit('groupLoaded');
+ scope.variable_url = data.related.variable_data;
+ scope.source_url = data.related.inventory_source;
+ $('#form-modal').modal('show');
+ scope.$emit('groupLoaded');
})
- .error( function(data, status, headers, config) {
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to retrieve group: ' + defaultUrl + '. GET status: ' + status });
+ .error(function (data, status) {
+ ProcessErrors(scope, data, status, form, {
+ hdr: 'Error!',
+ msg: 'Failed to retrieve group: ' + defaultUrl + '. GET status: ' + status
+ });
});
});
-
- var choicesReady = 0;
- if (scope.removeChoicesReady) {
- scope.removeChoicesReady();
- }
- scope.removeChoicesReady = scope.$on('choicesReadyGroup', function() {
- choicesReady++;
- if (choicesReady == 2) {
- scope.$emit('choicesCompleteGroup');
+ choicesReady = 0;
+
+ if (scope.removeChoicesReady) {
+ scope.removeChoicesReady();
}
+ scope.removeChoicesReady = scope.$on('choicesReadyGroup', function () {
+ choicesReady++;
+ if (choicesReady === 2) {
+ scope.$emit('choicesCompleteGroup');
+ }
});
- // Load options for source regions
- GetChoices({
- scope: scope,
- url: GetBasePath('inventory_sources'),
- field: 'source_regions',
- variable: 'rax_regions',
- choice_name: 'rax_region_choices',
- callback: 'choicesReadyGroup'
+ // Load options for source regions
+ GetChoices({
+ scope: scope,
+ url: GetBasePath('inventory_sources'),
+ field: 'source_regions',
+ variable: 'rax_regions',
+ choice_name: 'rax_region_choices',
+ callback: 'choicesReadyGroup'
});
- GetChoices({
- scope: scope,
- url: GetBasePath('inventory_sources'),
- field: 'source_regions',
- variable: 'ec2_regions',
- choice_name: 'ec2_region_choices',
- callback: 'choicesReadyGroup'
- });
-
- Wait('start');
+ GetChoices({
+ scope: scope,
+ url: GetBasePath('inventory_sources'),
+ field: 'source_regions',
+ variable: 'ec2_regions',
+ choice_name: 'ec2_region_choices',
+ callback: 'choicesReadyGroup'
+ });
- if (scope.removeSaveComplete) {
- scope.removeSaveComplete();
- }
- scope.removeSaveComplete = scope.$on('SaveComplete', function(e, error) {
- if (!error) {
- // Update the view with any changes
- if (groups_reload) {
- UpdateGroup({
- scope: parent_scope,
- group_id: group_id,
- properties: {
- name: scope.name,
- description: scope.description,
- has_inventory_sources: (scope.source && scope.source.value) ? true : false,
- source: (scope.source && scope.source.value) ? scope.source.value : ''
+ Wait('start');
+
+ if (scope.removeSaveComplete) {
+ scope.removeSaveComplete();
+ }
+ scope.removeSaveComplete = scope.$on('SaveComplete', function (e, error) {
+ if (!error) {
+ // Update the view with any changes
+ if (groups_reload) {
+ UpdateGroup({
+ scope: parent_scope,
+ group_id: group_id,
+ properties: {
+ name: scope.name,
+ description: scope.description,
+ has_inventory_sources: (scope.source && scope.source.value) ? true : false,
+ source: (scope.source && scope.source.value) ? scope.source.value : ''
}
});
+ } else if (scope.home_groups) {
+ // When home.groups controller is calling, update the groups array
+ var g = Find({
+ list: parent_scope.home_groups,
+ key: 'id',
+ val: group_id
+ });
+ if (g) {
+ g.name = scope.name;
+ g.description = scope.description;
+ }
+ }
+
+ //Clean up
+ if (scope.searchCleanUp) {
+ scope.searchCleanup();
+ }
+
+ scope.formModalActionDisabled = false;
+
+ $('#form-modal').modal('hide');
+
+ // Change the selected group
+ if (groups_reload && parent_scope.selected_tree_id !== tree_id) {
+ parent_scope.showHosts(tree_id, group_id, false);
+ } else {
+ Wait('stop');
+ }
+ WatchInventoryWindowResize();
}
- else if (scope.home_groups) {
- // When home.groups controller is calling, update the groups array
- var g = Find({ list: parent_scope.home_groups, key: 'id', val: group_id });
- if (g) {
- g.name = scope.name;
- g.description = scope.description;
+ });
+
+ if (scope.removeFormSaveSuccess) {
+ scope.removeFormSaveSuccess();
+ }
+ scope.removeFormSaveSuccess = scope.$on('formSaveSuccess', function () {
+
+ // Source data gets stored separately from the group. Validate and store Source
+ // related fields, then call SaveComplete to wrap things up.
+
+ var parseError = false,
+ regions, r, i, json_data,
+ data = {
+ group: group_id,
+ source: ((scope.source && scope.source.value) ? scope.source.value : ''),
+ source_path: scope.source_path,
+ credential: scope.credential,
+ overwrite: scope.overwrite,
+ overwrite_vars: scope.overwrite_vars,
+ update_on_launch: scope.update_on_launch
+ };
+
+ // Create a string out of selected list of regions
+ regions = $('#s2id_group_source_regions').select2("data");
+ r = [];
+ for (i = 0; i < regions.length; i++) {
+ r.push(regions[i].id);
+ }
+ data.source_regions = r.join();
+
+ if (scope.source && scope.source.value === 'ec2') {
+ // for ec2, validate variable data
+ try {
+ if (scope.envParseType === 'json') {
+ json_data = JSON.parse(scope.source_vars); //make sure JSON parses
+ } else {
+ json_data = jsyaml.load(scope.source_vars); //parse yaml
+ }
+
+ // Make sure our JSON is actually an object
+ if (typeof json_data !== 'object') {
+ throw "failed to return an object!";
+ }
+
+ // Send JSON as a string
+ if ($.isEmptyObject(json_data)) {
+ data.source_vars = "";
+ } else {
+ data.source_vars = JSON.stringify(json_data);
+ }
+ } catch (err) {
+ parseError = true;
+ scope.$emit('SaveComplete', true);
+ Alert("Error", "Error parsing extra variables. Parser returned: " + err);
}
}
-
- //Clean up
- if (scope.searchCleanUp) {
+
+ if (!parseError) {
+ Rest.setUrl(scope.source_url);
+ Rest.put(data)
+ .success(function () {
+ scope.$emit('SaveComplete', false);
+ })
+ .error(function (data, status) {
+ scope.$emit('SaveComplete', true);
+ ProcessErrors(scope, data, status, form, { hdr: 'Error!',
+ msg: 'Failed to update group inventory source. PUT status: ' + status });
+ });
+ }
+ });
+
+ // Cancel
+ scope.cancelModal = function () {
+ if (scope.searchCleanup) {
scope.searchCleanup();
}
-
- scope.formModalActionDisabled = false;
-
- $('#form-modal').modal('hide');
-
- // Change the selected group
- if (groups_reload && parent_scope.selected_tree_id !== tree_id) {
- parent_scope.showHosts(tree_id, group_id, false);
- }
- else {
- Wait('stop');
- }
WatchInventoryWindowResize();
- }
- });
+ };
- if (scope.removeFormSaveSuccess) {
- scope.removeFormSaveSuccess();
- }
- scope.removeFormSaveSuccess = scope.$on('formSaveSuccess', function(e) {
-
- // Source data gets stored separately from the group. Validate and store Source
- // related fields, then call SaveComplete to wrap things up.
-
- var parseError = false,
- saveError = false,
- regions, r, i,
-
- data = { group: group_id,
- source: ( (scope.source && scope.source.value) ? scope.source.value : '' ),
- source_path: scope['source_path'],
- credential: scope['credential'],
- overwrite: scope['overwrite'],
- overwrite_vars: scope['overwrite_vars'],
- update_on_launch: scope['update_on_launch']
- };
-
- // Create a string out of selected list of regions
- regions = $('#s2id_group_source_regions').select2("data");
- r = [];
- for (i=0; i < regions.length; i++) {
- r.push(regions[i].id);
- }
- data['source_regions'] = r.join();
-
- if (scope.source && scope.source.value == 'ec2') {
- // for ec2, validate variable data
+ // Save
+ scope.formModalAction = function () {
+ Wait('start');
try {
- if (scope.envParseType == 'json') {
- var json_data = JSON.parse(scope.source_vars); //make sure JSON parses
- }
- else {
- var json_data = jsyaml.load(scope.source_vars); //parse yaml
- }
-
- // Make sure our JSON is actually an object
- if (typeof json_data !== 'object') {
- throw "failed to return an object!";
- }
-
- // Send JSON as a string
- if ($.isEmptyObject(json_data)) {
- data.source_vars = "";
- }
- else {
- data.source_vars = JSON.stringify(json_data);
- }
- }
- catch(err) {
- parseError = true;
- scope.$emit('SaveComplete', true);
- Alert("Error", "Error parsing extra variables. Parser returned: " + err);
- }
- }
+ var fld, data, json_data;
- if (!parseError) {
- Rest.setUrl(scope.source_url)
- Rest.put(data)
- .success( function(data, status, headers, config) {
- scope.$emit('SaveComplete', false);
- })
- .error( function(data, status, headers, config) {
- scope.$emit('SaveComplete', true);
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to update group inventory source. PUT status: ' + status });
- });
- }
- });
+ // 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
+ }
- // Cancel
- scope.cancelModal = function() {
- if (scope.searchCleanup) {
- scope.searchCleanup();
- }
- WatchInventoryWindowResize();
- }
+ // Make sure our JSON is actually an object
+ if (typeof json_data !== 'object') {
+ throw "failed to return an object!";
+ }
- // Save
- scope.formModalAction = function() {
- Wait('start');
- try {
- var refreshHosts = false;
-
- // 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
- }
+ data = {};
+ for (fld in form.fields) {
+ data[fld] = scope[fld];
+ }
- // Make sure our JSON is actually an object
- if (typeof json_data !== 'object') {
- throw "failed to return an object!";
- }
+ data.inventory = inventory_id;
- var data = {}
- for (var fld in form.fields) {
- data[fld] = scope[fld];
- }
-
- data['inventory'] = inventory_id;
-
- Rest.setUrl(defaultUrl);
- Rest.put(data)
- .success( function(data, status, headers, config) {
- var group = data.id;
- if (scope.variables) {
- //update group variables
- Rest.setUrl(scope.variable_url);
- Rest.put(json_data)
- .success( function(data, status, headers, config) {
- scope.$emit('formSaveSuccess');
+ Rest.setUrl(defaultUrl);
+ Rest.put(data)
+ .success(function () {
+ if (scope.variables) {
+ //update group variables
+ Rest.setUrl(scope.variable_url);
+ Rest.put(json_data)
+ .success(function () {
+ scope.$emit('formSaveSuccess');
})
- .error( function(data, status, headers, config) {
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to update group variables. PUT status: ' + status });
+ .error(function (data, status) {
+ ProcessErrors(scope, data, status, form, { hdr: 'Error!',
+ msg: 'Failed to update group variables. PUT status: ' + status });
});
- }
- else {
- scope.$emit('formSaveSuccess');
- }
+ } else {
+ scope.$emit('formSaveSuccess');
+ }
})
- .error( function(data, status, headers, config) {
- Wait('stop');
- ProcessErrors(scope, data, status, form,
- { hdr: 'Error!', msg: 'Failed to update group: ' + group_id + '. PUT status: ' + status });
+ .error(function (data, status) {
+ Wait('stop');
+ ProcessErrors(scope, data, status, form, {
+ hdr: 'Error!',
+ msg: 'Failed to update group: ' + group_id + '. PUT status: ' + status
+ });
});
- }
- catch(err) {
- Wait('stop');
- Alert("Error", "Error parsing group variables. Parser returned: " + err);
- }
- };
-
- // Start the update process
- scope.updateGroup = function() {
- if (scope.source == "" || scope.source == null) {
- Alert('Missing Configuration', 'The selected group is not configured for updates. You must first edit the group, provide Source settings, ' +
- 'and then run an update.', 'alert-info');
- }
- else if (scope.status == 'updating') {
- Alert('Update in Progress', 'The inventory update process is currently running for group ' +
- scope.summary_fields.group.name + ' . Use the Refresh button to monitor the status.', 'alert-info');
- }
- else {
- /*if (scope.source == 'Amazon EC2') {
- scope.sourceUsernameLabel = 'Access Key ID';
- scope.sourcePasswordLabel = 'Secret Access Key';
- scope.sourcePasswordConfirmLabel = 'Confirm Secret Access Key';
- }
- else {
- scope.sourceUsernameLabel = 'Username';
- scope.sourcePasswordLabel = 'Password';
- scope.sourcePasswordConfirmLabel = 'Confirm Password';
- }*/
- InventoryUpdate({
- scope: scope,
- group_id: group_id,
- url: scope.group_update_url,
- group_name: scope.name,
- group_source: scope.source.value
- });
- }
- }
-
- // Change the lookup and regions when the source changes
- scope.sourceChange = function() {
- SourceChange({
- scope: scope,
- form: GroupForm
- });
- }
-
- }
- }])
-
-
- .factory('GroupsDelete', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
- 'Prompt', 'ProcessErrors', 'GetBasePath', 'Wait', 'BuildTree', 'Find',
- function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
- GetBasePath, Wait, BuildTree, Find) {
- return function(params) {
- // Delete the selected group node. Disassociates it from its parent.
-
- var scope = params.scope;
- var tree_id = params.tree_id;
- var group_id = params.group_id;
- var inventory_id = params.inventory_id;
-
- var node = Find({ list: scope.groups, key: 'id', val: tree_id });
- var url = GetBasePath('inventory') + inventory_id + '/groups/';
-
- var action_to_take = function() {
- $('#prompt-modal').on('hidden.bs.modal', function(){ Wait('start'); });
- $('#prompt-modal').modal('hide');
- Rest.setUrl(url);
- Rest.post({ id: node.group_id, disassociate: 1 })
- .success( function(data, status, headers, config) {
- $('#prompt-modal').off();
- scope.$emit('GroupDeleteCompleted'); // Signal a group refresh to start
- })
- .error( function(data, status, headers, config) {
- Wait('stop');
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
- });
- };
-
- Prompt({ hdr: 'Delete Group', body: 'Are you sure you want to delete group ' + node.name + '?
',
- action: action_to_take, 'class': 'btn-danger' });
- }
- }])
-
-
- .factory('ShowUpdateStatus', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm',
- 'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'InventoryStatusForm', 'Wait', 'Empty', 'WatchInventoryWindowResize',
- function($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath,
- FormatDate, InventoryStatusForm, Wait, Empty, WatchInventoryWindowResize) {
- return function(params) {
-
- var group_name = params.group_name;
- var last_update = params.last_update;
- var generator = GenerateForm;
- var form = InventoryStatusForm;
- var license_error = params.license_error;
- var tree_id = params.tree_id;
- var group_id = params.group_id;
- var parent_scope = params.parent_scope;
-
- var maxrows, html, scope, ww, wh, x, y;
-
- function calcRows (content) {
- var n, rows;
- n = content.match(/\n/g);
- rows = (n) ? n.length : 1;
- return (rows > maxrows) ? maxrows : rows;
- }
-
- if (last_update == undefined || last_update == null || last_update == ''){
- Wait('stop');
- Alert('Missing Configuration', 'The selected group is not configured for inventory sync. ' +
- 'Edit the group and provide Source information.', 'alert-info');
- }
- else {
-
- html = "\n";
-
- $('#inventory-modal-container').empty().append(html);
- scope = generator.inject(form, { mode: 'edit', id: 'form-container', breadCrumbs: false, related: false });
-
- // Set modal dimensions based on viewport width
- ww = $(document).width();
- wh = $('body').height();
- if (ww > 1199) {
- // desktop
- x = 675;
- y = (750 > wh) ? wh - 20 : 750;
- maxrows = 18;
- }
- else if (ww <= 1199 && ww >= 768) {
- x = 550;
- y = (620 > wh) ? wh - 15 : 620;
- maxrows = 12;
- }
- else {
- x = (ww - 20);
- y = (500 > wh) ? wh : 500;
- maxrows = 10;
- }
-
- // Create the modal
- $('#status-modal-dialog').dialog({
- buttons: { "OK": function() { $( this ).dialog( "close" ); } },
- modal: true,
- width: x,
- height: y,
- autoOpen: false,
- create: function (e, ui) {
- // fix the close button
- $('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-titlebar button')
- .empty().attr({ 'class': 'close' }).text('x');
- // fix the OK button
- $('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-buttonset button:first')
- .attr({ 'class': 'btn btn-primary' });
- },
- resizeStop: function(e, ui) {
- // for some reason, after resizing dialog the form and fields (the content) doesn't expand to 100%
- var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]');
- var content = dialog.find('#status-modal-dialog');
- content.width( dialog.width() - 28 );
- },
- close: function(e, ui) {
- // Destroy on close
- $('.tooltip').each( function(index) {
- // Remove any lingering tooltip elements
- $(this).remove();
- });
- $('.popover').each(function(index) {
- // remove lingering popover
elements
- $(this).remove();
- });
- $('#status-modal-dialog').dialog('destroy');
- $('#inventory-modal-container').empty();
- WatchInventoryWindowResize();
- },
- open: function(e, ui) {
+ } catch (err) {
Wait('stop');
+ Alert("Error", "Error parsing group variables. Parser returned: " + err);
+ }
+ };
+
+ // Start the update process
+ scope.updateGroup = function () {
+ if (scope.source === "" || scope.source === null) {
+ Alert('Missing Configuration', 'The selected group is not configured for updates. You must first edit the group, provide Source settings, ' +
+ 'and then run an update.', 'alert-info');
+ } else if (scope.status === 'updating') {
+ Alert('Update in Progress', 'The inventory update process is currently running for group
' +
+ scope.summary_fields.group.name + ' . Use the Refresh button to monitor the status.', 'alert-info');
+ } else {
+ InventoryUpdate({
+ scope: scope,
+ group_id: group_id,
+ url: scope.group_update_url,
+ group_name: scope.name,
+ group_source: scope.source.value
+ });
+ }
+ };
+
+ // Change the lookup and regions when the source changes
+ scope.sourceChange = function () {
+ SourceChange({ scope: scope, form: GroupForm });
+ };
+
+ };
+ }
+])
+
+
+.factory('GroupsDelete', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
+ 'Prompt', 'ProcessErrors', 'GetBasePath', 'Wait', 'BuildTree', 'Find',
+ function ($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
+ GetBasePath, Wait, BuildTree, Find) {
+ return function (params) {
+ // Delete the selected group node. Disassociates it from its parent.
+
+ var scope = params.scope,
+ tree_id = params.tree_id,
+ inventory_id = params.inventory_id,
+ node = Find({ list: scope.groups, key: 'id', val: tree_id }),
+ url = GetBasePath('inventory') + inventory_id + '/groups/',
+ action_to_take;
+
+ action_to_take = function () {
+ $('#prompt-modal').on('hidden.bs.modal', function () {
+ Wait('start');
+ });
+ $('#prompt-modal').modal('hide');
+ Rest.setUrl(url);
+ Rest.post({ id: node.group_id, disassociate: 1 })
+ .success(function () {
+ $('#prompt-modal').off();
+ scope.$emit('GroupDeleteCompleted'); // Signal a group refresh to start
+ })
+ .error(function (data, status) {
+ Wait('stop');
+ ProcessErrors(scope, data, status, null, {
+ hdr: 'Error!',
+ msg: 'Call to ' + url + ' failed. POST returned status: ' + status
+ });
+ });
+ };
+
+ Prompt({
+ hdr: 'Delete Group',
+ body: '
Are you sure you want to delete group ' + node.name + '?
',
+ action: action_to_take,
+ 'class': 'btn-danger'
+ });
+ };
+ }
+])
+
+
+.factory('ShowUpdateStatus', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm',
+ 'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'InventoryStatusForm', 'Wait', 'Empty', 'WatchInventoryWindowResize',
+ function ($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath,
+ FormatDate, InventoryStatusForm, Wait, Empty, WatchInventoryWindowResize) {
+ return function (params) {
+
+ var group_name = params.group_name,
+ last_update = params.last_update,
+ generator = GenerateForm,
+ form = InventoryStatusForm,
+ license_error = params.license_error,
+ maxrows, html, scope, ww, wh, x, y;
+
+ function calcRows(content) {
+ var n, rows;
+ n = content.match(/\n/g);
+ rows = (n) ? n.length : 1;
+ return (rows > maxrows) ? maxrows : rows;
+ }
+
+ if (last_update === undefined || last_update === null || last_update === '') {
+ Wait('stop');
+ Alert('Missing Configuration', 'The selected group is not configured for inventory sync. ' +
+ 'Edit the group and provide Source information.', 'alert-info');
+ } else {
+ html = "
\n";
+
+ $('#inventory-modal-container').empty().append(html);
+ scope = generator.inject(form, {
+ mode: 'edit',
+ id: 'form-container',
+ breadCrumbs: false,
+ related: false
+ });
+
+ // Set modal dimensions based on viewport width
+ ww = $(document).width();
+ wh = $('body').height();
+ if (ww > 1199) {
+ // desktop
+ x = 675;
+ y = (750 > wh) ? wh - 20 : 750;
+ maxrows = 18;
+ } else if (ww <= 1199 && ww >= 768) {
+ x = 550;
+ y = (620 > wh) ? wh - 15 : 620;
+ maxrows = 12;
+ } else {
+ x = (ww - 20);
+ y = (500 > wh) ? wh : 500;
+ maxrows = 10;
+ }
+
+ // Create the modal
+ $('#status-modal-dialog').dialog({
+ buttons: {
+ "OK": function () {
+ $(this).dialog("close");
+ }
+ },
+ modal: true,
+ width: x,
+ height: y,
+ autoOpen: false,
+ create: function () {
+ // fix the close button
+ $('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-titlebar button')
+ .empty().attr({
+ 'class': 'close'
+ }).text('x');
+ // fix the OK button
+ $('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-buttonset button:first')
+ .attr({
+ 'class': 'btn btn-primary'
+ });
+ },
+ resizeStop: function () {
+ // for some reason, after resizing dialog the form and fields (the content) doesn't expand to 100%
+ var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]'),
+ content = dialog.find('#status-modal-dialog');
+ content.width(dialog.width() - 28);
+ },
+ close: function () {
+ // Destroy on close
+ $('.tooltip').each(function () {
+ // Remove any lingering tooltip
elements
+ $(this).remove();
+ });
+ $('.popover').each(function () {
+ // remove lingering popover
elements
+ $(this).remove();
+ });
+ $('#status-modal-dialog').dialog('destroy');
+ $('#inventory-modal-container').empty();
+ WatchInventoryWindowResize();
+ },
+ open: function () {
+ Wait('stop');
}
});
- Rest.setUrl(last_update);
- Rest.get()
- .success( function(data, status, headers, config) {
- for (var fld in form.fields) {
- if (data[fld]) {
- if (fld == 'created') {
- scope[fld] = FormatDate(new Date(data[fld]));
- }
- else {
- scope[fld] = data[fld];
- }
+ Rest.setUrl(last_update);
+ Rest.get()
+ .success(function (data) {
+ for (var fld in form.fields) {
+ if (data[fld]) {
+ if (fld === 'created') {
+ scope[fld] = FormatDate(new Date(data[fld]));
+ } else {
+ scope[fld] = data[fld];
+ }
+ }
}
- }
- scope.license_error = license_error;
- scope.status_rows = calcRows(data.status);
- scope.stdout_rows = calcRows(data.result_stdout);
- scope.traceback_rows = calcRows(data.result_traceback);
- $('#status-modal-dialog').dialog('open');
+ scope.license_error = license_error;
+ scope.status_rows = calcRows(data.status);
+ scope.stdout_rows = calcRows(data.result_stdout);
+ scope.traceback_rows = calcRows(data.result_traceback);
+ $('#status-modal-dialog').dialog('open');
})
- .error( function(data, status, headers, config) {
- $('#form-modal').modal("hide");
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Failed to retrieve last update: ' + last_update + '. GET status: ' + status });
+ .error(function (data, status) {
+ $('#form-modal').modal("hide");
+ ProcessErrors(scope, data, status, null, {
+ hdr: 'Error!',
+ msg: 'Failed to retrieve last update: ' + last_update + '. GET status: ' + status
+ });
});
- }
-
- }
- }]);
-
-
-
-
-
-
-
+ }
+ };
+ }
+]);
\ No newline at end of file
diff --git a/awx/ui/static/js/helpers/Hosts.js b/awx/ui/static/js/helpers/Hosts.js
index 0651a7345a..88bb7c7096 100644
--- a/awx/ui/static/js/helpers/Hosts.js
+++ b/awx/ui/static/js/helpers/Hosts.js
@@ -9,6 +9,8 @@
/* jshint loopfunc: true */
+'use strict';
+
angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'HostListDefinition',
'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'AuthService', 'HostsHelper',
'InventoryHelper', 'RelatedSearchHelper', 'InventoryFormDefinition', 'SelectionHelper',
diff --git a/awx/ui/static/js/helpers/JobSubmission.js b/awx/ui/static/js/helpers/JobSubmission.js
index de4495d28d..d5ed796493 100644
--- a/awx/ui/static/js/helpers/JobSubmission.js
+++ b/awx/ui/static/js/helpers/JobSubmission.js
@@ -2,479 +2,463 @@
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* JobSubmission.js
- *
+ *
*/
-angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'CredentialFormDefinition', 'CredentialsListDefinition',
- 'LookUpHelper', 'ProjectFormDefinition', 'JobSubmissionHelper' ])
- .factory('PromptPasswords', ['CredentialForm', 'JobTemplateForm', '$compile', 'Rest', '$location', 'ProcessErrors',
- 'GetBasePath', 'Alert', 'Empty', 'Wait',
- function(CredentialForm, JobTemplateForm, $compile, Rest, $location, ProcessErrors, GetBasePath, Alert, Empty, Wait) {
- return function(params) {
-
- var scope = params.scope;
- var passwords = params.passwords;
- var start_url = params.start_url;
- var form = params.form;
- var html = '';
- var field, element, dialogScope, fld;
- var base = $location.path().replace(/^\//,'').split('/')[0];
- var extra_html = params.extra_html;
+'use strict';
- function navigate(canceled) {
- //Decide where to send the user once the modal dialog closes
- if (!canceled) {
- if (base == 'jobs') {
- scope.refreshJob();
- }
- else {
- $location.path('/jobs');
- }
- }
- else {
- $location.path('/' + base);
- }
- }
+angular.module('JobSubmissionHelper', ['RestServices', 'Utilities', 'CredentialFormDefinition', 'CredentialsListDefinition',
+ 'LookUpHelper', 'ProjectFormDefinition', 'JobSubmissionHelper'
+])
- function cancel() {
- // Delete a job
- var url = GetBasePath('jobs') + scope.job_id +'/'
- Rest.setUrl(url);
- Rest.destroy()
- .success ( function(data, status, headers, config) {
- if (form.name == 'credential') {
- navigate(true);
+.factory('PromptPasswords', ['CredentialForm', 'JobTemplateForm', '$compile', 'Rest', '$location', 'ProcessErrors',
+ 'GetBasePath', 'Alert', 'Empty', 'Wait',
+ function (CredentialForm, JobTemplateForm, $compile, Rest, $location, ProcessErrors, GetBasePath, Alert, Empty, Wait) {
+ return function (params) {
+
+ var scope = params.scope,
+ passwords = params.passwords,
+ start_url = params.start_url,
+ form = params.form,
+ html = '',
+ field, element, fld, i, current_form,
+ base = $location.path().replace(/^\//, '').split('/')[0],
+ extra_html = params.extra_html;
+
+ function navigate(canceled) {
+ //Decide where to send the user once the modal dialog closes
+ if (!canceled) {
+ if (base === 'jobs') {
+ scope.refreshJob();
+ } else {
+ $location.path('/jobs');
}
+ } else {
+ $location.path('/' + base);
+ }
+ }
+
+ function cancel() {
+ // Delete a job
+ var url = GetBasePath('jobs') + scope.job_id + '/';
+ Rest.setUrl(url);
+ Rest.destroy()
+ .success(function () {
+ if (form.name === 'credential') {
+ navigate(true);
+ }
})
- .error( function(data, status, headers, config) {
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
+ .error(function (data, status) {
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
+ msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
}
- scope.cancelJob = function() {
- // User clicked cancel button
- $('#password-modal').modal('hide');
- if (form.name == 'credential') {
- cancel();
- }
- else {
- scope.$emit('UpdateSubmitted','canceled');
- }
- }
-
- scope.startJob = function() {
- $('#password-modal').modal('hide');
- Wait('start');
- var pswd = {};
- var value_supplied = false;
- $('.password-field').each(function(index) {
- pswd[$(this).attr('name')] = $(this).val();
- if ($(this).val() != '' && $(this).val() !== null) {
- value_supplied = true;
+ scope.cancelJob = function () {
+ // User clicked cancel button
+ $('#password-modal').modal('hide');
+ if (form.name === 'credential') {
+ cancel();
+ } else {
+ scope.$emit('UpdateSubmitted', 'canceled');
}
- });
- if (Empty(passwords) || passwords.length == 0 || value_supplied) {
- Rest.setUrl(start_url);
- Rest.post(pswd)
- .success( function(data, status, headers, config) {
- scope.$emit('UpdateSubmitted','started');
- if (form.name == 'credential') {
- navigate(false);
- }
- })
- .error( function(data, status, headers, config) {
- Wait('stop');
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'POST to ' + start_url + ' failed with status: ' + status });
- });
- }
- else {
- Wait('stop');
- Alert('No Passwords', 'Required password(s) not provided. The request was not submitted.', 'alert-info');
- if (form.name == 'credential') {
- // No passwords provided, so we can't start the job. Rather than leave the job in a 'new'
- // state, let's delete it.
- cancelJob();
- }
- }
- }
-
- if (passwords && passwords.length > 0) {
- Wait('stop');
- // Prompt for passwords
- html += "
\n";
- var element = angular.element(document.getElementById('password-body'));
- element.html(html);
- $compile(element.contents())(scope);
- $('#password-modal').modal();
- $('#password-modal').on('shown.bs.modal', function() {
- $('#password-body').find('input[type="password"]:first').focus();
- });
- }
- else {
- scope.startJob();
- }
- }
- }])
-
- .factory('SubmitJob',['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'CredentialList',
- 'LookUpInit', 'CredentialForm', 'ProcessErrors', 'JobTemplateForm', 'Wait',
- function(PromptPasswords, $compile, Rest, $location, GetBasePath, CredentialList, LookUpInit, CredentialForm,
- ProcessErrors, JobTemplateForm, Wait) {
- return function(params) {
- var scope = params.scope;
- var id = params.id;
- var template_name = (params.template) ? params.template : null;
- var base = $location.path().replace(/^\//,'').split('/')[0];
- var url = GetBasePath(base) + id + '/';
+ };
- function postJob(data) {
- // Create the job record
- if (scope.credentialWatchRemove) {
- scope.credentialWatchRemove();
+ scope.startJob = function () {
+ var pswd = {}, value_supplied = false;
+ $('#password-modal').modal('hide');
+ Wait('start');
+ $('.password-field').each(function () {
+ pswd[$(this).attr('name')] = $(this).val();
+ if ($(this).val() !== '' && $(this).val() !== null) {
+ value_supplied = true;
+ }
+ });
+ if (Empty(passwords) || passwords.length === 0 || value_supplied) {
+ Rest.setUrl(start_url);
+ Rest.post(pswd)
+ .success(function () {
+ scope.$emit('UpdateSubmitted', 'started');
+ if (form.name === 'credential') {
+ navigate(false);
+ }
+ })
+ .error(function (data, status) {
+ Wait('stop');
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
+ msg: 'POST to ' + start_url + ' failed with status: ' + status });
+ });
+ } else {
+ Wait('stop');
+ Alert('No Passwords', 'Required password(s) not provided. The request was not submitted.', 'alert-info');
+ if (form.name === 'credential') {
+ // No passwords provided, so we can't start the job. Rather than leave the job in a 'new'
+ // state, let's delete it.
+ scope.cancelJob();
+ }
+ }
+ };
+
+ if (passwords && passwords.length > 0) {
+ Wait('stop');
+ // Prompt for passwords
+ html += "
\n";
+ element = angular.element(document.getElementById('password-body'));
+ element.html(html);
+ $compile(element.contents())(scope);
+ $('#password-modal').modal();
+ $('#password-modal').on('shown.bs.modal', function () {
+ $('#password-body').find('input[type="password"]:first').focus();
+ });
+ } else {
+ scope.startJob();
}
- var dt = new Date().toISOString();
- var url = (data.related.jobs) ? data.related.jobs : data.related.job_template + 'jobs/';
- var name = (template_name) ? template_name : data.name;
- Wait('start');
- Rest.setUrl(url);
- Rest.post({
- name: name + ' ' + dt, // job name required and unique
- description: data.description,
- job_template: data.id,
- inventory: data.inventory,
- project: data.project,
- playbook: data.playbook,
- credential: data.credential,
- forks: data.forks,
- limit: data.limit,
- verbosity: data.verbosity,
- extra_vars: data.extra_vars
- })
- .success( function(data, status, headers, config) {
+ };
+ }
+])
+
+.factory('SubmitJob', ['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'CredentialList',
+ 'LookUpInit', 'CredentialForm', 'ProcessErrors', 'JobTemplateForm', 'Wait',
+ function (PromptPasswords, $compile, Rest, $location, GetBasePath, CredentialList, LookUpInit, CredentialForm,
+ ProcessErrors, JobTemplateForm, Wait) {
+ return function (params) {
+ var scope = params.scope,
+ id = params.id,
+ template_name = (params.template) ? params.template : null,
+ base = $location.path().replace(/^\//, '').split('/')[0],
+ url = GetBasePath(base) + id + '/';
+
+ function postJob(data) {
+ var dt, url, name;
+ // Create the job record
+ if (scope.credentialWatchRemove) {
+ scope.credentialWatchRemove();
+ }
+ dt = new Date().toISOString();
+ url = (data.related.jobs) ? data.related.jobs : data.related.job_template + 'jobs/';
+ name = (template_name) ? template_name : data.name;
+ Wait('start');
+ Rest.setUrl(url);
+ Rest.post({
+ name: name + ' ' + dt, // job name required and unique
+ description: data.description,
+ job_template: data.id,
+ inventory: data.inventory,
+ project: data.project,
+ playbook: data.playbook,
+ credential: data.credential,
+ forks: data.forks,
+ limit: data.limit,
+ verbosity: data.verbosity,
+ extra_vars: data.extra_vars
+ }).success(function (data) {
scope.job_id = data.id;
if (data.passwords_needed_to_start.length > 0) {
- // Passwords needed. Prompt for passwords, then start job.
- PromptPasswords({
- scope: scope,
- passwords: data.passwords_needed_to_start,
- start_url: data.related.start,
- form: CredentialForm
- });
+ // Passwords needed. Prompt for passwords, then start job.
+ PromptPasswords({
+ scope: scope,
+ passwords: data.passwords_needed_to_start,
+ start_url: data.related.start,
+ form: CredentialForm
+ });
+ } else {
+ // No passwords needed, start the job!
+ Rest.setUrl(data.related.start);
+ Rest.post()
+ .success(function () {
+ Wait('stop');
+ var base = $location.path().replace(/^\//, '').split('/')[0];
+ if (base === 'jobs') {
+ scope.refresh();
+ } else {
+ $location.path('/jobs');
+ }
+ })
+ .error(function (data, status) {
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
+ msg: 'Failed to start job. POST returned status: ' + status });
+ });
}
- else {
- // No passwords needed, start the job!
- Rest.setUrl(data.related.start);
- Rest.post()
- .success( function(data, status, headers, config) {
- Wait('stop');
- var base = $location.path().replace(/^\//,'').split('/')[0];
- if (base == 'jobs') {
- scope.refresh();
- }
- else {
- $location.path('/jobs');
- }
- })
- .error( function(data, status, headers, config) {
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Failed to start job. POST returned status: ' + status });
- });
- }
- })
- .error( function(data, status, headers, config) {
+ }).error(function (data, status) {
Wait('stop');
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Failed to create job. POST returned status: ' + status });
- });
- };
-
- // Get the job or job_template record
- Wait('start');
- Rest.setUrl(url);
- Rest.get()
- .success( function(data, status, headers, config) {
- // Create a job record
- scope.credential = '';
- if (data.credential == '' || data.credential == null) {
- // Template does not have credential, prompt for one
- Wait('stop');
- if (scope.credentialWatchRemove) {
- scope.credentialWatchRemove();
- }
- scope.credentialWatchRemove = scope.$watch('credential', function(newVal, oldVal) {
- if (newVal !== oldVal) {
- // After user selects a credential from the modal,
- // submit the job
- if (scope.credential != '' && scope.credential !== null && scope.credential !== undefined) {
- data.credential = scope.credential;
- postJob(data);
- }
- }
- });
- LookUpInit({
- scope: scope,
- form: JobTemplateForm,
- current_item: null,
- list: CredentialList,
- field: 'credential',
- hdr: 'Credential Required'
- });
- scope.lookUpCredential();
- }
- else {
- // We have what we need, submit the job
- postJob(data);
- }
- })
- .error( function(data, status, headers, config) {
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Failed to get job template details. GET returned status: ' + status });
- });
- };
- }])
-
- // Sumbit SCM Update request
- .factory('ProjectUpdate',['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'ProcessErrors', 'Alert',
- 'ProjectsForm', 'Wait',
- function(PromptPasswords, $compile, Rest, $location, GetBasePath, ProcessErrors, Alert, ProjectsForm, Wait) {
- return function(params) {
- var scope = params.scope;
- var project_id = params.project_id;
- var url = GetBasePath('projects') + project_id + '/update/';
-
- if (scope.removeUpdateSubmitted) {
- scope.removeUpdateSubmitted();
- }
- scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function(e, action) {
- // Refresh the project list after update request submitted
- Wait('stop');
- Alert('Update Started', 'The request to start the SCM update process was submitted. ' +
- 'To monitor the update status, refresh the page by clicking the
Refresh button.', 'alert-info');
- scope.refresh();
- });
-
- if (scope.removeSCMSubmit) {
- scope.removeSCMSubmit();
- }
- scope.removeSCMSubmit = scope.$on('SCMSubmit', function(e, passwords_needed_to_update, extra_html) {
- // After the call to update, kick off the job.
- PromptPasswords({
- scope: scope,
- passwords: passwords_needed_to_update,
- start_url: url,
- form: ProjectsForm,
- extra_html: extra_html
- });
- });
-
- // Check to see if we have permission to perform the update and if any passwords are needed
- Wait('start');
- Rest.setUrl(url);
- Rest.get()
- .success( function(data, status, headers, config) {
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
+ msg: 'Failed to create job. POST returned status: ' + status });
+ });
+ }
+
+ // Get the job or job_template record
+ Wait('start');
+ Rest.setUrl(url);
+ Rest.get()
+ .success(function (data) {
+ // Create a job record
+ scope.credential = '';
+ if (data.credential === '' || data.credential === null) {
+ // Template does not have credential, prompt for one
+ Wait('stop');
+ if (scope.credentialWatchRemove) {
+ scope.credentialWatchRemove();
+ }
+ scope.credentialWatchRemove = scope.$watch('credential', function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ // After user selects a credential from the modal,
+ // submit the job
+ if (scope.credential !== '' && scope.credential !== null && scope.credential !== undefined) {
+ data.credential = scope.credential;
+ postJob(data);
+ }
+ }
+ });
+ LookUpInit({
+ scope: scope,
+ form: JobTemplateForm,
+ current_item: null,
+ list: CredentialList,
+ field: 'credential',
+ hdr: 'Credential Required'
+ });
+ scope.lookUpCredential();
+ } else {
+ // We have what we need, submit the job
+ postJob(data);
+ }
+ })
+ .error(function (data, status) {
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
+ msg: 'Failed to get job template details. GET returned status: ' + status });
+ });
+ };
+ }
+])
+
+// Sumbit SCM Update request
+.factory('ProjectUpdate', ['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'ProcessErrors', 'Alert',
+ 'ProjectsForm', 'Wait',
+ function (PromptPasswords, $compile, Rest, $location, GetBasePath, ProcessErrors, Alert, ProjectsForm, Wait) {
+ return function (params) {
+ var scope = params.scope,
+ project_id = params.project_id,
+ url = GetBasePath('projects') + project_id + '/update/';
+
+ if (scope.removeUpdateSubmitted) {
+ scope.removeUpdateSubmitted();
+ }
+ scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function () {
+ // Refresh the project list after update request submitted
Wait('stop');
- if (data.can_update) {
- var extra_html = '';
- for (var i=0; i < scope.projects.length; i++) {
- if (scope.projects[i].id == project_id) {
- extra_html += "
\n";
- if (scope.projects[i].scm_username) {
- extra_html += "
\n";
- }
- break;
- }
- }
- extra_html += "";
- scope.$emit('SCMSubmit', data.passwords_needed_to_update, extra_html);
- }
- else {
- Alert('Permission Denied', 'You do not have access to update this project. Please contact your system administrator.',
- 'alert-danger');
- }
- })
- .error( function(data, status, headers, config) {
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Failed to get project update details: ' + url + ' GET status: ' + status });
+ Alert('Update Started', 'The request to start the SCM update process was submitted. ' +
+ 'To monitor the update status, refresh the page by clicking the
Refresh button.', 'alert-info');
+ scope.refresh();
});
- };
- }])
+
+ if (scope.removeSCMSubmit) {
+ scope.removeSCMSubmit();
+ }
+ scope.removeSCMSubmit = scope.$on('SCMSubmit', function (e, passwords_needed_to_update, extra_html) {
+ // After the call to update, kick off the job.
+ PromptPasswords({
+ scope: scope,
+ passwords: passwords_needed_to_update,
+ start_url: url,
+ form: ProjectsForm,
+ extra_html: extra_html
+ });
+ });
+
+ // Check to see if we have permission to perform the update and if any passwords are needed
+ Wait('start');
+ Rest.setUrl(url);
+ Rest.get()
+ .success(function (data) {
+ var i, extra_html;
+ Wait('stop');
+ if (data.can_update) {
+ extra_html = '';
+ for (i = 0; i < scope.projects.length; i++) {
+ if (scope.projects[i].id === project_id) {
+ extra_html += "
\n";
+ if (scope.projects[i].scm_username) {
+ extra_html += "
\n";
+ }
+ break;
+ }
+ }
+ extra_html += "";
+ scope.$emit('SCMSubmit', data.passwords_needed_to_update, extra_html);
+ } else {
+ Alert('Permission Denied', 'You do not have access to update this project. Please contact your system administrator.',
+ 'alert-danger');
+ }
+ })
+ .error(function (data, status) {
+ ProcessErrors(scope, data, status, null, {
+ hdr: 'Error!',
+ msg: 'Failed to get project update details: ' + url + ' GET status: ' + status
+ });
+ });
+ };
+ }
+])
- // Sumbit Inventory Update request
- .factory('InventoryUpdate',['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'ProcessErrors', 'Alert',
- 'GroupForm', 'BuildTree', 'Wait',
- function(PromptPasswords, $compile, Rest, $location, GetBasePath, ProcessErrors, Alert, GroupForm, BuildTree, Wait) {
- return function(params) {
-
- var scope = params.scope;
- var inventory_id = params.inventory_id;
- var url = params.url;
- var group_name = params.group_name;
- var group_source = params.group_source;
- var group_id = params.group_id;
- var tree_id = params.tree_id;
+// Sumbit Inventory Update request
+.factory('InventoryUpdate', ['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'ProcessErrors', 'Alert',
+ 'GroupForm', 'BuildTree', 'Wait',
+ function (PromptPasswords, $compile, Rest, $location, GetBasePath, ProcessErrors, Alert, GroupForm, BuildTree, Wait) {
+ return function (params) {
+
+ var scope = params.scope,
+ url = params.url,
+ group_id = params.group_id,
+ tree_id = params.tree_id;
- if (scope.removeHostReloadComplete) {
- scope.removeHostReloadComplete();
- }
- scope.removeHostReloadComplete = scope.$on('HostReloadComplete', function(e) {
- Wait('stop');
- Alert('Update Started', 'Your request to start the inventory sync process was submitted. Monitor progress ' +
- 'by clicking the
button.', 'alert-info');
if (scope.removeHostReloadComplete) {
scope.removeHostReloadComplete();
}
- });
-
- if (scope.removeUpdateSubmitted) {
- scope.removeUpdateSubmitted();
- }
- scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function(e, action) {
- if (action == 'started') {
- if (scope.refreshGroups) {
- scope.selected_tree_id = tree_id;
- scope.selected_group_id = group_id;
- scope.refreshGroups();
- }
- else if (scope.refresh) {
- scope.refresh();
- }
- scope.$emit('HostReloadComplete');
- }
- });
-
- if (scope.removeInventorySubmit) {
- scope.removeInventorySubmit();
- }
- scope.removeInventorySubmit = scope.$on('InventorySubmit', function(e, passwords_needed_to_update, extra_html) {
- // After the call to update, kick off the job.
- PromptPasswords({
- scope: scope,
- passwords: passwords_needed_to_update,
- start_url: url,
- form: GroupForm,
- extra_html: extra_html
- });
- });
-
- // Check to see if we have permission to perform the update and if any passwords are needed
- Wait('start');
- Rest.setUrl(url);
- Rest.get()
- .success( function(data, status, headers, config) {
- if (data.can_update) {
- //var extra_html = "
Starting inventory update for " + group_name +
- // " . Please provide the " + group_source + " credentials:
\n";
- scope.$emit('InventorySubmit', data.passwords_needed_to_update);
- }
- else {
- Wait('stop');
- Alert('Permission Denied', 'You do not have access to run the update. Please contact your system administrator.',
- 'alert-danger');
- }
- })
- .error( function(data, status, headers, config) {
+ scope.removeHostReloadComplete = scope.$on('HostReloadComplete', function () {
Wait('stop');
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Failed to get inventory_source details. ' + url + 'GET status: ' + status });
+ Alert('Update Started', 'Your request to start the inventory sync process was submitted. Monitor progress ' +
+ 'by clicking the
button.', 'alert-info');
+ if (scope.removeHostReloadComplete) {
+ scope.removeHostReloadComplete();
+ }
});
- };
- }]);
+ if (scope.removeUpdateSubmitted) {
+ scope.removeUpdateSubmitted();
+ }
+ scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function (e, action) {
+ if (action === 'started') {
+ if (scope.refreshGroups) {
+ scope.selected_tree_id = tree_id;
+ scope.selected_group_id = group_id;
+ scope.refreshGroups();
+ } else if (scope.refresh) {
+ scope.refresh();
+ }
+ scope.$emit('HostReloadComplete');
+ }
+ });
+
+ if (scope.removeInventorySubmit) {
+ scope.removeInventorySubmit();
+ }
+ scope.removeInventorySubmit = scope.$on('InventorySubmit', function (e, passwords_needed_to_update, extra_html) {
+ // After the call to update, kick off the job.
+ PromptPasswords({
+ scope: scope,
+ passwords: passwords_needed_to_update,
+ start_url: url,
+ form: GroupForm,
+ extra_html: extra_html
+ });
+ });
+
+ // Check to see if we have permission to perform the update and if any passwords are needed
+ Wait('start');
+ Rest.setUrl(url);
+ Rest.get()
+ .success(function (data) {
+ if (data.can_update) {
+ //var extra_html = "
Starting inventory update for " + group_name +
+ // " . Please provide the " + group_source + " credentials:
\n";
+ scope.$emit('InventorySubmit', data.passwords_needed_to_update);
+ } else {
+ Wait('stop');
+ Alert('Permission Denied', 'You do not have access to run the update. Please contact your system administrator.',
+ 'alert-danger');
+ }
+ })
+ .error(function (data, status) {
+ Wait('stop');
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
+ msg: 'Failed to get inventory_source details. ' + url + 'GET status: ' + status });
+ });
+ };
+ }
+]);
\ No newline at end of file
diff --git a/awx/ui/static/js/helpers/Jobs.js b/awx/ui/static/js/helpers/Jobs.js
index 29e2d76f06..0ac79b2560 100644
--- a/awx/ui/static/js/helpers/Jobs.js
+++ b/awx/ui/static/js/helpers/Jobs.js
@@ -4,15 +4,18 @@
* JobsHelper
*
* Routines shared by job related controllers
- *
+ *
*/
+'use strict';
+
angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinition', 'InventoryHelper'])
- .factory('JobStatusToolTip', [ function() {
- return function(status) {
- var toolTip;
- switch (status) {
+.factory('JobStatusToolTip', [
+ function () {
+ return function (status) {
+ var toolTip;
+ switch (status) {
case 'successful':
case 'success':
toolTip = 'There were no failed tasks.';
@@ -35,118 +38,124 @@ angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinitio
case 'running':
toolTip = 'Playbook tasks executing.';
break;
- }
- return toolTip;
+ }
+ return toolTip;
};
- }])
+ }
+])
- .factory('ShowJobSummary', ['Rest', 'Wait', 'GetBasePath', 'FormatDate', 'ProcessErrors', 'GenerateForm', 'JobSummary',
+.factory('ShowJobSummary', ['Rest', 'Wait', 'GetBasePath', 'FormatDate', 'ProcessErrors', 'GenerateForm', 'JobSummary',
'WatchInventoryWindowResize',
- function(Rest, Wait, GetBasePath, FormatDate, ProcessErrors, GenerateForm, JobSummary, WatchInventoryWindowResize) {
- return function(params) {
- // Display status info in a modal dialog- called from inventory edit page
-
- var job_id = params.job_id;
+ function (Rest, Wait, GetBasePath, FormatDate, ProcessErrors, GenerateForm, JobSummary, WatchInventoryWindowResize) {
+ return function (params) {
+ // Display status info in a modal dialog- called from inventory edit page
- var generator = GenerateForm;
- var form = JobSummary;
-
- // Using jquery dialog for its expandable property
-
- var html = '
\n';
-
- $('#inventory-modal-container').empty().append(html);
- var scope = generator.inject(form, { mode: 'edit', id: 'form-container', breadCrumbs: false, related: false });
-
- // Set modal dimensions based on viewport width
- var ww = $(document).width();
- var wh = $('body').height();
- var x, y, maxrows;
- if (ww > 1199) {
- // desktop
- x = 675;
- y = (750 > wh) ? wh - 20 : 750;
- maxrows = 20;
- }
- else if (ww <= 1199 && ww >= 768) {
- x = 550;
- y = (620 > wh) ? wh - 15 : 620;
- maxrows = 15;
- }
- else {
- x = (ww - 20);
- y = (500 > wh) ? wh : 500;
- maxrows = 10;
- }
-
- // Create the modal
- $('#status-modal-dialog').dialog({
- buttons: { 'OK': function() { $( this ).dialog( 'close' ); } },
- modal: true,
- width: x,
- height: y,
- autoOpen: false,
- create: function () {
- // fix the close button
- $('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-titlebar button')
- .empty().attr({ 'class': 'close' }).text('x');
- // fix the OK button
- $('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-buttonset button:first')
- .attr({ 'class': 'btn btn-primary' });
- },
- resizeStop: function() {
- // for some reason, after resizing dialog the form and fields (the content) doesn't expand to 100%
- var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]');
- var content = dialog.find('#status-modal-dialog');
- content.width( dialog.width() - 28 );
- },
- close: function() {
- // Destroy on close
- $('.tooltip').each( function() {
- // Remove any lingering tooltip
elements
- $(this).remove();
- });
- $('.popover').each(function() {
- // remove lingering popover
elements
- $(this).remove();
- });
- $('#status-modal-dialog').dialog('destroy');
- $('#inventory-modal-container').empty();
- WatchInventoryWindowResize();
- },
- open: function() {
- Wait('stop');
- }
- });
-
- function calcRows (content) {
- var n = content.match(/\n/g);
- var rows = (n) ? n.length : 1;
- return (rows > maxrows) ? 20 : rows;
+ var job_id = params.job_id,
+ generator = GenerateForm,
+ form = JobSummary,
+ scope, ww, wh, x, y, maxrows, url, html;
+
+ html = '
\n';
+
+ $('#inventory-modal-container').empty().append(html);
+
+ scope = generator.inject(form, { mode: 'edit', id: 'form-container', breadCrumbs: false, related: false });
+
+ // Set modal dimensions based on viewport width
+ ww = $(document).width();
+ wh = $('body').height();
+ if (ww > 1199) {
+ // desktop
+ x = 675;
+ y = (750 > wh) ? wh - 20 : 750;
+ maxrows = 20;
+ } else if (ww <= 1199 && ww >= 768) {
+ x = 550;
+ y = (620 > wh) ? wh - 15 : 620;
+ maxrows = 15;
+ } else {
+ x = (ww - 20);
+ y = (500 > wh) ? wh : 500;
+ maxrows = 10;
}
- Wait('start');
- var url = GetBasePath('jobs') + job_id + '/';
- Rest.setUrl(url);
- Rest.get()
- .success( function(data) {
- scope.id = data.id;
- scope.name = data.name;
- scope.status = data.status;
- scope.result_stdout = data.result_stdout;
- scope.result_traceback = data.result_traceback;
- scope.stdout_rows = calcRows(scope.result_stdout);
- scope.traceback_rows = calcRows(scope.result_traceback);
- var cDate = new Date(data.created);
- scope.created = FormatDate(cDate);
- $('#status-modal-dialog').dialog('open');
+ // Create the modal
+ $('#status-modal-dialog').dialog({
+ buttons: {
+ 'OK': function () {
+ $(this).dialog('close');
+ }
+ },
+ modal: true,
+ width: x,
+ height: y,
+ autoOpen: false,
+ create: function () {
+ // fix the close button
+ $('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-titlebar button')
+ .empty().attr({
+ 'class': 'close'
+ }).text('x');
+ // fix the OK button
+ $('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-buttonset button:first')
+ .attr({
+ 'class': 'btn btn-primary'
+ });
+ },
+ resizeStop: function () {
+ // for some reason, after resizing dialog the form and fields (the content) doesn't expand to 100%
+ var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]'),
+ content = dialog.find('#status-modal-dialog');
+ content.width(dialog.width() - 28);
+ },
+ close: function () {
+ // Destroy on close
+ $('.tooltip').each(function () {
+ // Remove any lingering tooltip
elements
+ $(this).remove();
+ });
+ $('.popover').each(function () {
+ // remove lingering popover
elements
+ $(this).remove();
+ });
+ $('#status-modal-dialog').dialog('destroy');
+ $('#inventory-modal-container').empty();
+ WatchInventoryWindowResize();
+ },
+ open: function () {
+ Wait('stop');
+ }
+ });
+
+ function calcRows(content) {
+ var n = content.match(/\n/g),
+ rows = (n) ? n.length : 1;
+ return (rows > maxrows) ? 20 : rows;
+ }
+
+ Wait('start');
+ url = GetBasePath('jobs') + job_id + '/';
+ Rest.setUrl(url);
+ Rest.get()
+ .success(function (data) {
+ var cDate;
+ scope.id = data.id;
+ scope.name = data.name;
+ scope.status = data.status;
+ scope.result_stdout = data.result_stdout;
+ scope.result_traceback = data.result_traceback;
+ scope.stdout_rows = calcRows(scope.result_stdout);
+ scope.traceback_rows = calcRows(scope.result_traceback);
+ cDate = new Date(data.created);
+ scope.created = FormatDate(cDate);
+ $('#status-modal-dialog').dialog('open');
})
- .error( function(data, status) {
- ProcessErrors(scope, data, status, null,
- { hdr: 'Error!', msg: 'Attempt to load job failed. GET returned status: ' + status });
+ .error(function (data, status) {
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
+ msg: 'Attempt to load job failed. GET returned status: ' + status });
});
};
- }]);
-
+ }
+]);
\ No newline at end of file
diff --git a/awx/ui/static/js/helpers/Lookup.js b/awx/ui/static/js/helpers/Lookup.js
index 5d3dfc4aab..4286cfe3ff 100644
--- a/awx/ui/static/js/helpers/Lookup.js
+++ b/awx/ui/static/js/helpers/Lookup.js
@@ -3,7 +3,7 @@
*
* LookupHelper
* Build a lookup dialog
- *
+ *
* LookUpInit( {
* scope: