Merge pull request #66 from joefiorini/broccoli-build

Improved build workflow for UI client
This commit is contained in:
Joe Fiorini
2015-02-09 09:18:07 -05:00
359 changed files with 17851 additions and 417985 deletions

7
.gitignore vendored
View File

@@ -15,6 +15,7 @@ awx/tower_warnings.log
tower/tower_warnings.log tower/tower_warnings.log
celerybeat-schedule celerybeat-schedule
awx/ui/static/docs awx/ui/static/docs
awx/ui/static/dist
# Python & setuptools # Python & setuptools
__pycache__ __pycache__
@@ -28,9 +29,14 @@ tar-build
# JavaScript # JavaScript
/Gruntfile.js /Gruntfile.js
/Brocfile.js
/bower.json /bower.json
/package.json /package.json
node_modules/** node_modules/**
/tmp
# UI build debugging
/DEBUG-*
# Testing # Testing
.coverage .coverage
@@ -62,3 +68,4 @@ setup/inventory
env/* env/*
nohup.out nohup.out
reports reports

View File

@@ -8,6 +8,7 @@
"latedef": "nofunc", "latedef": "nofunc",
"noarg": true, "noarg": true,
"nonew": true, "nonew": true,
"maxerr": 10000,
"notypeof": true, "notypeof": true,
"globals": { "globals": {
"angular":false, "angular":false,

View File

@@ -3,7 +3,7 @@ recursive-include awx/static *.ico
recursive-include awx/templates *.html recursive-include awx/templates *.html
recursive-include awx/api/templates *.md recursive-include awx/api/templates *.md
recursive-include awx/ui *.html recursive-include awx/ui *.html
recursive-include awx/ui/static *.css *.ico *.png *.gif *.jpg recursive-include awx/ui/static *.css *.ico *.png *.gif *.jpg *.gz
recursive-include awx/ui/static *.eot *.svg *.ttf *.woff *.otf recursive-include awx/ui/static *.eot *.svg *.ttf *.woff *.otf
recursive-include awx/ui/static/lib * recursive-include awx/ui/static/lib *
recursive-include awx/playbooks *.yml recursive-include awx/playbooks *.yml
@@ -16,7 +16,8 @@ recursive-exclude awx/api/tests *
recursive-exclude awx/main/tests * recursive-exclude awx/main/tests *
recursive-exclude awx/ui/static/lib/ansible * recursive-exclude awx/ui/static/lib/ansible *
recursive-exclude awx/settings local_settings.py* recursive-exclude awx/settings local_settings.py*
include awx/ui/static/js/awx.min.js include awx/ui/static/dist/tower.concat.js
include awx/ui/static/dist/tower.concat.js.gz
include awx/ui/static/js/config.js include awx/ui/static/js/config.js
include tools/scripts/request_tower_configuration.sh include tools/scripts/request_tower_configuration.sh
include tools/scripts/ansible-tower include tools/scripts/ansible-tower

View File

@@ -3,6 +3,7 @@ SITELIB=$(shell $(PYTHON) -c "from distutils.sysconfig import get_python_lib; pr
OFFICIAL ?= no OFFICIAL ?= no
PACKER ?= packer PACKER ?= packer
GRUNT ?= $(shell [ -t 0 ] && echo "grunt" || echo "grunt --no-color") GRUNT ?= $(shell [ -t 0 ] && echo "grunt" || echo "grunt --no-color")
BROCCOLI ?= ./node_modules/.bin/broccoli
# Get the branch information from git # Get the branch information from git
GIT_DATE := $(shell git log -n 1 --format="%ai") GIT_DATE := $(shell git log -n 1 --format="%ai")
@@ -84,12 +85,12 @@ clean-deb:
# Remove grunt build files # Remove grunt build files
clean-grunt: clean-grunt:
rm -f package.json Gruntfile.js bower.json rm -f package.json Gruntfile.js Brocfile.js bower.json
rm -rf node_modules rm -rf node_modules
# Remove UI build files # Remove UI build files
clean-ui: clean-ui:
rm -f awx/ui/static/{js,css}/awx*.{js,css} rm -rf awx/ui/static/dist
rm -rf awx/ui/static/docs rm -rf awx/ui/static/docs
# Remove temporary build files, compiled Python files. # Remove temporary build files, compiled Python files.
@@ -261,6 +262,9 @@ test_jenkins:
Gruntfile.js: Gruntfile.js:
cp packaging/grunt/$@ $@ cp packaging/grunt/$@ $@
Brocfile.js:
cp packaging/grunt/$@ $@
bower.json: bower.json:
cp packaging/grunt/$@ $@ cp packaging/grunt/$@ $@
@@ -268,12 +272,14 @@ package.json:
sed -e 's#%NAME%#$(NAME)#;s#%VERSION%#$(VERSION)#;s#%GIT_REMOTE_URL%#$(GIT_REMOTE_URL)#;' packaging/grunt/package.template > $@ sed -e 's#%NAME%#$(NAME)#;s#%VERSION%#$(VERSION)#;s#%GIT_REMOTE_URL%#$(GIT_REMOTE_URL)#;' packaging/grunt/package.template > $@
# Update local npm install # Update local npm install
node_modules: Gruntfile.js bower.json package.json node_modules: Gruntfile.js Brocfile.js bower.json package.json
npm install npm install
devjs: node_modules clean-ui
$(BROCCOLI) build awx/ui/static/dist -- --debug
# Build minified JS/CSS. # Build minified JS/CSS.
minjs: node_modules minjs: node_modules clean-ui
$(GRUNT) $(BROCCOLI) build awx/ui/static/dist -- --silent --no-debug --no-tests --compress
# Check .js files for errors and lint # Check .js files for errors and lint
jshint: node_modules jshint: node_modules

View File

@@ -7,8 +7,7 @@
* *
*/ */
var urlPrefix, var urlPrefix;
$AnsibleConfig;
if ($basePath) { if ($basePath) {
urlPrefix = $basePath; urlPrefix = $basePath;
@@ -18,17 +17,46 @@ if ($basePath) {
urlPrefix = $basePath; urlPrefix = $basePath;
} }
import 'tower/helpers';
import 'tower/forms';
import 'tower/lists';
import 'tower/widgets';
import 'tower/help';
import {Home, HomeGroups, HomeHosts} from 'tower/controllers/Home';
import {SocketsController} from 'tower/controllers/Sockets';
import {Authenticate} from 'tower/controllers/Authentication';
import {CredentialsAdd, CredentialsEdit, CredentialsList} from 'tower/controllers/Credentials';
import {JobsListController} from 'tower/controllers/Jobs';
import {PortalController} from 'tower/controllers/Portal';
angular.module('Tower', [ import dataServices from 'tower/services/_data-services';
import dashboardGraphs from 'tower/directives/_dashboard-graphs';
import {JobDetailController} from 'tower/controllers/JobDetail';
import {JobStdoutController} from 'tower/controllers/JobStdout';
import {JobTemplatesList, JobTemplatesAdd, JobTemplatesEdit} from 'tower/controllers/JobTemplates';
import {ScheduleEditController} from 'tower/controllers/Schedules';
import {ProjectsList, ProjectsAdd, ProjectsEdit} from 'tower/controllers/Projects';
import {OrganizationsList, OrganizationsAdd, OrganizationsEdit} from 'tower/controllers/Organizations';
import {InventoriesList, InventoriesAdd, InventoriesEdit} from 'tower/controllers/Inventories';
import {AdminsList} from 'tower/controllers/Admins';
import {UsersList, UsersAdd, UsersEdit} from 'tower/controllers/Users';
import {TeamsList, TeamsAdd, TeamsEdit} from 'tower/controllers/Teams';
import {PermissionsAdd, PermissionsList, PermissionsEdit} from 'tower/controllers/Permissions';
var tower = angular.module('Tower', [
'ngRoute', 'ngRoute',
'ngSanitize', 'ngSanitize',
'ngCookies', 'ngCookies',
'RestServices', 'RestServices',
'DataServices', dataServices.name,
'DashboardGraphs', dashboardGraphs.name,
'AuthService', 'AuthService',
'Utilities', 'Utilities',
'LicenseHelper', 'License',
'OrganizationFormDefinition', 'OrganizationFormDefinition',
'UserFormDefinition', 'UserFormDefinition',
'FormGenerator', 'FormGenerator',
@@ -138,267 +166,267 @@ angular.module('Tower', [
when('/jobs', { when('/jobs', {
templateUrl: urlPrefix + 'partials/jobs.html', templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobsListController' controller: JobsListController
}). }).
when('/portal', { when('/portal', {
templateUrl: urlPrefix + 'partials/portal.html', templateUrl: urlPrefix + 'partials/portal.html',
controller: 'PortalController' controller: PortalController
}). }).
when('/jobs/:id', { when('/jobs/:id', {
templateUrl: urlPrefix + 'partials/job_detail.html', templateUrl: urlPrefix + 'partials/job_detail.html',
controller: 'JobDetailController' controller: JobDetailController
}). }).
when('/jobs/:id/stdout', { when('/jobs/:id/stdout', {
templateUrl: urlPrefix + 'partials/job_stdout.html', templateUrl: urlPrefix + 'partials/job_stdout.html',
controller: 'JobStdoutController' controller: JobStdoutController
}). }).
when('/job_templates', { when('/job_templates', {
templateUrl: urlPrefix + 'partials/job_templates.html', templateUrl: urlPrefix + 'partials/job_templates.html',
controller: 'JobTemplatesList' controller: JobTemplatesList
}). }).
when('/job_templates/add', { when('/job_templates/add', {
templateUrl: urlPrefix + 'partials/job_templates.html', templateUrl: urlPrefix + 'partials/job_templates.html',
controller: 'JobTemplatesAdd' controller: JobTemplatesAdd
}). }).
when('/job_templates/:template_id', { when('/job_templates/:template_id', {
templateUrl: urlPrefix + 'partials/job_templates.html', templateUrl: urlPrefix + 'partials/job_templates.html',
controller: 'JobTemplatesEdit' controller: JobTemplatesEdit
}). }).
when('/job_templates/:id/schedules', { when('/job_templates/:id/schedules', {
templateUrl: urlPrefix + 'partials/schedule_detail.html', templateUrl: urlPrefix + 'partials/schedule_detail.html',
controller: 'ScheduleEditController' controller: ScheduleEditController
}). }).
when('/projects', { when('/projects', {
templateUrl: urlPrefix + 'partials/projects.html', templateUrl: urlPrefix + 'partials/projects.html',
controller: 'ProjectsList' controller: ProjectsList
}). }).
when('/projects/add', { when('/projects/add', {
templateUrl: urlPrefix + 'partials/projects.html', templateUrl: urlPrefix + 'partials/projects.html',
controller: 'ProjectsAdd' controller: ProjectsAdd
}). }).
when('/projects/:id', { when('/projects/:id', {
templateUrl: urlPrefix + 'partials/projects.html', templateUrl: urlPrefix + 'partials/projects.html',
controller: 'ProjectsEdit' controller: ProjectsEdit
}). }).
when('/projects/:id/schedules', { when('/projects/:id/schedules', {
templateUrl: urlPrefix + 'partials/schedule_detail.html', templateUrl: urlPrefix + 'partials/schedule_detail.html',
controller: 'ScheduleEditController' controller: ScheduleEditController
}). }).
when('/projects/:project_id/organizations', { when('/projects/:project_id/organizations', {
templateUrl: urlPrefix + 'partials/projects.html', templateUrl: urlPrefix + 'partials/projects.html',
controller: 'OrganizationsList' controller: OrganizationsList
}). }).
when('/projects/:project_id/organizations/add', { when('/projects/:project_id/organizations/add', {
templateUrl: urlPrefix + 'partials/projects.html', templateUrl: urlPrefix + 'partials/projects.html',
controller: 'OrganizationsAdd' controller: OrganizationsAdd
}). }).
when('/inventories', { when('/inventories', {
templateUrl: urlPrefix + 'partials/inventories.html', templateUrl: urlPrefix + 'partials/inventories.html',
controller: 'InventoriesList' controller: InventoriesList
}). }).
when('/inventories/add', { when('/inventories/add', {
templateUrl: urlPrefix + 'partials/inventories.html', templateUrl: urlPrefix + 'partials/inventories.html',
controller: 'InventoriesAdd' controller: InventoriesAdd
}). }).
when('/inventories/:inventory_id', { when('/inventories/:inventory_id', {
templateUrl: urlPrefix + 'partials/inventory-edit.html', templateUrl: urlPrefix + 'partials/inventory-edit.html',
controller: 'InventoriesEdit' controller: InventoriesEdit
}). }).
when('/organizations', { when('/organizations', {
templateUrl: urlPrefix + 'partials/organizations.html', templateUrl: urlPrefix + 'partials/organizations.html',
controller: 'OrganizationsList' controller: OrganizationsList
}). }).
when('/organizations/add', { when('/organizations/add', {
templateUrl: urlPrefix + 'partials/organizations.html', templateUrl: urlPrefix + 'partials/organizations.html',
controller: 'OrganizationsAdd' controller: OrganizationsAdd
}). }).
when('/organizations/:organization_id', { when('/organizations/:organization_id', {
templateUrl: urlPrefix + 'partials/organizations.html', templateUrl: urlPrefix + 'partials/organizations.html',
controller: 'OrganizationsEdit' controller: OrganizationsEdit
}). }).
when('/organizations/:organization_id/admins', { when('/organizations/:organization_id/admins', {
templateUrl: urlPrefix + 'partials/organizations.html', templateUrl: urlPrefix + 'partials/organizations.html',
controller: 'AdminsList' controller: AdminsList
}). }).
when('/organizations/:organization_id/users', { when('/organizations/:organization_id/users', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersList' controller: UsersList
}). }).
when('/organizations/:organization_id/users/add', { when('/organizations/:organization_id/users/add', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersAdd' controller: UsersAdd
}). }).
when('/organizations/:organization_id/users/:user_id', { when('/organizations/:organization_id/users/:user_id', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersEdit' controller: UsersEdit
}). }).
when('/teams', { when('/teams', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'TeamsList' controller: TeamsList
}). }).
when('/teams/add', { when('/teams/add', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'TeamsAdd' controller: TeamsAdd
}). }).
when('/teams/:team_id', { when('/teams/:team_id', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'TeamsEdit' controller: TeamsEdit
}). }).
when('/teams/:team_id/permissions/add', { when('/teams/:team_id/permissions/add', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'PermissionsAdd' controller: PermissionsAdd
}). }).
when('/teams/:team_id/permissions', { when('/teams/:team_id/permissions', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'PermissionsList' controller: PermissionsList
}). }).
when('/teams/:team_id/permissions/:permission_id', { when('/teams/:team_id/permissions/:permission_id', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'PermissionsEdit' controller: PermissionsEdit
}). }).
when('/teams/:team_id/users', { when('/teams/:team_id/users', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'UsersList' controller: UsersList
}). }).
when('/teams/:team_id/users/:user_id', { when('/teams/:team_id/users/:user_id', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'UsersEdit' controller: UsersEdit
}). }).
when('/teams/:team_id/projects', { when('/teams/:team_id/projects', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'ProjectsList' controller: ProjectsList
}). }).
when('/teams/:team_id/projects/add', { when('/teams/:team_id/projects/add', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'ProjectsAdd' controller: ProjectsAdd
}). }).
when('/teams/:team_id/projects/:project_id', { when('/teams/:team_id/projects/:project_id', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'ProjectsEdit' controller: ProjectsEdit
}). }).
when('/teams/:team_id/credentials', { when('/teams/:team_id/credentials', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'CredentialsList' controller: CredentialsList
}). }).
when('/teams/:team_id/credentials/add', { when('/teams/:team_id/credentials/add', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'CredentialsAdd' controller: CredentialsAdd
}). }).
when('/teams/:team_id/credentials/:credential_id', { when('/teams/:team_id/credentials/:credential_id', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'CredentialsEdit' controller: CredentialsEdit
}). }).
when('/credentials', { when('/credentials', {
templateUrl: urlPrefix + 'partials/credentials.html', templateUrl: urlPrefix + 'partials/credentials.html',
controller: 'CredentialsList' controller: CredentialsList
}). }).
when('/credentials/add', { when('/credentials/add', {
templateUrl: urlPrefix + 'partials/credentials.html', templateUrl: urlPrefix + 'partials/credentials.html',
controller: 'CredentialsAdd' controller: CredentialsAdd
}). }).
when('/credentials/:credential_id', { when('/credentials/:credential_id', {
templateUrl: urlPrefix + 'partials/credentials.html', templateUrl: urlPrefix + 'partials/credentials.html',
controller: 'CredentialsEdit' controller: CredentialsEdit
}). }).
when('/users', { when('/users', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersList' controller: UsersList
}). }).
when('/users/add', { when('/users/add', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersAdd' controller: UsersAdd
}). }).
when('/users/:user_id', { when('/users/:user_id', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersEdit' controller: UsersEdit
}). }).
when('/users/:user_id/credentials', { when('/users/:user_id/credentials', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: 'CredentialsList' controller: CredentialsList
}). }).
when('/users/:user_id/permissions/add', { when('/users/:user_id/permissions/add', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: 'PermissionsAdd' controller: PermissionsAdd
}). }).
when('/users/:user_id/permissions', { when('/users/:user_id/permissions', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: 'PermissionsList' controller: PermissionsList
}). }).
when('/users/:user_id/permissions/:permission_id', { when('/users/:user_id/permissions/:permission_id', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: 'PermissionsEdit' controller: PermissionsEdit
}). }).
when('/users/:user_id/credentials/add', { when('/users/:user_id/credentials/add', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'CredentialsAdd' controller: CredentialsAdd
}). }).
when('/teams/:user_id/credentials/:credential_id', { when('/teams/:user_id/credentials/:credential_id', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: 'CredentialsEdit' controller: CredentialsEdit
}). }).
when('/login', { when('/login', {
templateUrl: urlPrefix + 'partials/blank.html', templateUrl: urlPrefix + 'partials/blank.html',
controller: 'Authenticate' controller: Authenticate
}). }).
when('/logout', { when('/logout', {
templateUrl: urlPrefix + 'partials/blank.html', templateUrl: urlPrefix + 'partials/blank.html',
controller: 'Authenticate' controller: Authenticate
}). }).
when('/home', { when('/home', {
templateUrl: urlPrefix + 'partials/home.html', templateUrl: urlPrefix + 'partials/home.html',
controller: 'Home', controller: Home,
resolve: { resolve: {
graphData: ['$q', 'jobStatusGraphData', 'hostCountGraphData', function($q, jobStatusGraphData, hostCountGraphData) { graphData: ['$q', 'jobStatusGraphData', 'hostCountGraphData', function($q, jobStatusGraphData, hostCountGraphData) {
return $q.all({ return $q.all({
@@ -411,17 +439,17 @@ angular.module('Tower', [
when('/home/groups', { when('/home/groups', {
templateUrl: urlPrefix + 'partials/subhome.html', templateUrl: urlPrefix + 'partials/subhome.html',
controller: 'HomeGroups' controller: HomeGroups
}). }).
when('/home/hosts', { when('/home/hosts', {
templateUrl: urlPrefix + 'partials/subhome.html', templateUrl: urlPrefix + 'partials/subhome.html',
controller: 'HomeHosts' controller: HomeHosts
}). }).
when('/sockets', { when('/sockets', {
templateUrl: urlPrefix + 'partials/sockets.html', templateUrl: urlPrefix + 'partials/sockets.html',
controller: 'SocketsController' controller: SocketsController
}). }).
otherwise({ otherwise({
@@ -756,3 +784,6 @@ angular.module('Tower', [
LoadConfig(); LoadConfig();
} }
]); ]);
export default tower;

View File

@@ -17,9 +17,9 @@
* Controller functions for ading Admins to an Organization. * Controller functions for ading Admins to an Organization.
* *
*/ */
'use strict';
function AdminsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, AdminList, GenerateList, LoadBreadCrumbs,
export function AdminsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, AdminList, GenerateList, LoadBreadCrumbs,
Prompt, SearchInit, PaginateInit, ReturnToCaller, GetBasePath, SelectionInit) { Prompt, SearchInit, PaginateInit, ReturnToCaller, GetBasePath, SelectionInit) {
var list = AdminList, var list = AdminList,

View File

@@ -57,9 +57,9 @@
* @Usage * @Usage
* This is usage information. * This is usage information.
*/ */
'use strict';
function Authenticate($log, $cookieStore, $compile, $window, $rootScope, $location, Authorization, ToggleClass, Alert, Wait,
export function Authenticate($log, $cookieStore, $compile, $window, $rootScope, $location, Authorization, ToggleClass, Alert, Wait,
Timer, Empty, ClearScope) { Timer, Empty, ClearScope) {
var setLoginFocus, lastPath, sessionExpired, loginAgain, var setLoginFocus, lastPath, sessionExpired, loginAgain,

View File

@@ -11,9 +11,9 @@
* @name controllers.function:Credentials * @name controllers.function:Credentials
* @description This controller's for the credentials page * @description This controller's for the credentials page
*/ */
'use strict';
function CredentialsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, CredentialList,
export function CredentialsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, CredentialList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
ClearScope, ProcessErrors, GetBasePath, SelectionInit, GetChoices, Wait, Stream) { ClearScope, ProcessErrors, GetBasePath, SelectionInit, GetChoices, Wait, Stream) {
@@ -134,7 +134,7 @@ CredentialsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeP
]; ];
function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm, GenerateForm, Rest, Alert, export function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm, GenerateForm, Rest, Alert,
ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateList, SearchInit, PaginateInit, LookUpInit, UserList, TeamList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateList, SearchInit, PaginateInit, LookUpInit, UserList, TeamList,
GetBasePath, GetChoices, Empty, KindChange, OwnerChange, LoginMethodChange, FormSave) { GetBasePath, GetChoices, Empty, KindChange, OwnerChange, LoginMethodChange, FormSave) {
@@ -286,7 +286,7 @@ CredentialsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log
]; ];
function CredentialsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm, GenerateForm, Rest, Alert, export function CredentialsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm, GenerateForm, Rest, Alert,
ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, Prompt, GetBasePath, GetChoices, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, Prompt, GetBasePath, GetChoices,
KindChange, UserList, TeamList, LookUpInit, Empty, OwnerChange, LoginMethodChange, FormSave, Stream, Wait) { KindChange, UserList, TeamList, LookUpInit, Empty, OwnerChange, LoginMethodChange, FormSave, Stream, Wait) {

View File

@@ -14,7 +14,7 @@
* @name controllers.function:Home * @name controllers.function:Home
* @description This controller's for the dashboard * @description This controller's for the dashboard
*/ */
'use strict';
/** /**
* @ngdoc method * @ngdoc method
@@ -25,7 +25,8 @@
* Host count graph should only be loaded if the user is a super user * Host count graph should only be loaded if the user is a super user
* *
*/ */
function Home($scope, $compile, $routeParams, $rootScope, $location, $log, Wait, DashboardCounts, DashboardJobs,
export function Home($scope, $compile, $routeParams, $rootScope, $location, $log, Wait, DashboardCounts, DashboardJobs,
ClearScope, Stream, Rest, GetBasePath, ProcessErrors, Button, $window, graphData){ ClearScope, Stream, Rest, GetBasePath, ProcessErrors, Button, $window, graphData){
ClearScope('home'); ClearScope('home');
@@ -136,7 +137,7 @@ Home.$inject = ['$scope', '$compile', '$routeParams', '$rootScope', '$location',
* @description This controls the 'home/groups' page that is loaded from the dashboard * @description This controls the 'home/groups' page that is loaded from the dashboard
* *
*/ */
function HomeGroups($log, $scope, $filter, $compile, $location, $routeParams, LogViewer, HomeGroupList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, export function HomeGroups($log, $scope, $filter, $compile, $location, $routeParams, LogViewer, HomeGroupList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
GetBasePath, SearchInit, PaginateInit, FormatDate, GetHostsStatusMsg, GetSyncStatusMsg, ViewUpdateStatus, Stream, GroupsEdit, Wait, GetBasePath, SearchInit, PaginateInit, FormatDate, GetHostsStatusMsg, GetSyncStatusMsg, ViewUpdateStatus, Stream, GroupsEdit, Wait,
Alert, Rest, Empty, InventoryUpdate, Find, GroupsCancelUpdate, Store, Socket) { Alert, Rest, Empty, InventoryUpdate, Find, GroupsCancelUpdate, Store, Socket) {
@@ -572,7 +573,8 @@ HomeGroups.$inject = ['$log', '$scope', '$filter', '$compile', '$location', '$ro
* @description This loads the page for 'home/hosts' * @description This loads the page for 'home/hosts'
* *
*/ */
function HomeHosts($scope, $location, $routeParams, HomeHostList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
export function HomeHosts($scope, $location, $routeParams, HomeHostList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
GetBasePath, SearchInit, PaginateInit, FormatDate, SetStatus, ToggleHostEnabled, HostsEdit, Stream, Find, ShowJobSummary, ViewJob) { GetBasePath, SearchInit, PaginateInit, FormatDate, SetStatus, ToggleHostEnabled, HostsEdit, Stream, Find, ShowJobSummary, ViewJob) {
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior

View File

@@ -12,9 +12,9 @@
* @name controllers.function:Inventories * @name controllers.function:Inventories
* @description This controller's for the Inventory page * @description This controller's for the Inventory page
*/ */
'use strict';
function InventoriesList($scope, $rootScope, $location, $log, $routeParams, $compile, $filter, Rest, Alert, InventoryList, GenerateList,
export function InventoriesList($scope, $rootScope, $location, $log, $routeParams, $compile, $filter, Rest, Alert, InventoryList, GenerateList,
LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, Wait, Stream, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, Wait, Stream,
EditInventoryProperties, Find, Empty, LogViewer) { EditInventoryProperties, Find, Empty, LogViewer) {
@@ -368,7 +368,7 @@ InventoriesList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeP
]; ];
function InventoriesAdd($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm, GenerateForm, Rest, export function InventoriesAdd($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm, GenerateForm, Rest,
Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateList, OrganizationList, SearchInit, PaginateInit, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateList, OrganizationList, SearchInit, PaginateInit,
LookUpInit, GetBasePath, ParseTypeChange, Wait, ToJSON) { LookUpInit, GetBasePath, ParseTypeChange, Wait, ToJSON) {
@@ -478,7 +478,7 @@ InventoriesAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log
function InventoriesEdit ($log, $scope, $location, $routeParams, $compile, GenerateList, ClearScope, Empty, Wait, Rest, Alert, LoadBreadCrumbs, GetBasePath, ProcessErrors, export function InventoriesEdit ($log, $scope, $location, $routeParams, $compile, GenerateList, ClearScope, Empty, Wait, Rest, Alert, LoadBreadCrumbs, GetBasePath, ProcessErrors,
Breadcrumbs, InventoryGroups, InjectHosts, Find, HostsReload, SearchInit, PaginateInit, GetSyncStatusMsg, GetHostsStatusMsg, GroupsEdit, InventoryUpdate, Breadcrumbs, InventoryGroups, InjectHosts, Find, HostsReload, SearchInit, PaginateInit, GetSyncStatusMsg, GetHostsStatusMsg, GroupsEdit, InventoryUpdate,
GroupsCancelUpdate, ViewUpdateStatus, GroupsDelete, Store, HostsEdit, HostsDelete, EditInventoryProperties, ToggleHostEnabled, Stream, ShowJobSummary, GroupsCancelUpdate, ViewUpdateStatus, GroupsDelete, Store, HostsEdit, HostsDelete, EditInventoryProperties, ToggleHostEnabled, Stream, ShowJobSummary,
InventoryGroupsHelp, HelpDialog, ViewJob, WatchInventoryWindowResize, GetHostContainerRows, GetGroupContainerRows, GetGroupContainerHeight, InventoryGroupsHelp, HelpDialog, ViewJob, WatchInventoryWindowResize, GetHostContainerRows, GetGroupContainerRows, GetGroupContainerHeight,

View File

@@ -9,9 +9,9 @@
* @name controllers.function:JobDetail * @name controllers.function:JobDetail
* @description This controller's for the Job Detail Page * @description This controller's for the Job Detail Page
*/ */
'use strict';
function JobDetailController ($location, $rootScope, $scope, $compile, $routeParams, $log, ClearScope, Breadcrumbs, LoadBreadCrumbs, GetBasePath, Wait, Rest,
export function JobDetailController ($location, $rootScope, $scope, $compile, $routeParams, $log, ClearScope, Breadcrumbs, LoadBreadCrumbs, GetBasePath, Wait, Rest,
ProcessErrors, SelectPlay, SelectTask, Socket, GetElapsed, DrawGraph, LoadHostSummary, ReloadHostSummaryList, JobIsFinished, SetTaskStyles, DigestEvent, ProcessErrors, SelectPlay, SelectTask, Socket, GetElapsed, DrawGraph, LoadHostSummary, ReloadHostSummaryList, JobIsFinished, SetTaskStyles, DigestEvent,
UpdateDOM, EventViewer, DeleteJob, PlaybookRun, HostEventsViewer, LoadPlays, LoadTasks, LoadHosts, HostsEdit, ParseVariableString) { UpdateDOM, EventViewer, DeleteJob, PlaybookRun, HostEventsViewer, LoadPlays, LoadTasks, LoadHosts, HostsEdit, ParseVariableString) {

View File

@@ -12,9 +12,9 @@
* @name controllers.function:JobEvent * @name controllers.function:JobEvent
* @description This controller's for the job event page * @description This controller's for the job event page
*/ */
'use strict';
function JobEventsList($sce, $filter, $scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobEventList, GenerateList,
export function JobEventsList($sce, $filter, $scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobEventList, GenerateList,
LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, LookUpInit, ToggleChildren, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, LookUpInit, ToggleChildren,
FormatDate, EventView, Refresh, Wait) { FormatDate, EventView, Refresh, Wait) {
@@ -260,7 +260,7 @@ JobEventsList.$inject = ['$sce', '$filter', '$scope', '$rootScope', '$location',
'GetBasePath', 'LookUpInit', 'ToggleChildren', 'FormatDate', 'EventView', 'Refresh', 'Wait' 'GetBasePath', 'LookUpInit', 'ToggleChildren', 'FormatDate', 'EventView', 'Refresh', 'Wait'
]; ];
function JobEventsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobEventsForm, GenerateForm, export function JobEventsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobEventsForm, GenerateForm,
Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, FormatDate, EventView, Wait) { Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, FormatDate, EventView, Wait) {
ClearScope(); ClearScope();

View File

@@ -12,9 +12,9 @@
* @name controllers.function:JobHosts * @name controllers.function:JobHosts
* @description This controller's for the job hosts page * @description This controller's for the job hosts page
*/ */
'use strict';
function JobHostSummaryList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobHostList, GenerateList,
export function JobHostSummaryList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobHostList, GenerateList,
LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, Refresh, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, Refresh,
JobStatusToolTip) { JobStatusToolTip) {

View File

@@ -9,9 +9,9 @@
* @name controllers.function:JobStdout * @name controllers.function:JobStdout
* @description This controller's for the standard out page that can be displayed when a job runs * @description This controller's for the standard out page that can be displayed when a job runs
*/ */
'use strict';
function JobStdoutController ($log, $rootScope, $scope, $compile, $routeParams, ClearScope, GetBasePath, Wait, Rest, ProcessErrors, Socket) {
export function JobStdoutController ($log, $rootScope, $scope, $compile, $routeParams, ClearScope, GetBasePath, Wait, Rest, ProcessErrors, Socket) {
ClearScope(); ClearScope();

View File

@@ -12,9 +12,9 @@
* @name controllers.function:JobTemplate * @name controllers.function:JobTemplate
* @description This controller's for the Job Template page * @description This controller's for the Job Template page
*/ */
'use strict';
function JobTemplatesList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobTemplateList,
export function JobTemplatesList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobTemplateList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors,
GetBasePath, JobTemplateForm, CredentialList, LookUpInit, PlaybookRun, Wait, Stream, CreateDialog, $compile) { GetBasePath, JobTemplateForm, CredentialList, LookUpInit, PlaybookRun, Wait, Stream, CreateDialog, $compile) {
@@ -246,7 +246,7 @@ JobTemplatesList.$inject = ['$scope', '$rootScope', '$location', '$log', '$route
'PlaybookRun', 'Wait', 'Stream', 'CreateDialog' , '$compile' 'PlaybookRun', 'Wait', 'Stream', 'CreateDialog' , '$compile'
]; ];
function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm, export function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GetBasePath, GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GetBasePath,
InventoryList, CredentialList, ProjectList, LookUpInit, md5Setup, ParseTypeChange, Wait, Empty, ToJSON, InventoryList, CredentialList, ProjectList, LookUpInit, md5Setup, ParseTypeChange, Wait, Empty, ToJSON,
CallbackHelpInit, SurveyControllerInit, Prompt) { CallbackHelpInit, SurveyControllerInit, Prompt) {
@@ -551,7 +551,7 @@ JobTemplatesAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$lo
]; ];
function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm, GenerateForm, Rest, export function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm, GenerateForm, Rest,
Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList,
CredentialList, ProjectList, LookUpInit, GetBasePath, md5Setup, ParseTypeChange, JobStatusToolTip, FormatDate, CredentialList, ProjectList, LookUpInit, GetBasePath, md5Setup, ParseTypeChange, JobStatusToolTip, FormatDate,
Wait, Stream, Empty, Prompt, ParseVariableString, ToJSON, SchedulesControllerInit, JobsControllerInit, JobsListUpdate, Wait, Stream, Empty, Prompt, ParseVariableString, ToJSON, SchedulesControllerInit, JobsControllerInit, JobsListUpdate,

View File

@@ -12,9 +12,9 @@
* @name controllers.function:Jobs * @name controllers.function:Jobs
* @description This controller's for the jobs page * @description This controller's for the jobs page
*/ */
'use strict';
function JobsListController ($rootScope, $log, $scope, $compile, $routeParams, ClearScope, Breadcrumbs, LoadBreadCrumbs, LoadSchedulesScope,
export function JobsListController ($rootScope, $log, $scope, $compile, $routeParams, ClearScope, Breadcrumbs, LoadBreadCrumbs, LoadSchedulesScope,
LoadJobsScope, RunningJobsList, CompletedJobsList, QueuedJobsList, ScheduledJobsList, GetChoices, GetBasePath, Wait, Socket) { LoadJobsScope, RunningJobsList, CompletedJobsList, QueuedJobsList, ScheduledJobsList, GetChoices, GetBasePath, Wait, Socket) {
ClearScope(); ClearScope();

View File

@@ -12,9 +12,9 @@
* @name controllers.function:Organizations * @name controllers.function:Organizations
* @description This controller's for the Organizations page * @description This controller's for the Organizations page
*/ */
'use strict';
function OrganizationsList($routeParams, $scope, $rootScope, $location, $log, Rest, Alert, LoadBreadCrumbs, Prompt,
export function OrganizationsList($routeParams, $scope, $rootScope, $location, $log, Rest, Alert, LoadBreadCrumbs, Prompt,
GenerateList, OrganizationList, SearchInit, PaginateInit, ClearScope, ProcessErrors, GetBasePath, SelectionInit, Wait, Stream) { GenerateList, OrganizationList, SearchInit, PaginateInit, ClearScope, ProcessErrors, GetBasePath, SelectionInit, Wait, Stream) {
ClearScope(); ClearScope();
@@ -101,7 +101,7 @@ OrganizationsList.$inject = ['$routeParams', '$scope', '$rootScope', '$location'
]; ];
function OrganizationsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm, export function OrganizationsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath,
ReturnToCaller, Wait) { ReturnToCaller, Wait) {
@@ -152,7 +152,7 @@ OrganizationsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$l
]; ];
function OrganizationsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm, GenerateForm, Rest, export function OrganizationsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm, GenerateForm, Rest,
Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, Prompt, ClearScope, GetBasePath, Wait, Stream) { Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, Prompt, ClearScope, GetBasePath, Wait, Stream) {
ClearScope(); ClearScope();

View File

@@ -12,9 +12,9 @@
* @name controllers.function:Permissions * @name controllers.function:Permissions
* @description This controller's for permissions * @description This controller's for permissions
*/ */
'use strict';
function PermissionsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, PermissionList,
export function PermissionsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, PermissionList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors,
GetBasePath, CheckAccess, Wait) { GetBasePath, CheckAccess, Wait) {
@@ -102,7 +102,7 @@ PermissionsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeP
]; ];
function PermissionsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm, export function PermissionsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope,
GetBasePath, ReturnToCaller, InventoryList, ProjectList, LookUpInit, CheckAccess, GetBasePath, ReturnToCaller, InventoryList, ProjectList, LookUpInit, CheckAccess,
Wait, PermissionCategoryChange) { Wait, PermissionCategoryChange) {
@@ -199,7 +199,7 @@ PermissionsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log
]; ];
function PermissionsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm, export function PermissionsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, Prompt, GetBasePath, GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, Prompt, GetBasePath,
InventoryList, ProjectList, LookUpInit, CheckAccess, Wait, PermissionCategoryChange) { InventoryList, ProjectList, LookUpInit, CheckAccess, Wait, PermissionCategoryChange) {

View File

@@ -14,7 +14,7 @@
* @name controllers.function:Portal * @name controllers.function:Portal
* @description This controller's for portal mode * @description This controller's for portal mode
*/ */
'use strict';
/** /**
* @ngdoc method * @ngdoc method
@@ -24,7 +24,7 @@
* *
* *
*/ */
function PortalController($scope, $compile, $routeParams, $rootScope, $location, $log, Wait, ClearScope, Stream, Rest, GetBasePath, ProcessErrors, export function PortalController($scope, $compile, $routeParams, $rootScope, $location, $log, Wait, ClearScope, Stream, Rest, GetBasePath, ProcessErrors,
Button, PortalJobsWidget, GenerateList, PortalJobTemplateList, SearchInit, PaginateInit, PlaybookRun){ Button, PortalJobsWidget, GenerateList, PortalJobTemplateList, SearchInit, PaginateInit, PlaybookRun){
ClearScope('portal'); ClearScope('portal');

View File

@@ -12,9 +12,9 @@
* @name controllers.function:Projects * @name controllers.function:Projects
* @description This controller's for the projects page * @description This controller's for the projects page
*/ */
'use strict';
function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, ProjectList, GenerateList, LoadBreadCrumbs,
export function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, ProjectList, GenerateList, LoadBreadCrumbs,
Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, SelectionInit, ProjectUpdate, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, SelectionInit, ProjectUpdate,
Refresh, Wait, Stream, GetChoices, Empty, Find, LogViewer, GetProjectIcon, GetProjectToolTip) { Refresh, Wait, Stream, GetChoices, Empty, Find, LogViewer, GetProjectIcon, GetProjectToolTip) {
@@ -391,7 +391,7 @@ ProjectsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routePara
]; ];
function ProjectsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, ProjectsForm, GenerateForm, Rest, Alert, ProcessErrors, export function ProjectsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, ProjectsForm, GenerateForm, Rest, Alert, ProcessErrors,
LoadBreadCrumbs, ClearScope, GetBasePath, ReturnToCaller, GetProjectPath, LookUpInit, OrganizationList, LoadBreadCrumbs, ClearScope, GetBasePath, ReturnToCaller, GetProjectPath, LookUpInit, OrganizationList,
CredentialList, GetChoices, DebugForm, Wait) { CredentialList, GetChoices, DebugForm, Wait) {
@@ -537,7 +537,7 @@ ProjectsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log',
]; ];
function ProjectsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, ProjectsForm, export function ProjectsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, ProjectsForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, Prompt, GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, Prompt,
ClearScope, GetBasePath, ReturnToCaller, GetProjectPath, Authorization, CredentialList, LookUpInit, GetChoices, ClearScope, GetBasePath, ReturnToCaller, GetProjectPath, Authorization, CredentialList, LookUpInit, GetChoices,
Empty, DebugForm, Wait, Stream, SchedulesControllerInit, SchedulesListInit, SchedulesList, ProjectUpdate) { Empty, DebugForm, Wait, Stream, SchedulesControllerInit, SchedulesListInit, SchedulesList, ProjectUpdate) {

View File

@@ -12,9 +12,9 @@
* @name controllers.function:Schedules * @name controllers.function:Schedules
* @description This controller's for schedules * @description This controller's for schedules
*/ */
'use strict';
function ScheduleEditController($scope, $compile, $location, $routeParams, SchedulesList, Rest, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
export function ScheduleEditController($scope, $compile, $location, $routeParams, SchedulesList, Rest, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
GetBasePath, Wait, Breadcrumbs, Find, LoadDialogPartial, LoadSchedulesScope, GetChoices, Stream) { GetBasePath, Wait, Breadcrumbs, Find, LoadDialogPartial, LoadSchedulesScope, GetChoices, Stream) {
ClearScope(); ClearScope();

View File

@@ -11,9 +11,9 @@
* @description This controller's for controlling websockets * @description This controller's for controlling websockets
* discuss * discuss
*/ */
'use strict';
function SocketsController ($scope, $compile, ClearScope, Socket) {
export function SocketsController ($scope, $compile, ClearScope, Socket) {
ClearScope(); ClearScope();

View File

@@ -26,7 +26,7 @@
// * // *
// * The variables in local memory are cleaned out whenever the user navigates to a page (other than the Survey Maker page) // * The variables in local memory are cleaned out whenever the user navigates to a page (other than the Survey Maker page)
// */ // */
// 'use strict'; //
// function SurveyController($scope, $rootScope, $compile, $location, $log, $routeParams, SurveyMakerForm, // function SurveyController($scope, $rootScope, $compile, $location, $log, $routeParams, SurveyMakerForm,
// GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, // GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath,

View File

@@ -12,9 +12,9 @@
* @name controllers.function:Teams * @name controllers.function:Teams
* @description This controller's for teams * @description This controller's for teams
*/ */
'use strict';
function TeamsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, TeamList, GenerateList, LoadBreadCrumbs,
export function TeamsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, TeamList, GenerateList, LoadBreadCrumbs,
Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, SetTeamListeners, GetBasePath, SelectionInit, Wait, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, SetTeamListeners, GetBasePath, SelectionInit, Wait,
Stream) { Stream) {
@@ -116,7 +116,7 @@ TeamsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams'
]; ];
function TeamsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, GenerateForm, export function TeamsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, GenerateForm,
Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateList, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateList,
OrganizationList, SearchInit, PaginateInit, GetBasePath, LookUpInit, Wait) { OrganizationList, SearchInit, PaginateInit, GetBasePath, LookUpInit, Wait) {
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
@@ -177,7 +177,7 @@ TeamsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$r
]; ];
function TeamsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, GenerateForm, Rest, Alert, ProcessErrors, export function TeamsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, GenerateForm, Rest, Alert, ProcessErrors,
LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInit, Prompt, GetBasePath, CheckAccess, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInit, Prompt, GetBasePath, CheckAccess,
OrganizationList, Wait, Stream) { OrganizationList, Wait, Stream) {

View File

@@ -11,9 +11,9 @@
* @name controllers.function:Users * @name controllers.function:Users
* @description This controller's the Users page * @description This controller's the Users page
*/ */
'use strict';
function UsersList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, UserList, GenerateList, LoadBreadCrumbs,
export function UsersList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, UserList, GenerateList, LoadBreadCrumbs,
Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, SelectionInit, Wait, Stream) { Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, SelectionInit, Wait, Stream) {
ClearScope(); ClearScope();
@@ -105,7 +105,7 @@ UsersList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams'
]; ];
function UsersAdd($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm, GenerateForm, Rest, Alert, ProcessErrors, export function UsersAdd($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm, GenerateForm, Rest, Alert, ProcessErrors,
LoadBreadCrumbs, ReturnToCaller, ClearScope, GetBasePath, LookUpInit, OrganizationList, ResetForm, Wait) { LoadBreadCrumbs, ReturnToCaller, ClearScope, GetBasePath, LookUpInit, OrganizationList, ResetForm, Wait) {
ClearScope(); ClearScope();
@@ -208,7 +208,7 @@ UsersAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$r
]; ];
function UsersEdit($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm, GenerateForm, Rest, Alert, export function UsersEdit($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm, GenerateForm, Rest, Alert,
ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, GetBasePath, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, GetBasePath,
Prompt, CheckAccess, ResetForm, Wait, Stream) { Prompt, CheckAccess, ResetForm, Wait, Stream) {

View File

@@ -1 +1,12 @@
angular.module('DashboardGraphs', []); import JobStatusGraph from 'tower/directives/job-status-graph';
import HostCountGraph from 'tower/directives/host-count-graph';
import HostStatusGraph from 'tower/directives/host-status-graph';
import AutoSizeModule from 'tower/directives/auto-size-module';
import AdjustGraphSize from 'tower/services/adjust-graph-size';
export default angular.module('DashboardGraphs', [])
.directive('jobStatusGraph', JobStatusGraph)
.directive('hostCountGraph', HostCountGraph)
.directive('hostStatusGraph', HostStatusGraph)
.directive('autoSizeModule', AutoSizeModule)
.service('adjustGraphSize', AdjustGraphSize);

View File

@@ -1,5 +1,9 @@
angular.module('DashboardGraphs') export default
.directive('autoSizeModule', ['$window', function($window) { [ '$window',
AutoSizeModule
];
function AutoSizeModule($window) {
// Adjusts the size of the module so that all modules // Adjusts the size of the module so that all modules
// fit into a single a page; assumes there are 2 rows // fit into a single a page; assumes there are 2 rows
@@ -32,4 +36,4 @@ angular.module('DashboardGraphs')
}; };
}]); }

View File

@@ -1,5 +1,10 @@
angular.module('DashboardGraphs'). export default
directive('hostCountGraph', ['GetBasePath', 'Rest', 'adjustGraphSize', '$window', function(getBasePath, Rest, adjustGraphSize, $window) { [ 'adjustGraphSize',
'$window',
HostCountGraph
];
function HostCountGraph(adjustGraphSize, $window) {
return { return {
restrict: 'E', restrict: 'E',
@@ -42,11 +47,11 @@ angular.module('DashboardGraphs').
{ "key" : "Hosts" , { "key" : "Hosts" ,
"color" : "#1778c3", "color" : "#1778c3",
"values": data.hosts "values": data.hosts
}, },
{ "key" : "License" , { "key" : "License" ,
"color" : "#171717", "color" : "#171717",
"values": data.hosts "values": data.hosts
} }
]; ];
graphData.map(function(series) { graphData.map(function(series) {
@@ -116,4 +121,4 @@ angular.module('DashboardGraphs').
} }
} }
}]); }

View File

@@ -1,6 +1,10 @@
angular.module('DashboardGraphs') export default
.directive('hostStatusGraph', ['$compile', '$window', [ '$compile',
function ($compile, $window) { '$window',
HostStatusGraph
];
function HostStatusGraph($compile, $window) {
return { return {
restrict: 'E', restrict: 'E',
link: link, link: link,
@@ -99,4 +103,4 @@ angular.module('DashboardGraphs')
} }
} }
}]); }

View File

@@ -1,6 +1,15 @@
angular.module('DashboardGraphs') export default
.directive('jobStatusGraph', ['$rootScope', '$compile', '$location' , '$window', 'Wait', 'adjustGraphSize', 'jobStatusGraphData', [ '$rootScope',
function ($rootScope, $compile , $location, $window, Wait, adjustGraphSize) { '$compile',
'$location' ,
'$window',
'Wait',
'adjustGraphSize',
'jobStatusGraphData',
JobStatusGraph
];
function JobStatusGraph($rootScope, $compile , $location, $window, Wait, adjustGraphSize) {
return { return {
restrict: 'E', restrict: 'E',
templateUrl: '/static/partials/job_status_graph.html', templateUrl: '/static/partials/job_status_graph.html',
@@ -117,4 +126,4 @@ angular.module('DashboardGraphs')
} }
} }
}]); }

58
awx/ui/static/js/forms.js Normal file
View File

@@ -0,0 +1,58 @@
import ActivityDetail from "tower/forms/ActivityDetail";
import Credentials from "tower/forms/Credentials";
import CustomInventory from "tower/forms/CustomInventory";
import EventsViewer from "tower/forms/EventsViewer";
import Groups from "tower/forms/Groups";
import HostGroups from "tower/forms/HostGroups";
import Hosts from "tower/forms/Hosts";
import Inventories from "tower/forms/Inventories";
import InventoryStatus from "tower/forms/InventoryStatus";
import JobEventData from "tower/forms/JobEventData";
import JobSummary from "tower/forms/JobSummary";
import JobTemplates from "tower/forms/JobTemplates";
import JobVarsPrompt from "tower/forms/JobVarsPrompt";
import Jobs from "tower/forms/Jobs";
import LicenseForm from "tower/forms/LicenseForm";
import LicenseUpdate from "tower/forms/LicenseUpdate";
import LogViewerOptions from "tower/forms/LogViewerOptions";
import LogViewerStatus from "tower/forms/LogViewerStatus";
import Organizations from "tower/forms/Organizations";
import Permissions from "tower/forms/Permissions";
import ProjectStatus from "tower/forms/ProjectStatus";
import Projects from "tower/forms/Projects";
import Source from "tower/forms/Source";
import SurveyMaker from "tower/forms/SurveyMaker";
import SurveyQuestion from "tower/forms/SurveyQuestion";
import Teams from "tower/forms/Teams";
import Users from "tower/forms/Users";
export
{ ActivityDetail,
Credentials,
CustomInventory,
EventsViewer,
Groups,
HostGroups,
Hosts,
Inventories,
InventoryStatus,
JobEventData,
JobSummary,
JobTemplates,
JobVarsPrompt,
Jobs,
LicenseForm,
LicenseUpdate,
LogViewerOptions,
LogViewerStatus,
Organizations,
Permissions,
ProjectStatus,
Projects,
Source,
SurveyMaker,
SurveyQuestion,
Teams,
Users
};

View File

@@ -16,33 +16,35 @@
* @name forms.function:ActivityDetail * @name forms.function:ActivityDetail
* @description This form is for activity detail modal that can be shown on most pages. * @description This form is for activity detail modal that can be shown on most pages.
*/ */
angular.module('ActivityDetailDefinition', [])
.value('ActivityDetailForm', {
name: 'activity', export default
editTitle: 'Activity Detail', angular.module('ActivityDetailDefinition', [])
well: false, .value('ActivityDetailForm', {
'class': 'horizontal-narrow',
formFieldSize: 'col-lg-10',
formLabelSize: 'col-lg-2',
fields: { name: 'activity',
user: { editTitle: 'Activity Detail',
label: "Initiated by", well: false,
type: 'text', 'class': 'horizontal-narrow',
readonly: true formFieldSize: 'col-lg-10',
}, formLabelSize: 'col-lg-2',
operation: {
label: 'Action', fields: {
type: 'text', user: {
readonly: true label: "Initiated by",
}, type: 'text',
changes: { readonly: true
label: 'Changes', },
type: 'textarea', operation: {
ngHide: "!changes || changes =='' || changes == 'null'", label: 'Action',
readonly: true type: 'text',
readonly: true
},
changes: {
label: 'Changes',
type: 'textarea',
ngHide: "!changes || changes =='' || changes == 'null'",
readonly: true
}
} }
}
}); //Form }); //Form

View File

@@ -10,438 +10,440 @@
* @name forms.function:Credentials * @name forms.function:Credentials
* @description This form is for adding/editing a Credential * @description This form is for adding/editing a Credential
*/ */
angular.module('CredentialFormDefinition', [])
.value('CredentialForm', {
addTitle: 'Create Credential', //Legend in add mode export default
editTitle: '{{ name }}', //Legend in edit mode angular.module('CredentialFormDefinition', [])
name: 'credential', .value('CredentialForm', {
well: true,
forceListeners: true,
actions: { addTitle: 'Create Credential', //Legend in add mode
stream: { editTitle: '{{ name }}', //Legend in edit mode
ngClick: "showActivity()", name: 'credential',
awToolTip: "View Activity Stream", well: true,
mode: 'edit' forceListeners: true,
}
},
fields: { actions: {
name: { stream: {
label: 'Name', ngClick: "showActivity()",
type: 'text', awToolTip: "View Activity Stream",
addRequired: true, mode: 'edit'
editRequired: true,
autocomplete: false
},
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: "<p>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.</p>",
dataTitle: 'Owner',
dataPlacement: 'right',
dataContainer: "body"
},
user: {
label: 'User that owns this credential',
type: 'lookup',
sourceModel: 'user',
sourceField: 'username',
ngClick: 'lookUpUser()',
ngShow: "owner == 'user'",
awRequiredWhen: {
variable: "user_required",
init: "false"
} }
}, },
team: {
label: 'Team that owns this credential', fields: {
type: 'lookup', name: {
sourceModel: 'team', label: 'Name',
sourceField: 'name', type: 'text',
ngClick: 'lookUpTeam()', addRequired: true,
ngShow: "owner == 'team'", editRequired: true,
awRequiredWhen: { autocomplete: false
variable: "team_required", },
init: "false" 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: "<p>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.</p>",
dataTitle: 'Owner',
dataPlacement: 'right',
dataContainer: "body"
},
user: {
label: 'User that owns this credential',
type: 'lookup',
sourceModel: 'user',
sourceField: 'username',
ngClick: 'lookUpUser()',
ngShow: "owner == 'user'",
awRequiredWhen: {
variable: "user_required",
init: "false"
}
},
team: {
label: 'Team that owns this credential',
type: 'lookup',
sourceModel: 'team',
sourceField: 'name',
ngClick: 'lookUpTeam()',
ngShow: "owner == 'team'",
awRequiredWhen: {
variable: "team_required",
init: "false"
}
},
kind: {
label: 'Type',
excludeModal: true,
type: 'select',
ngOptions: 'kind.label for kind in credential_kind_options track by kind.value', // select as label for value in array 'kind.label for kind in credential_kind_options',
ngChange: 'kindChange()',
addRequired: true,
editRequired: true,
awPopOver:'<dl>\n' +
'<dt>Machine</dt>\n' +
'<dd>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.</dd>' +
'<dt>Source Control</dt>\n' +
'<dd>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.</dd>\n' +
'<dt>Others (Cloud Providers)</dt>\n' +
'<dd>Access keys for authenticating to the specific ' +
'cloud provider, usually used for inventory sync ' +
'and deployment.</dd>\n' +
'</dl>\n',
dataTitle: 'Type',
dataPlacement: 'right',
dataContainer: "body"
// helpCollapse: [{
// hdr: 'Select a Credential Type',
// content: '<dl>\n' +
// '<dt>Machine</dt>\n' +
// '<dd>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.</dd>' +
// '<dt>Source Control</dt>\n' +
// '<dd>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.</dd>\n' +
// '<dt>Others (Cloud Providers)</dt>\n' +
// '<dd>Access keys for authenticating to the specific ' +
// 'cloud provider, usually used for inventory sync ' +
// 'and deployment.</dd>\n' +
// '</dl>\n'
// }]
},
access_key: {
label: 'Access Key',
type: 'text',
ngShow: "kind.value == 'aws'",
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
},
autocomplete: false,
ask: false,
clear: false,
apiField: 'passwowrd'
},
"host": {
labelBind: 'hostLabel',
type: 'text',
ngShow: "kind.value == 'vmware'",
autocomplete: false,
awRequiredWhen: {
variable: 'host_required',
init: false
}
},
"username": {
labelBind: 'usernameLabel',
type: 'text',
ngShow: "kind.value && kind.value !== 'aws' && " +
"kind.value !== 'gce' && kind.value!=='azure'",
awRequiredWhen: {
variable: 'username_required',
init: false
},
autocomplete: false
},
"email_address": {
labelBind: 'usernameLabel',
type: 'email',
ngShow: "kind.value === 'gce'",
awRequiredWhen: {
variable: 'email_required',
init: false
},
autocomplete: false,
awPopOver: '<p>The email address assigned to the Google Compute Engine <b><i>service account.</b></i></p>',
dataTitle: 'Email',
dataPlacement: 'right',
dataContainer: "body"
},
"subscription_id": {
labelBind: "usernameLabel",
type: 'text',
ngShow: "kind.value == 'azure'",
awRequiredWhen: {
variable: 'subscription_required',
init: false
},
addRequired: false,
editRequired: false,
autocomplete: false,
awPopOver: '<p>Subscription ID is an Azure construct, which is mapped to a username.</p>',
dataTitle: 'Subscription ID',
dataPlacement: 'right',
dataContainer: "body"
},
"api_key": {
label: 'API Key',
type: 'password',
ngShow: "kind.value == 'rax'",
awRequiredWhen: {
variable: "rackspace_required",
init: false
},
autocomplete: false,
ask: false,
clear: false,
// apiField: 'passwowrd'
},
"password": {
label: 'Password',
type: 'password',
ngShow: "kind.value == 'scm' || kind.value == 'vmware'",
addRequired: false,
editRequired: false,
ngChange: "clearPWConfirm('password_confirm')",
ask: false,
clear: false,
associated: 'password_confirm',
autocomplete: false,
awRequiredWhen: {
variable: "password_required",
init: false
}
},
"password_confirm": {
label: 'Confirm Password',
type: 'password',
ngShow: "kind.value == 'scm' || kind.value == 'vmware'",
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'password',
autocomplete: false,
awRequiredWhen: {
variable: "password_required",
init: false
}
},
"ssh_password": {
label: 'Password', // formally 'SSH Password'
type: 'password',
ngShow: "kind.value == 'ssh'",
ngChange: "clearPWConfirm('ssh_password_confirm')",
addRequired: false,
editRequired: false,
ask: true,
clear: true,
associated: 'ssh_password_confirm',
autocomplete: false
},
"ssh_password_confirm": {
label: 'Confirm Password', // formally 'Confirm SSH password'
type: 'password',
ngShow: "kind.value == 'ssh'",
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'ssh_password',
autocomplete: false
},
"ssh_key_data": {
labelBind: 'sshKeyDataLabel',
type: 'textarea',
ngShow: "kind.value == 'ssh' || kind.value == 'scm' || " +
"kind.value == 'gce' || kind.value == 'azure'",
awRequiredWhen: {
variable: 'key_required',
init: true
},
hintText: "{{ key_hint }}",
addRequired: false,
editRequired: false,
awDropFile: true,
'class': 'ssh-key-field',
rows: 10,
awPopOver: "SSH key description",
awPopOverWatch: "key_description",
dataTitle: 'Help',
dataPlacement: 'right',
dataContainer: "body"
},
"ssh_key_unlock": {
label: 'Key Password',
type: 'password',
ngShow: "kind.value == 'ssh' || kind.value == 'scm'",
addRequired: false,
editRequired: false,
ngChange: "clearPWConfirm('ssh_key_unlock_confirm')",
associated: 'ssh_key_unlock_confirm',
ask: true,
askShow: "kind.value == 'ssh'", // Only allow ask for machine credentials
clear: true
},
"ssh_key_unlock_confirm": {
label: 'Confirm Key Password',
type: 'password',
ngShow: "kind.value == 'ssh' || kind.value == 'scm'",
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'ssh_key_unlock'
},
"login_method": {
label: "Login Method", // FIXME: Confirm this label is ok?
type: 'radio_group',
ngShow: "kind.value == 'ssh'",
ngChange: "loginMethodChange()",
options: [{
label: 'None', // FIXME: Maybe 'Default' or 'SSH only' instead?
value: '',
selected: true
}, {
label: 'Sudo',
value: 'sudo'
}, {
label: 'Su',
value: 'su'
}],
awPopOver: "<p>A credential may optionally provide a sudo username and password or su username and password to use when running a playbook.</p>",
dataPlacement: 'right',
dataContainer: "body"
},
"sudo_username": {
label: 'Sudo Username',
type: 'text',
ngShow: "kind.value == 'ssh' && login_method == 'sudo'",
addRequired: false,
editRequired: false,
autocomplete: false
},
"sudo_password": {
label: 'Sudo Password',
type: 'password',
ngShow: "kind.value == 'ssh' && login_method == 'sudo'",
addRequired: false,
editRequired: false,
ngChange: "clearPWConfirm('sudo_password_confirm')",
ask: true,
clear: true,
associated: 'sudo_password_confirm',
autocomplete: false
},
"sudo_password_confirm": {
label: 'Confirm Sudo Password',
type: 'password',
ngShow: "kind.value == 'ssh' && login_method == 'sudo'",
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'sudo_password',
autocomplete: false
},
"su_username": {
label: 'Su Username',
type: 'text',
ngShow: "kind.value == 'ssh' && login_method == 'su'",
addRequired: false,
editRequired: false,
autocomplete: false
},
"su_password": {
label: 'Su Password',
type: 'password',
ngShow: "kind.value == 'ssh' && login_method == 'su'",
addRequired: false,
editRequired: false,
ngChange: "clearPWConfirm('su_password_confirm')",
ask: true,
clear: true,
associated: 'su_password_confirm',
autocomplete: false
},
"su_password_confirm": {
label: 'Confirm Su Password',
type: 'password',
ngShow: "kind.value == 'ssh' && login_method == 'su'",
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'su_password',
autocomplete: false
},
"project": {
label: "Project",
type: 'text',
ngShow: "kind.value == 'gce'",
awRequiredWhen: {
variable: 'project_required',
init: false
},
awPopOver: "<p>The Project ID is the GCE assigned identification. It is constructed as two words followed by a three digit number. Such as: </p><p>adjective-noun-000</p>",
dataTitle: 'Project ID',
dataPlacement: 'right',
dataContainer: "body",
addRequired: false,
editRequired: false,
autocomplete: false
},
"vault_password": {
label: "Vault Password",
type: 'password',
ngShow: "kind.value == 'ssh'",
addRequired: false,
editRequired: false,
ngChange: "clearPWConfirm('vault_password_confirm')",
ask: true,
clear: true,
associated: 'vault_password_confirm',
autocomplete: false
},
"vault_password_confirm": {
label: "Confirm Vault Password",
type: 'password',
ngShow: "kind.value == 'ssh'",
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'vault_password',
autocomplete: false
} }
}, },
kind: {
label: 'Type', buttons: {
excludeModal: true, save: {
type: 'select', label: 'Save',
ngOptions: 'kind.label for kind in credential_kind_options track by kind.value', // select as label for value in array 'kind.label for kind in credential_kind_options', ngClick: 'formSave()', //$scope.function to call on click, optional
ngChange: 'kindChange()', ngDisabled: true //Disable when $pristine or $invalid, optional
addRequired: true,
editRequired: true,
awPopOver:'<dl>\n' +
'<dt>Machine</dt>\n' +
'<dd>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.</dd>' +
'<dt>Source Control</dt>\n' +
'<dd>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.</dd>\n' +
'<dt>Others (Cloud Providers)</dt>\n' +
'<dd>Access keys for authenticating to the specific ' +
'cloud provider, usually used for inventory sync ' +
'and deployment.</dd>\n' +
'</dl>\n',
dataTitle: 'Type',
dataPlacement: 'right',
dataContainer: "body"
// helpCollapse: [{
// hdr: 'Select a Credential Type',
// content: '<dl>\n' +
// '<dt>Machine</dt>\n' +
// '<dd>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.</dd>' +
// '<dt>Source Control</dt>\n' +
// '<dd>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.</dd>\n' +
// '<dt>Others (Cloud Providers)</dt>\n' +
// '<dd>Access keys for authenticating to the specific ' +
// 'cloud provider, usually used for inventory sync ' +
// 'and deployment.</dd>\n' +
// '</dl>\n'
// }]
},
access_key: {
label: 'Access Key',
type: 'text',
ngShow: "kind.value == 'aws'",
awRequiredWhen: {
variable: "aws_required",
init: false
}, },
autocomplete: false, reset: {
apiField: 'username' ngClick: 'formReset()',
}, ngDisabled: true //Disabled when $pristine
secret_key: {
label: 'Secret Key',
type: 'password',
ngShow: "kind.value == 'aws'",
awRequiredWhen: {
variable: "aws_required",
init: false
},
autocomplete: false,
ask: false,
clear: false,
apiField: 'passwowrd'
},
"host": {
labelBind: 'hostLabel',
type: 'text',
ngShow: "kind.value == 'vmware'",
autocomplete: false,
awRequiredWhen: {
variable: 'host_required',
init: false
} }
}, },
"username": {
labelBind: 'usernameLabel',
type: 'text',
ngShow: "kind.value && kind.value !== 'aws' && " +
"kind.value !== 'gce' && kind.value!=='azure'",
awRequiredWhen: {
variable: 'username_required',
init: false
},
autocomplete: false
},
"email_address": {
labelBind: 'usernameLabel',
type: 'email',
ngShow: "kind.value === 'gce'",
awRequiredWhen: {
variable: 'email_required',
init: false
},
autocomplete: false,
awPopOver: '<p>The email address assigned to the Google Compute Engine <b><i>service account.</b></i></p>',
dataTitle: 'Email',
dataPlacement: 'right',
dataContainer: "body"
},
"subscription_id": {
labelBind: "usernameLabel",
type: 'text',
ngShow: "kind.value == 'azure'",
awRequiredWhen: {
variable: 'subscription_required',
init: false
},
addRequired: false,
editRequired: false,
autocomplete: false,
awPopOver: '<p>Subscription ID is an Azure construct, which is mapped to a username.</p>',
dataTitle: 'Subscription ID',
dataPlacement: 'right',
dataContainer: "body"
}, related: {}
"api_key": {
label: 'API Key',
type: 'password',
ngShow: "kind.value == 'rax'",
awRequiredWhen: {
variable: "rackspace_required",
init: false
},
autocomplete: false,
ask: false,
clear: false,
// apiField: 'passwowrd'
},
"password": {
label: 'Password',
type: 'password',
ngShow: "kind.value == 'scm' || kind.value == 'vmware'",
addRequired: false,
editRequired: false,
ngChange: "clearPWConfirm('password_confirm')",
ask: false,
clear: false,
associated: 'password_confirm',
autocomplete: false,
awRequiredWhen: {
variable: "password_required",
init: false
}
},
"password_confirm": {
label: 'Confirm Password',
type: 'password',
ngShow: "kind.value == 'scm' || kind.value == 'vmware'",
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'password',
autocomplete: false,
awRequiredWhen: {
variable: "password_required",
init: false
}
},
"ssh_password": {
label: 'Password', // formally 'SSH Password'
type: 'password',
ngShow: "kind.value == 'ssh'",
ngChange: "clearPWConfirm('ssh_password_confirm')",
addRequired: false,
editRequired: false,
ask: true,
clear: true,
associated: 'ssh_password_confirm',
autocomplete: false
},
"ssh_password_confirm": {
label: 'Confirm Password', // formally 'Confirm SSH password'
type: 'password',
ngShow: "kind.value == 'ssh'",
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'ssh_password',
autocomplete: false
},
"ssh_key_data": {
labelBind: 'sshKeyDataLabel',
type: 'textarea',
ngShow: "kind.value == 'ssh' || kind.value == 'scm' || " +
"kind.value == 'gce' || kind.value == 'azure'",
awRequiredWhen: {
variable: 'key_required',
init: true
},
hintText: "{{ key_hint }}",
addRequired: false,
editRequired: false,
awDropFile: true,
'class': 'ssh-key-field',
rows: 10,
awPopOver: "SSH key description",
awPopOverWatch: "key_description",
dataTitle: 'Help',
dataPlacement: 'right',
dataContainer: "body"
},
"ssh_key_unlock": {
label: 'Key Password',
type: 'password',
ngShow: "kind.value == 'ssh' || kind.value == 'scm'",
addRequired: false,
editRequired: false,
ngChange: "clearPWConfirm('ssh_key_unlock_confirm')",
associated: 'ssh_key_unlock_confirm',
ask: true,
askShow: "kind.value == 'ssh'", // Only allow ask for machine credentials
clear: true
},
"ssh_key_unlock_confirm": {
label: 'Confirm Key Password',
type: 'password',
ngShow: "kind.value == 'ssh' || kind.value == 'scm'",
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'ssh_key_unlock'
},
"login_method": {
label: "Login Method", // FIXME: Confirm this label is ok?
type: 'radio_group',
ngShow: "kind.value == 'ssh'",
ngChange: "loginMethodChange()",
options: [{
label: 'None', // FIXME: Maybe 'Default' or 'SSH only' instead?
value: '',
selected: true
}, {
label: 'Sudo',
value: 'sudo'
}, {
label: 'Su',
value: 'su'
}],
awPopOver: "<p>A credential may optionally provide a sudo username and password or su username and password to use when running a playbook.</p>",
dataPlacement: 'right',
dataContainer: "body"
},
"sudo_username": {
label: 'Sudo Username',
type: 'text',
ngShow: "kind.value == 'ssh' && login_method == 'sudo'",
addRequired: false,
editRequired: false,
autocomplete: false
},
"sudo_password": {
label: 'Sudo Password',
type: 'password',
ngShow: "kind.value == 'ssh' && login_method == 'sudo'",
addRequired: false,
editRequired: false,
ngChange: "clearPWConfirm('sudo_password_confirm')",
ask: true,
clear: true,
associated: 'sudo_password_confirm',
autocomplete: false
},
"sudo_password_confirm": {
label: 'Confirm Sudo Password',
type: 'password',
ngShow: "kind.value == 'ssh' && login_method == 'sudo'",
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'sudo_password',
autocomplete: false
},
"su_username": {
label: 'Su Username',
type: 'text',
ngShow: "kind.value == 'ssh' && login_method == 'su'",
addRequired: false,
editRequired: false,
autocomplete: false
},
"su_password": {
label: 'Su Password',
type: 'password',
ngShow: "kind.value == 'ssh' && login_method == 'su'",
addRequired: false,
editRequired: false,
ngChange: "clearPWConfirm('su_password_confirm')",
ask: true,
clear: true,
associated: 'su_password_confirm',
autocomplete: false
},
"su_password_confirm": {
label: 'Confirm Su Password',
type: 'password',
ngShow: "kind.value == 'ssh' && login_method == 'su'",
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'su_password',
autocomplete: false
},
"project": {
label: "Project",
type: 'text',
ngShow: "kind.value == 'gce'",
awRequiredWhen: {
variable: 'project_required',
init: false
},
awPopOver: "<p>The Project ID is the GCE assigned identification. It is constructed as two words followed by a three digit number. Such as: </p><p>adjective-noun-000</p>",
dataTitle: 'Project ID',
dataPlacement: 'right',
dataContainer: "body",
addRequired: false,
editRequired: false,
autocomplete: false
},
"vault_password": { });
label: "Vault Password",
type: 'password',
ngShow: "kind.value == 'ssh'",
addRequired: false,
editRequired: false,
ngChange: "clearPWConfirm('vault_password_confirm')",
ask: true,
clear: true,
associated: 'vault_password_confirm',
autocomplete: false
},
"vault_password_confirm": {
label: "Confirm Vault Password",
type: 'password',
ngShow: "kind.value == 'ssh'",
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'vault_password',
autocomplete: false
}
},
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: {}
});

View File

@@ -11,68 +11,70 @@
* @name forms.function:Organizations * @name forms.function:Organizations
* @description This form is for adding/editing an organization * @description This form is for adding/editing an organization
*/ */
angular.module('CustomInventoryFormDefinition', [])
.value('CustomInventoryForm', {
addTitle: 'Create Custom Inventory', //Title in add mode export default
editTitle: '{{ name }}', //Title in edit mode angular.module('CustomInventoryFormDefinition', [])
name: 'custom_inventory', //entity or model name in singular form .value('CustomInventoryForm', {
well: false,
showActions: false,
fields: { addTitle: 'Create Custom Inventory', //Title in add mode
name: { editTitle: '{{ name }}', //Title in edit mode
label: 'Name', name: 'custom_inventory', //entity or model name in singular form
type: 'text', well: false,
addRequired: true, showActions: false,
editRequired: true,
capitalize: false fields: {
}, name: {
description: { label: 'Name',
label: 'Description', type: 'text',
type: 'text', addRequired: true,
addRequired: false, editRequired: true,
editRequired: false capitalize: false
}, },
organization: { description: {
label: 'Organization', label: 'Description',
type: 'lookup', type: 'text',
awRequiredWhen: { addRequired: false,
variable: "orgrequired", editRequired: false
init: true },
organization: {
label: 'Organization',
type: 'lookup',
awRequiredWhen: {
variable: "orgrequired",
init: true
},
sourceModel: 'organization',
sourceField: 'name',
ngClick: 'lookUpOrganization()'
},
script: {
label: 'Custom Script',
type: 'textarea',
hintText: "Drag and drop an inventory script on the field below",
addRequired: true,
editRequired: true,
awDropFile: true,
'class': 'ssh-key-field',
rows: 10,
awPopOver: "<p>Drag and drop your custom inventory script file here or create one in the field to import your custom inventory. " +
"<br><br> Script must begin with a hashbang sequence: i.e.... #!/usr/bin/env python</p>",
dataTitle: 'Custom Script',
dataPlacement: 'right',
dataContainer: "body"
}, },
sourceModel: 'organization',
sourceField: 'name',
ngClick: 'lookUpOrganization()'
}, },
script: {
label: 'Custom Script', buttons: { //for now always generates <button> tags
type: 'textarea', save: {
hintText: "Drag and drop an inventory script on the field below", ngClick: 'formSave()', //$scope.function to call on click, optional
addRequired: true, ngDisabled: true //Disable when $pristine or $invalid, optional
editRequired: true, },
awDropFile: true, reset: {
'class': 'ssh-key-field', ngClick: 'formReset()',
rows: 10, ngDisabled: true //Disabled when $pristine
awPopOver: "<p>Drag and drop your custom inventory script file here or create one in the field to import your custom inventory. " + }
"<br><br> Script must begin with a hashbang sequence: i.e.... #!/usr/bin/env python</p>",
dataTitle: 'Custom Script',
dataPlacement: 'right',
dataContainer: "body"
}, },
},
buttons: { //for now always generates <button> 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
}
},
}); //OrganizationForm }); //OrganizationForm

View File

@@ -9,74 +9,76 @@
* @name forms.function:EventsViewer * @name forms.function:EventsViewer
* @description This form is for events on the job detail page * @description This form is for events on the job detail page
*/ */
angular.module('EventsViewerFormDefinition', [])
.value('EventsViewerForm', {
fields: { export default
host_name: { angular.module('EventsViewerFormDefinition', [])
label: 'Host', .value('EventsViewerForm', {
section: 'Event'
}, fields: {
status: { host_name: {
label: 'Status', label: 'Host',
section: 'Event' section: 'Event'
}, },
id: { status: {
label: 'ID', label: 'Status',
section: 'Event' section: 'Event'
}, },
created: { id: {
label: 'Created On', label: 'ID',
section: 'Event' section: 'Event'
}, },
role: { created: {
label: 'Role', label: 'Created On',
section: 'Event' section: 'Event'
}, },
play: { role: {
label: 'Play', label: 'Role',
type: 'text', section: 'Event'
section: 'Event' },
}, play: {
task: { label: 'Play',
label: 'Task', type: 'text',
section: 'Event' section: 'Event'
}, },
item: { task: {
label: 'Item', label: 'Task',
section: 'Event' section: 'Event'
}, },
module_name: { item: {
label: 'Module', label: 'Item',
section: 'Event' section: 'Event'
}, },
module_args: { module_name: {
label: 'Arguments', label: 'Module',
section: 'Event' section: 'Event'
}, },
rc: { module_args: {
label: 'Return Code', label: 'Arguments',
section: 'Results' section: 'Event'
}, },
msg: { rc: {
label: 'Message', label: 'Return Code',
section: 'Results' section: 'Results'
}, },
results: { msg: {
label: 'Results', label: 'Message',
section: 'Results' section: 'Results'
}, },
start: { results: {
label: 'Start', label: 'Results',
section: 'Timing' section: 'Results'
}, },
end: { start: {
label: 'End', label: 'Start',
section: 'Timing' section: 'Timing'
}, },
delta: { end: {
label: 'Elapsed', label: 'End',
section: 'Timing' section: 'Timing'
},
delta: {
label: 'Elapsed',
section: 'Timing'
}
} }
} });
});

View File

@@ -11,56 +11,58 @@
* @name forms.function:Groups * @name forms.function:Groups
* @description This form is for adding/editing a Group on the inventory page * @description This form is for adding/editing a Group on the inventory page
*/ */
angular.module('GroupFormDefinition', [])
.value('GroupForm', {
addTitle: 'Create Group', export default
editTitle: 'Edit Group', angular.module('GroupFormDefinition', [])
showTitle: true, .value('GroupForm', {
cancelButton: false,
name: 'group',
well: false,
fields: { addTitle: 'Create Group',
name: { editTitle: 'Edit Group',
label: 'Name', showTitle: true,
type: 'text', cancelButton: false,
addRequired: true, name: 'group',
editRequired: true, well: false,
tab: 'properties'
fields: {
name: {
label: 'Name',
type: 'text',
addRequired: true,
editRequired: true,
tab: 'properties'
},
description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false,
tab: 'properties'
},
variables: {
label: 'Variables',
type: 'textarea',
addRequired: false,
editRequird: false,
rows: 12,
'default': '---',
dataTitle: 'Group Variables',
dataPlacement: 'right',
awPopOver: "<p>Variables defined here apply to all child groups and hosts.</p>" +
"<p>Enter variables using either JSON or YAML syntax. Use the " +
"radio button to toggle between the two.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n" +
'<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p>' +
'<p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">docs.ansible.com</a></p>',
dataContainer: 'body',
tab: 'properties'
}
}, },
description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false,
tab: 'properties'
},
variables: {
label: 'Variables',
type: 'textarea',
addRequired: false,
editRequird: false,
rows: 12,
'default': '---',
dataTitle: 'Group Variables',
dataPlacement: 'right',
awPopOver: "<p>Variables defined here apply to all child groups and hosts.</p>" +
"<p>Enter variables using either JSON or YAML syntax. Use the " +
"radio button to toggle between the two.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n" +
'<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p>' +
'<p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">docs.ansible.com</a></p>',
dataContainer: 'body',
tab: 'properties'
}
},
buttons: { }, buttons: { },
related: { } related: { }
}); });

View File

@@ -11,47 +11,49 @@
* @name forms.function:HostGroups * @name forms.function:HostGroups
* @description This form is for groups of hosts on the inventory page * @description This form is for groups of hosts on the inventory page
*/ */
angular.module('HostGroupsFormDefinition', [])
.value('HostGroupsForm', {
editTitle: 'Host Groups', export default
name: 'host', angular.module('HostGroupsFormDefinition', [])
well: false, .value('HostGroupsForm', {
formLabelSize: 'col-lg-3',
formFieldSize: 'col-lg-9',
fields: { editTitle: 'Host Groups',
groups: { name: 'host',
label: 'Groups', well: false,
type: 'select', formLabelSize: 'col-lg-3',
multiple: true, formFieldSize: 'col-lg-9',
ngOptions: 'group.name for group in inventory_groups track by group.value',
addRequired: true,
editRequired: true,
awPopOver: "<p>Provide a host name, ip address, or ip address:port. Examples include:</p>" +
"<blockquote>myserver.domain.com<br/>" +
"127.0.0.1<br />" +
"10.1.0.140:25<br />" +
"server.example.com:25" +
"</blockquote>",
dataTitle: 'Host Name',
dataPlacement: 'right',
dataContainer: '#form-modal .modal-content'
}
},
buttons: { //for now always generates <button> tags fields: {
save: { groups: {
ngClick: 'formSave()', label: 'Groups',
ngDisabled: true type: 'select',
multiple: true,
ngOptions: 'group.name for group in inventory_groups track by group.value',
addRequired: true,
editRequired: true,
awPopOver: "<p>Provide a host name, ip address, or ip address:port. Examples include:</p>" +
"<blockquote>myserver.domain.com<br/>" +
"127.0.0.1<br />" +
"10.1.0.140:25<br />" +
"server.example.com:25" +
"</blockquote>",
dataTitle: 'Host Name',
dataPlacement: 'right',
dataContainer: '#form-modal .modal-content'
}
}, },
reset: {
ngClick: 'formReset()',
ngDisabled: true
}
},
related: { } buttons: { //for now always generates <button> tags
save: {
ngClick: 'formSave()',
ngDisabled: true
},
reset: {
ngClick: 'formReset()',
ngDisabled: true
}
},
}); //UserForm related: { }
}); //UserForm

View File

@@ -11,90 +11,92 @@
* @name forms.function:Hosts * @name forms.function:Hosts
* @description This form is for adding/editing a host on the inventory page * @description This form is for adding/editing a host on the inventory page
*/ */
angular.module('HostFormDefinition', [])
.value('HostForm', {
addTitle: 'Create Host', export default
editTitle: '{{ name }}', angular.module('HostFormDefinition', [])
name: 'host', .value('HostForm', {
well: false,
formLabelSize: 'col-lg-3',
formFieldSize: 'col-lg-9',
fields: { addTitle: 'Create Host',
name: { editTitle: '{{ name }}',
label: 'Host Name', name: 'host',
type: 'text', well: false,
addRequired: true, formLabelSize: 'col-lg-3',
editRequired: true, formFieldSize: 'col-lg-9',
awPopOver: "<p>Provide a host name, ip address, or ip address:port. Examples include:</p>" +
"<blockquote>myserver.domain.com<br/>" +
"127.0.0.1<br />" +
"10.1.0.140:25<br />" +
"server.example.com:25" +
"</blockquote>",
dataTitle: 'Host Name',
dataPlacement: 'right',
dataContainer: 'body'
},
description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
},
enabled: {
label: 'Enabled?',
type: 'checkbox',
addRequired: false,
editRequired: false,
"default": true,
awPopOver: "<p>Indicates if a host is available and should be included in running jobs.</p><p>For hosts that " +
"are part of an external inventory, this flag cannot be changed. It will be set by the inventory sync process.</p>",
dataTitle: 'Host Enabled',
dataPlacement: 'right',
dataContainer: 'body',
ngDisabled: 'has_inventory_sources == true'
},
variables: {
label: 'Variables',
type: 'textarea',
addRequired: false,
editRequird: false,
rows: 6,
"class": "modal-input-xlarge",
"default": "---",
awPopOver: "<p>Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n" +
'<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p>' +
'<p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">docs.ansible.com</a></p>',
dataTitle: 'Host Variables',
dataPlacement: 'right',
dataContainer: 'body'
},
inventory: {
type: 'hidden',
includeOnEdit: true,
includeOnAdd: true
}
},
buttons: { //for now always generates <button> tags fields: {
/* name: {
save: { label: 'Host Name',
ngClick: 'formSave()', //$scope.function to call on click, optional type: 'text',
ngDisabled: true //Disable when $pristine or $invalid, optional addRequired: true,
editRequired: true,
awPopOver: "<p>Provide a host name, ip address, or ip address:port. Examples include:</p>" +
"<blockquote>myserver.domain.com<br/>" +
"127.0.0.1<br />" +
"10.1.0.140:25<br />" +
"server.example.com:25" +
"</blockquote>",
dataTitle: 'Host Name',
dataPlacement: 'right',
dataContainer: 'body'
},
description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
},
enabled: {
label: 'Enabled?',
type: 'checkbox',
addRequired: false,
editRequired: false,
"default": true,
awPopOver: "<p>Indicates if a host is available and should be included in running jobs.</p><p>For hosts that " +
"are part of an external inventory, this flag cannot be changed. It will be set by the inventory sync process.</p>",
dataTitle: 'Host Enabled',
dataPlacement: 'right',
dataContainer: 'body',
ngDisabled: 'has_inventory_sources == true'
},
variables: {
label: 'Variables',
type: 'textarea',
addRequired: false,
editRequird: false,
rows: 6,
"class": "modal-input-xlarge",
"default": "---",
awPopOver: "<p>Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n" +
'<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p>' +
'<p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">docs.ansible.com</a></p>',
dataTitle: 'Host Variables',
dataPlacement: 'right',
dataContainer: 'body'
},
inventory: {
type: 'hidden',
includeOnEdit: true,
includeOnAdd: true
}
}, },
reset: {
ngClick: 'formReset()',
ngDisabled: true //Disabled when $pristine
}
*/
},
related: {} buttons: { //for now always generates <button> 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: {}
});

View File

@@ -11,87 +11,89 @@
* @name forms.function:Inventories * @name forms.function:Inventories
* @description This form is for adding/editing an inventory * @description This form is for adding/editing an inventory
*/ */
angular.module('InventoryFormDefinition', [])
.value('InventoryForm', {
addTitle: 'Create Inventory', export default
editTitle: '{{ inventory_name }}', angular.module('InventoryFormDefinition', [])
name: 'inventory', .value('InventoryForm', {
well: true,
actions: { addTitle: 'Create Inventory',
stream: { editTitle: '{{ inventory_name }}',
'class': "btn-primary btn-xs activity-btn", name: 'inventory',
ngClick: "showActivity()", well: true,
awToolTip: "View Activity Stream",
dataPlacement: "top",
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
}
},
fields: { actions: {
inventory_name: { stream: {
realName: 'name', 'class': "btn-primary btn-xs activity-btn",
label: 'Name', ngClick: "showActivity()",
type: 'text', awToolTip: "View Activity Stream",
addRequired: true, dataPlacement: "top",
editRequired: true, icon: "icon-comments-alt",
capitalize: false mode: 'edit',
}, iconSize: 'large'
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"
} }
}, },
variables: {
label: 'Variables',
type: 'textarea',
'class': 'span12',
addRequired: false,
editRequird: false,
rows: 6,
"default": "---",
awPopOver: "<p>Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n" +
'<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p>' +
'<p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">docs.ansible.com</a></p>',
dataTitle: 'Inventory Variables',
dataPlacement: 'right',
dataContainer: 'body'
}
},
buttons: { fields: {
save: { inventory_name: {
ngClick: 'formSave()', realName: 'name',
ngDisabled: true label: 'Name',
type: 'text',
addRequired: true,
editRequired: true,
capitalize: false
},
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"
}
},
variables: {
label: 'Variables',
type: 'textarea',
'class': 'span12',
addRequired: false,
editRequird: false,
rows: 6,
"default": "---",
awPopOver: "<p>Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n" +
'<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p>' +
'<p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">docs.ansible.com</a></p>',
dataTitle: 'Inventory Variables',
dataPlacement: 'right',
dataContainer: 'body'
}
}, },
reset: {
ngClick: 'formReset()', buttons: {
ngDisabled: true save: {
ngClick: 'formSave()',
ngDisabled: true
},
reset: {
ngClick: 'formReset()',
ngDisabled: true
}
},
related: {
} }
},
related: { });
}
});

View File

@@ -11,51 +11,52 @@
* @name forms.function:InventoryStatus * @name forms.function:InventoryStatus
* @description This form is for adding/editing an InventoryStatus * @description This form is for adding/editing an InventoryStatus
*/ */
angular.module('InventoryStatusDefinition', []) export default
.value('InventoryStatusForm', { angular.module('InventoryStatusDefinition', [])
.value('InventoryStatusForm', {
name: 'inventory_update', name: 'inventory_update',
editTitle: 'Inventory Status', editTitle: 'Inventory Status',
well: false, well: false,
'class': 'horizontal-narrow', 'class': 'horizontal-narrow',
fields: { fields: {
license_error: { license_error: {
type: 'alertblock', type: 'alertblock',
'class': 'alert-info', 'class': 'alert-info',
alertTxt: 'The invenvtory update process exceeded the available number of licensed hosts. ' + alertTxt: 'The invenvtory update process exceeded the available number of licensed hosts. ' +
'<strong><a ng-click=\"viewLicense()\" href=\"\">View your license</a></strong> ' + '<strong><a ng-click=\"viewLicense()\" href=\"\">View your license</a></strong> ' +
'for more information.', 'for more information.',
ngShow: 'license_error', ngShow: 'license_error',
closeable: true closeable: true
}, },
created: { created: {
label: 'Created', label: 'Created',
type: 'text', type: 'text',
readonly: true readonly: true
}, },
status: { status: {
label: 'Status', label: 'Status',
type: 'text', type: 'text',
readonly: true, readonly: true,
'class': 'nowrap mono-space resizable', 'class': 'nowrap mono-space resizable',
rows: '{{ status_rows }}' rows: '{{ status_rows }}'
}, },
result_stdout: { result_stdout: {
label: 'Std Out', label: 'Std Out',
type: 'textarea', type: 'textarea',
ngShow: 'result_stdout', ngShow: 'result_stdout',
'class': 'nowrap mono-space resizable', 'class': 'nowrap mono-space resizable',
readonly: true, readonly: true,
rows: '{{ stdout_rows }}' rows: '{{ stdout_rows }}'
}, },
result_traceback: { result_traceback: {
label: 'Traceback', label: 'Traceback',
type: 'textarea', type: 'textarea',
ngShow: 'result_traceback', ngShow: 'result_traceback',
'class': 'nowrap mono-space resizable', 'class': 'nowrap mono-space resizable',
readonly: true, readonly: true,
rows: '{{ traceback_rows }}' rows: '{{ traceback_rows }}'
}
} }
} }); //Form
}); //Form

View File

@@ -11,22 +11,24 @@
* @name forms.function:JobEventData * @name forms.function:JobEventData
* @description Not sure if this is used... * @description Not sure if this is used...
*/ */
angular.module('JobEventDataDefinition', [])
.value('JobEventDataForm', {
editTitle: '{{ id }} - {{ event_display }}', export default
name: 'job_events', angular.module('JobEventDataDefinition', [])
well: false, .value('JobEventDataForm', {
'class': 'horizontal-narrow',
fields: { editTitle: '{{ id }} - {{ event_display }}',
event_data: { name: 'job_events',
label: false, well: false,
type: 'textarea', 'class': 'horizontal-narrow',
readonly: true,
rows: 18, fields: {
'class': 'modal-input-xxlarge' event_data: {
label: false,
type: 'textarea',
readonly: true,
rows: 18,
'class': 'modal-input-xxlarge'
}
} }
}
}); //Form }); //Form

View File

@@ -12,43 +12,44 @@
* @description Display job status info in a dialog * @description Display job status info in a dialog
*/ */
angular.module('JobSummaryDefinition', []) export default
.value('JobSummary', { angular.module('JobSummaryDefinition', [])
.value('JobSummary', {
editTitle: '{{ id }} - {{ name }}', editTitle: '{{ id }} - {{ name }}',
name: 'jobs', name: 'jobs',
well: false, well: false,
fields: { fields: {
status: { status: {
//label: 'Job Status', //label: 'Job Status',
type: 'custom', type: 'custom',
control: '<div class=\"job-detail-status\"><span style="padding-right: 15px; font-weight: bold;">Status</span> ' + control: '<div class=\"job-detail-status\"><span style="padding-right: 15px; font-weight: bold;">Status</span> ' +
'<i class=\"fa icon-job-{{ status }}\"></i> {{ status }}</div>', '<i class=\"fa icon-job-{{ status }}\"></i> {{ status }}</div>',
readonly: true readonly: true
}, },
created: { created: {
label: 'Created On', label: 'Created On',
type: 'text', type: 'text',
readonly: true readonly: true
}, },
result_stdout: { result_stdout: {
label: 'Standard Out', label: 'Standard Out',
type: 'textarea', type: 'textarea',
readonly: true, readonly: true,
xtraWide: true, xtraWide: true,
rows: '{{ stdout_rows }}', rows: '{{ stdout_rows }}',
'class': 'nowrap mono-space resizable', 'class': 'nowrap mono-space resizable',
ngShow: 'result_stdout != ""' ngShow: 'result_stdout != ""'
}, },
result_traceback: { result_traceback: {
label: 'Traceback', label: 'Traceback',
type: 'textarea', type: 'textarea',
xtraWide: true, xtraWide: true,
readonly: true, readonly: true,
rows: '{{ traceback_rows }}', rows: '{{ traceback_rows }}',
'class': 'nowrap mono-space resizable', 'class': 'nowrap mono-space resizable',
ngShow: 'result_traceback != ""' ngShow: 'result_traceback != ""'
}
} }
} });
});

View File

@@ -12,376 +12,376 @@
* @name forms.function:JobTemplate * @name forms.function:JobTemplate
* @description This form is for adding/editing a Job Template * @description This form is for adding/editing a Job Template
*/ */
'use strict';
angular.module('JobTemplateFormDefinition', ['SchedulesListDefinition', 'CompletedJobsDefinition']) export default
angular.module('JobTemplateFormDefinition', ['SchedulesListDefinition', 'CompletedJobsDefinition'])
.value ('JobTemplateFormObject', { .value ('JobTemplateFormObject', {
addTitle: 'Create Job Templates', addTitle: 'Create Job Templates',
editTitle: '{{ name }}', editTitle: '{{ name }}',
name: 'job_templates', name: 'job_templates',
twoColumns: true, twoColumns: true,
well: true, well: true,
base: 'job_templates', base: 'job_templates',
collapse: true, collapse: true,
collapseTitle: "Properties", collapseTitle: "Properties",
collapseMode: 'edit', collapseMode: 'edit',
collapseOpenFirst: true, //Always open first panel collapseOpenFirst: true, //Always open first panel
actions: { actions: {
// submit: { // submit: {
// ngClick: 'launch()', // ngClick: 'launch()',
// awToolTip: 'Start a job using this template', // awToolTip: 'Start a job using this template',
// dataPlacement: 'top', // dataPlacement: 'top',
// mode: 'edit' // mode: 'edit'
// }, // },
stream: { stream: {
'class': "btn-primary btn-xs activity-btn", 'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
dataPlacement: "top", dataPlacement: "top",
icon: "icon-comments-alt", icon: "icon-comments-alt",
mode: 'edit', mode: 'edit',
iconSize: 'large' iconSize: 'large'
} }
}, },
fields: { fields: {
name: { name: {
label: 'Name', label: 'Name',
type: 'text', type: 'text',
addRequired: true, addRequired: true,
editRequired: true, editRequired: true,
column: 1 column: 1
},
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 track by type.value',
"default": 0,
addRequired: true,
editRequired: true,
column: 1,
awPopOver: "<p>When this template is submitted as a job, setting the type to <em>run</em> will execute the playbook, running tasks " +
" on the selected hosts.</p> <p>Setting the type to <em>check</em> will not execute the playbook. Instead, ansible will check playbook " +
" syntax, test environment setup and report problems.</p>",
dataTitle: 'Job Type',
dataPlacement: 'right',
dataContainer: "body"
},
inventory: {
label: 'Inventory',
type: 'lookup',
sourceModel: 'inventory',
sourceField: 'name',
ngClick: 'lookUpInventory()',
awRequiredWhen: {variable: "inventoryrequired", init: "true" },
column: 1,
awPopOver: "<p>Select the inventory containing the hosts you want this job to manage.</p>",
dataTitle: 'Inventory',
dataPlacement: 'right',
dataContainer: "body"
},
project: {
label: 'Project',
type: 'lookup',
sourceModel: 'project',
sourceField: 'name',
ngClick: 'lookUpProject()',
awRequiredWhen: {variable: "projectrequired", init: "true" },
column: 1,
awPopOver: "<p>Select the project containing the playbook you want this job to execute.</p>",
dataTitle: 'Project',
dataPlacement: 'right',
dataContainer: "body"
},
playbook: {
label: 'Playbook',
type:'select',
ngOptions: 'book for book in playbook_options track by book',
id: 'playbook-select',
awRequiredWhen: {variable: "playbookrequired", init: "true" },
column: 1,
awPopOver: "<p>Select the playbook to be executed by this job.</p>",
dataTitle: 'Playbook',
dataPlacement: 'right',
dataContainer: "body"
},
credential: {
label: 'Machine Credential',
type: 'lookup',
sourceModel: 'credential',
sourceField: 'name',
ngClick: 'lookUpCredential()',
addRequired: false,
editRequired: false,
column: 1,
awPopOver: "<p>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.</p>",
dataTitle: 'Credential',
dataPlacement: 'right',
dataContainer: "body"
},
cloud_credential: {
label: 'Cloud Credential',
type: 'lookup',
sourceModel: 'cloud_credential',
sourceField: 'name',
ngClick: 'lookUpCloudcredential()',
addRequired: false,
editRequired: false,
column: 1,
awPopOver: "<p>Selecting an optional cloud credential in the job template will pass along the access credentials to the " +
"running playbook, allowing provisioning into the cloud without manually passing parameters to the included modules.</p>",
dataTitle: 'Cloud Credential',
dataPlacement: 'right',
dataContainer: "body"
},
forks: {
label: 'Forks',
id: 'forks-number',
type: 'number',
integer: true,
min: 0,
spinner: true,
"default": '0',
addRequired: false,
editRequired: false,
'class': "input-small",
column: 1,
awPopOver: '<p>The number of parallel or simultaneous processes to use while executing the playbook. 0 signifies ' +
'the default value from the <a href=\"http://docs.ansible.com/intro_configuration.html#the-ansible-configuration-file\" ' +
' target=\"_blank\">ansible configuration file</a>.</p>',
dataTitle: 'Forks',
dataPlacement: 'right',
dataContainer: "body"
},
limit: {
label: 'Limit',
type: 'text',
addRequired: false,
editRequired: false,
column: 1,
awPopOver: "<p>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 &#59; &#58; or &#44;</p><p>For more information and examples see " +
"<a href=\"http://docs.ansible.com/intro_patterns.html\" target=\"_blank\">the Patterns topic at docs.ansible.com</a>.</p>",
dataTitle: 'Limit',
dataPlacement: 'right',
dataContainer: "body"
},
verbosity: {
label: 'Verbosity',
type: 'select',
ngOptions: 'v.label for v in verbosity_options track by v.value',
"default": 0,
addRequired: true,
editRequired: true,
column: 1,
awPopOver: "<p>Control the level of output ansible will produce as the playbook executes.</p>",
dataTitle: 'Verbosity',
dataPlacement: 'right',
dataContainer: "body"
},
job_tags: {
label: 'Job Tags',
type: 'textarea',
rows: 1,
addRequired: false,
editRequired: false,
'class': 'span12',
column: 2,
awPopOver: "<p>Provide a comma separated list of tags.</p>\n" +
"<p>Tags are useful when you have a large playbook, and you want to run a specific part of a play or task.</p>" +
"<p>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 &quot;configuration&quot;, &quot;packages&quot; and &quot;install&quot;.</p>" +
"<p>If you just want to run the &quot;configuration&quot; and &quot;packages&quot; actions, you would enter the following here " +
"in the Job Tags field:</p>\n<blockquote>configuration,packages</blockquote>\n",
dataTitle: "Job Tags",
dataPlacement: "right",
dataContainer: "body"
},
variables: {
label: 'Extra Variables',
type: 'textarea',
rows: 6,
"class": 'span12',
addRequired: false,
editRequired: false,
"default": "---",
column: 2,
awPopOver: "<p>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.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n",
dataTitle: 'Extra Variables',
dataPlacement: 'right',
dataContainer: "body"
},
ask_variables_on_launch: {
label: 'Prompt for Extra Variables',
type: 'checkbox',
addRequired: false,
editRequird: false,
trueValue: 'true',
falseValue: 'false',
column: 2,
awPopOver: "<p>If checked, user will be prompted at job launch with a dialog allowing override of the extra variables setting.</p>",
dataPlacement: 'right',
dataTitle: 'Prompt for Extra Variables',
dataContainer: "body"
},
// survey_enabled: {
// type: 'custom',
// column: 2,
// control: '<div class="form-group">'+
// '<div class="checkbox">'+
// '<label><input type="checkbox" ng-model="survey_enabled" name="survey_enabled" id="job_templates_survey_enabled_chbox" class="ng-valid ng-valid-api-error ng-dirty" ng-true-value="true" ng-false-value="false">'+
// '<span class="label-text">Enable Survey</span><a id="awp-survey_enabled" href="" aw-pop-over="<p>If checked, user will be prompted at job launch with a survey of questions related to the job.</p>'+
// '<div class=&quot;popover-footer&quot;><span class=&quot;key&quot;>esc</span> or click to close</div>" data-placement="right" data-container="body" data-title="Enable Survey" class="help-link" data-original-title="" title="" tabindex="-1">'+
// '<i class="fa fa-question-circle"></i></a> </label>'+
// '<div class="error api-error ng-binding" id="job_templates-survey_enabled-api-error" ng-bind="survey_enabled_api_error"></div>'+
// '<button type="button" class="btn btn-sm btn-default" id="job_templates_edit_survey_btn" ng-click="navigateToSurvey()"><i class="fa fa-pencil"></i> Create Survey</button>'+
// '</div>'+
// '</div>'
// },
survey_enabled: {
label: 'Enable Survey',
type: 'checkbox',
addRequired: false,
editRequird: false,
// trueValue: true,
// falseValue: false,
ngChange: "surveyEnabled()",
column: 2,
awPopOver: "<p>If checked, user will be prompted at job launch with a series of questions related to the job.</p>",
dataPlacement: 'right',
dataTitle: 'Enable Survey',
dataContainer: "body"
},
create_survey: {
type: 'custom',
column: 2,
control: '<button type="button" class="btn btn-sm btn-primary" id="job_templates_create_survey_btn" ng-show="survey_enabled" ng-click="addSurvey()"><i class="fa fa-pencil"></i> Create Survey</button>'+
'<button style="display:none;" type="button" class="btn btn-sm btn-primary" id="job_templates_edit_survey_btn" ng-show="survey_enabled" ng-click="editSurvey()"><i class="fa fa-pencil"></i> Edit Survey</button>'+
'<button style="display:none;margin-left:5px" type="button" class="btn btn-sm btn-primary" id="job_templates_delete_survey_btn" ng-show="survey_enabled" ng-click="deleteSurvey()"><i class="fa fa-trash-o"></i> Delete Survey</button>'
// label: 'Create Survey',
// type: 'text',
// addRequired: false,
// editRequired: false,
// // readonly: true,
// // ngShow: "survey_enabled",
// column: 2,
// awPopOver: "survey_help",
// awPopOverWatch: "survey_help",
// dataPlacement: 'right',
// dataTitle: 'Provisioning Callback URL',
// dataContainer: "body"
},
allow_callbacks: {
label: 'Allow Provisioning Callbacks',
type: 'checkbox',
addRequired: false,
editRequird: false,
trueValue: 'true',
falseValue: 'false',
ngChange: "toggleCallback('host_config_key')",
column: 2,
awPopOver: "<p>Enables creation of a provisioning callback URL. Using the URL a host can contact Tower and request a configuration update " +
"using this job template.</p>",
dataPlacement: 'right',
dataTitle: 'Allow Provisioning Callbacks',
dataContainer: "body"
},
callback_url: {
label: 'Provisioning Callback URL',
type: 'text',
addRequired: false,
editRequired: false,
readonly: true,
ngShow: "allow_callbacks",
column: 2,
awPopOver: "callback_help",
awPopOverWatch: "callback_help",
dataPlacement: 'right',
dataTitle: 'Provisioning Callback URL',
dataContainer: "body"
},
host_config_key: {
label: 'Host Config Key',
type: 'text',
ngShow: "allow_callbacks",
ngChange: "configKeyChange()",
genMD5: true,
column: 2,
awPopOver: "callback_help",
awPopOverWatch: "callback_help",
dataPlacement: 'right',
dataTitle: "Host Config Key",
dataContainer: "body"
}
},
buttons: { //for now always generates <button> tags
save: {
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: "job_templates_form.$invalid || can_edit!==true"//true //Disable when $pristine or $invalid, optional and when can_edit = false, for permission reasons
},
reset: {
ngClick: 'formReset()',
ngDisabled: true //Disabled when $pristine
}
},
related: {
schedules: {
include: "SchedulesList"
},
"completed_jobs": {
include: "CompletedJobsList"
}
},
relatedSets: function(urls) {
return {
completed_jobs: {
iterator: 'completed_job',
url: urls.jobs + '?or__status=successful&or__status=failed&or__status=error&or__status=canceled'
}, },
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 track by type.value',
"default": 0,
addRequired: true,
editRequired: true,
column: 1,
awPopOver: "<p>When this template is submitted as a job, setting the type to <em>run</em> will execute the playbook, running tasks " +
" on the selected hosts.</p> <p>Setting the type to <em>check</em> will not execute the playbook. Instead, ansible will check playbook " +
" syntax, test environment setup and report problems.</p>",
dataTitle: 'Job Type',
dataPlacement: 'right',
dataContainer: "body"
},
inventory: {
label: 'Inventory',
type: 'lookup',
sourceModel: 'inventory',
sourceField: 'name',
ngClick: 'lookUpInventory()',
awRequiredWhen: {variable: "inventoryrequired", init: "true" },
column: 1,
awPopOver: "<p>Select the inventory containing the hosts you want this job to manage.</p>",
dataTitle: 'Inventory',
dataPlacement: 'right',
dataContainer: "body"
},
project: {
label: 'Project',
type: 'lookup',
sourceModel: 'project',
sourceField: 'name',
ngClick: 'lookUpProject()',
awRequiredWhen: {variable: "projectrequired", init: "true" },
column: 1,
awPopOver: "<p>Select the project containing the playbook you want this job to execute.</p>",
dataTitle: 'Project',
dataPlacement: 'right',
dataContainer: "body"
},
playbook: {
label: 'Playbook',
type:'select',
ngOptions: 'book for book in playbook_options track by book',
id: 'playbook-select',
awRequiredWhen: {variable: "playbookrequired", init: "true" },
column: 1,
awPopOver: "<p>Select the playbook to be executed by this job.</p>",
dataTitle: 'Playbook',
dataPlacement: 'right',
dataContainer: "body"
},
credential: {
label: 'Machine Credential',
type: 'lookup',
sourceModel: 'credential',
sourceField: 'name',
ngClick: 'lookUpCredential()',
addRequired: false,
editRequired: false,
column: 1,
awPopOver: "<p>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.</p>",
dataTitle: 'Credential',
dataPlacement: 'right',
dataContainer: "body"
},
cloud_credential: {
label: 'Cloud Credential',
type: 'lookup',
sourceModel: 'cloud_credential',
sourceField: 'name',
ngClick: 'lookUpCloudcredential()',
addRequired: false,
editRequired: false,
column: 1,
awPopOver: "<p>Selecting an optional cloud credential in the job template will pass along the access credentials to the " +
"running playbook, allowing provisioning into the cloud without manually passing parameters to the included modules.</p>",
dataTitle: 'Cloud Credential',
dataPlacement: 'right',
dataContainer: "body"
},
forks: {
label: 'Forks',
id: 'forks-number',
type: 'number',
integer: true,
min: 0,
spinner: true,
"default": '0',
addRequired: false,
editRequired: false,
'class': "input-small",
column: 1,
awPopOver: '<p>The number of parallel or simultaneous processes to use while executing the playbook. 0 signifies ' +
'the default value from the <a href=\"http://docs.ansible.com/intro_configuration.html#the-ansible-configuration-file\" ' +
' target=\"_blank\">ansible configuration file</a>.</p>',
dataTitle: 'Forks',
dataPlacement: 'right',
dataContainer: "body"
},
limit: {
label: 'Limit',
type: 'text',
addRequired: false,
editRequired: false,
column: 1,
awPopOver: "<p>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 &#59; &#58; or &#44;</p><p>For more information and examples see " +
"<a href=\"http://docs.ansible.com/intro_patterns.html\" target=\"_blank\">the Patterns topic at docs.ansible.com</a>.</p>",
dataTitle: 'Limit',
dataPlacement: 'right',
dataContainer: "body"
},
verbosity: {
label: 'Verbosity',
type: 'select',
ngOptions: 'v.label for v in verbosity_options track by v.value',
"default": 0,
addRequired: true,
editRequired: true,
column: 1,
awPopOver: "<p>Control the level of output ansible will produce as the playbook executes.</p>",
dataTitle: 'Verbosity',
dataPlacement: 'right',
dataContainer: "body"
},
job_tags: {
label: 'Job Tags',
type: 'textarea',
rows: 1,
addRequired: false,
editRequired: false,
'class': 'span12',
column: 2,
awPopOver: "<p>Provide a comma separated list of tags.</p>\n" +
"<p>Tags are useful when you have a large playbook, and you want to run a specific part of a play or task.</p>" +
"<p>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 &quot;configuration&quot;, &quot;packages&quot; and &quot;install&quot;.</p>" +
"<p>If you just want to run the &quot;configuration&quot; and &quot;packages&quot; actions, you would enter the following here " +
"in the Job Tags field:</p>\n<blockquote>configuration,packages</blockquote>\n",
dataTitle: "Job Tags",
dataPlacement: "right",
dataContainer: "body"
},
variables: {
label: 'Extra Variables',
type: 'textarea',
rows: 6,
"class": 'span12',
addRequired: false,
editRequired: false,
"default": "---",
column: 2,
awPopOver: "<p>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.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n",
dataTitle: 'Extra Variables',
dataPlacement: 'right',
dataContainer: "body"
},
ask_variables_on_launch: {
label: 'Prompt for Extra Variables',
type: 'checkbox',
addRequired: false,
editRequird: false,
trueValue: 'true',
falseValue: 'false',
column: 2,
awPopOver: "<p>If checked, user will be prompted at job launch with a dialog allowing override of the extra variables setting.</p>",
dataPlacement: 'right',
dataTitle: 'Prompt for Extra Variables',
dataContainer: "body"
},
// survey_enabled: {
// type: 'custom',
// column: 2,
// control: '<div class="form-group">'+
// '<div class="checkbox">'+
// '<label><input type="checkbox" ng-model="survey_enabled" name="survey_enabled" id="job_templates_survey_enabled_chbox" class="ng-valid ng-valid-api-error ng-dirty" ng-true-value="true" ng-false-value="false">'+
// '<span class="label-text">Enable Survey</span><a id="awp-survey_enabled" href="" aw-pop-over="<p>If checked, user will be prompted at job launch with a survey of questions related to the job.</p>'+
// '<div class=&quot;popover-footer&quot;><span class=&quot;key&quot;>esc</span> or click to close</div>" data-placement="right" data-container="body" data-title="Enable Survey" class="help-link" data-original-title="" title="" tabindex="-1">'+
// '<i class="fa fa-question-circle"></i></a> </label>'+
// '<div class="error api-error ng-binding" id="job_templates-survey_enabled-api-error" ng-bind="survey_enabled_api_error"></div>'+
// '<button type="button" class="btn btn-sm btn-default" id="job_templates_edit_survey_btn" ng-click="navigateToSurvey()"><i class="fa fa-pencil"></i> Create Survey</button>'+
// '</div>'+
// '</div>'
// },
survey_enabled: {
label: 'Enable Survey',
type: 'checkbox',
addRequired: false,
editRequird: false,
// trueValue: true,
// falseValue: false,
ngChange: "surveyEnabled()",
column: 2,
awPopOver: "<p>If checked, user will be prompted at job launch with a series of questions related to the job.</p>",
dataPlacement: 'right',
dataTitle: 'Enable Survey',
dataContainer: "body"
},
create_survey: {
type: 'custom',
column: 2,
control: '<button type="button" class="btn btn-sm btn-primary" id="job_templates_create_survey_btn" ng-show="survey_enabled" ng-click="addSurvey()"><i class="fa fa-pencil"></i> Create Survey</button>'+
'<button style="display:none;" type="button" class="btn btn-sm btn-primary" id="job_templates_edit_survey_btn" ng-show="survey_enabled" ng-click="editSurvey()"><i class="fa fa-pencil"></i> Edit Survey</button>'+
'<button style="display:none;margin-left:5px" type="button" class="btn btn-sm btn-primary" id="job_templates_delete_survey_btn" ng-show="survey_enabled" ng-click="deleteSurvey()"><i class="fa fa-trash-o"></i> Delete Survey</button>'
// label: 'Create Survey',
// type: 'text',
// addRequired: false,
// editRequired: false,
// // readonly: true,
// // ngShow: "survey_enabled",
// column: 2,
// awPopOver: "survey_help",
// awPopOverWatch: "survey_help",
// dataPlacement: 'right',
// dataTitle: 'Provisioning Callback URL',
// dataContainer: "body"
},
allow_callbacks: {
label: 'Allow Provisioning Callbacks',
type: 'checkbox',
addRequired: false,
editRequird: false,
trueValue: 'true',
falseValue: 'false',
ngChange: "toggleCallback('host_config_key')",
column: 2,
awPopOver: "<p>Enables creation of a provisioning callback URL. Using the URL a host can contact Tower and request a configuration update " +
"using this job template.</p>",
dataPlacement: 'right',
dataTitle: 'Allow Provisioning Callbacks',
dataContainer: "body"
},
callback_url: {
label: 'Provisioning Callback URL',
type: 'text',
addRequired: false,
editRequired: false,
readonly: true,
ngShow: "allow_callbacks",
column: 2,
awPopOver: "callback_help",
awPopOverWatch: "callback_help",
dataPlacement: 'right',
dataTitle: 'Provisioning Callback URL',
dataContainer: "body"
},
host_config_key: {
label: 'Host Config Key',
type: 'text',
ngShow: "allow_callbacks",
ngChange: "configKeyChange()",
genMD5: true,
column: 2,
awPopOver: "callback_help",
awPopOverWatch: "callback_help",
dataPlacement: 'right',
dataTitle: "Host Config Key",
dataContainer: "body"
}
},
buttons: { //for now always generates <button> tags
save: {
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: "job_templates_form.$invalid || can_edit!==true"//true //Disable when $pristine or $invalid, optional and when can_edit = false, for permission reasons
},
reset: {
ngClick: 'formReset()',
ngDisabled: true //Disabled when $pristine
}
},
related: {
schedules: { schedules: {
iterator: 'schedule', include: "SchedulesList"
url: urls.schedules },
"completed_jobs": {
include: "CompletedJobsList"
} }
}; },
}
})
.factory('JobTemplateForm', ['JobTemplateFormObject', 'SchedulesList', 'CompletedJobsList', relatedSets: function(urls) {
function(JobTemplateFormObject, SchedulesList, CompletedJobsList) { return {
return function() { completed_jobs: {
var itm; iterator: 'completed_job',
url: urls.jobs + '?or__status=successful&or__status=failed&or__status=error&or__status=canceled'
for (itm in JobTemplateFormObject.related) { },
if (JobTemplateFormObject.related[itm].include === "SchedulesList") { schedules: {
JobTemplateFormObject.related[itm] = SchedulesList; iterator: 'schedule',
JobTemplateFormObject.related[itm].generateList = true; // tell form generator to call list generator and inject a list url: urls.schedules
} }
if (JobTemplateFormObject.related[itm].include === "CompletedJobsList") { };
JobTemplateFormObject.related[itm] = CompletedJobsList;
JobTemplateFormObject.related[itm].generateList = true;
}
} }
})
return JobTemplateFormObject; .factory('JobTemplateForm', ['JobTemplateFormObject', 'SchedulesList', 'CompletedJobsList',
}; function(JobTemplateFormObject, SchedulesList, CompletedJobsList) {
}]); return function() {
var itm;
for (itm in JobTemplateFormObject.related) {
if (JobTemplateFormObject.related[itm].include === "SchedulesList") {
JobTemplateFormObject.related[itm] = SchedulesList;
JobTemplateFormObject.related[itm].generateList = true; // tell form generator to call list generator and inject a list
}
if (JobTemplateFormObject.related[itm].include === "CompletedJobsList") {
JobTemplateFormObject.related[itm] = CompletedJobsList;
JobTemplateFormObject.related[itm].generateList = true;
}
}
return JobTemplateFormObject;
};
}]);

View File

@@ -11,32 +11,32 @@
* @name forms.function:JobVarsPrompt * @name forms.function:JobVarsPrompt
* @description This form is for job variables prompt modal * @description This form is for job variables prompt modal
*/ */
'use strict';
angular.module('JobVarsPromptFormDefinition', []) export default
angular.module('JobVarsPromptFormDefinition', [])
.value ('JobVarsPromptForm', { .value ('JobVarsPromptForm', {
addTitle: '', addTitle: '',
editTitle: '', editTitle: '',
name: 'job', name: 'job',
well: false, well: false,
actions: { }, actions: { },
fields: { fields: {
extra_vars: { extra_vars: {
label: null, label: null,
type: 'textarea', type: 'textarea',
rows: 6, rows: 6,
addRequired: false, addRequired: false,
editRequired: false, editRequired: false,
"default": "---" "default": "---"
} }
}, },
buttons: { }, buttons: { },
related: { } related: { }
}); });

View File

@@ -11,108 +11,110 @@
* @name forms.function:Jobs * @name forms.function:Jobs
* @description This form is for adding/editing a Job * @description This form is for adding/editing a Job
*/ */
angular.module('JobFormDefinition', [])
.value('JobForm', {
addTitle: 'Create Job', export default
editTitle: '{{ id }} - {{ name }}', angular.module('JobFormDefinition', [])
name: 'jobs', .value('JobForm', {
well: true,
base: 'jobs',
collapse: true,
collapseMode: 'edit',
collapseTitle: 'Job Status',
collapseOpenFirst: true, //Always open first panel
navigationLinks: { addTitle: 'Create Job',
details: { editTitle: '{{ id }} - {{ name }}',
href: "/#/jobs/{{ job_id }}", name: 'jobs',
label: 'Status', well: true,
icon: 'icon-zoom-in', base: 'jobs',
active: true, collapse: true,
ngShow: "job_id !== null" collapseMode: 'edit',
collapseTitle: 'Job Status',
collapseOpenFirst: true, //Always open first panel
navigationLinks: {
details: {
href: "/#/jobs/{{ job_id }}",
label: 'Status',
icon: 'icon-zoom-in',
active: true,
ngShow: "job_id !== null"
},
events: {
href: "/#/jobs/{{ job_id }}/job_events",
label: 'Events',
icon: 'icon-list-ul'
},
hosts: {
href: "/#/jobs/{{ job_id }}/job_host_summaries",
label: 'Host Summary',
icon: 'icon-laptop'
}
}, },
events: {
href: "/#/jobs/{{ job_id }}/job_events", fields: {
label: 'Events', status: {
icon: 'icon-list-ul' type: 'custom',
control: "<i class=\"fa icon-job-{{ status }}\"></i> &nbsp;{{ job_explanation }}",
readonly: true
},
result_stdout: {
label: 'Standard Out',
type: 'textarea',
readonly: true,
xtraWide: true,
rows: "{{ stdout_rows }}",
"class": 'nowrap mono-space allowresize',
ngShow: "result_stdout != ''"
},
result_traceback: {
label: 'Traceback',
type: 'textarea',
xtraWide: true,
readonly: true,
rows: "{{ traceback_rows }}",
"class": 'nowrap mono-space allowresize',
ngShow: "result_traceback != ''"
},
type: {
label: 'Job Type',
type: 'text',
readonly: true
},
launch_type: {
label: 'Launch Type',
type: 'text',
readonly: true
},
created: {
label: 'Created On',
type: 'text',
readonly: true
},
modified: {
label: 'Last Updated',
type: 'text',
readonly: true
}
}, },
hosts: {
href: "/#/jobs/{{ job_id }}/job_host_summaries", actions: {
label: 'Host Summary', refresh: {
icon: 'icon-laptop' dataPlacement: 'top',
icon: "icon-refresh",
iconSize: 'large',
mode: 'all',
//ngShow: "job_status == 'pending' || job_status == 'waiting' || job_status == 'running'",
'class': 'btn-xs btn-primary',
awToolTip: "Refresh the page",
ngClick: "refresh()"
}
},
related: {
job_template: {
type: 'collection',
title: 'Job Tempate',
iterator: 'job',
index: false,
open: false,
fields: { }
}
} }
},
fields: { });
status: {
type: 'custom',
control: "<i class=\"fa icon-job-{{ status }}\"></i> &nbsp;{{ job_explanation }}",
readonly: true
},
result_stdout: {
label: 'Standard Out',
type: 'textarea',
readonly: true,
xtraWide: true,
rows: "{{ stdout_rows }}",
"class": 'nowrap mono-space allowresize',
ngShow: "result_stdout != ''"
},
result_traceback: {
label: 'Traceback',
type: 'textarea',
xtraWide: true,
readonly: true,
rows: "{{ traceback_rows }}",
"class": 'nowrap mono-space allowresize',
ngShow: "result_traceback != ''"
},
type: {
label: 'Job Type',
type: 'text',
readonly: true
},
launch_type: {
label: 'Launch Type',
type: 'text',
readonly: true
},
created: {
label: 'Created On',
type: 'text',
readonly: true
},
modified: {
label: 'Last Updated',
type: 'text',
readonly: true
}
},
actions: {
refresh: {
dataPlacement: 'top',
icon: "icon-refresh",
iconSize: 'large',
mode: 'all',
//ngShow: "job_status == 'pending' || job_status == 'waiting' || job_status == 'running'",
'class': 'btn-xs btn-primary',
awToolTip: "Refresh the page",
ngClick: "refresh()"
}
},
related: {
job_template: {
type: 'collection',
title: 'Job Tempate',
iterator: 'job',
index: false,
open: false,
fields: { }
}
}
});

View File

@@ -10,73 +10,74 @@
* @name forms.function:LicenseForm * @name forms.function:LicenseForm
* @description This form is for viewing the license information * @description This form is for viewing the license information
*/ */
'use strict';
angular.module('LicenseFormDefinition', [])
.value('LicenseForm', {
name: 'license', export default
well: false, angular.module('LicenseFormDefinition', [])
.value('LicenseForm', {
tabs: [{
name: 'license', name: 'license',
label: 'License' well: false,
}, {
name: 'managed',
label: 'Managed Hosts'
}],
fields: { tabs: [{
license_status: { name: 'license',
type: 'custom', label: 'License'
control: "<div class=\"license-status\" ng-class=\"status_color\"><i class=\"fa fa-circle\"></i> {{ license_status }}</div>", }, {
readonly: true, name: 'managed',
tab: 'license' label: 'Managed Hosts'
}, }],
tower_version: {
label: 'Tower Version', fields: {
type: 'text', license_status: {
readonly: true, type: 'custom',
tab: 'license' control: "<div class=\"license-status\" ng-class=\"status_color\"><i class=\"fa fa-circle\"></i> {{ license_status }}</div>",
}, readonly: true,
license_key: { tab: 'license'
label: 'License Key', },
type: 'textarea', tower_version: {
'class': 'modal-input-xlarge', label: 'Tower Version',
readonly: true, type: 'text',
tab: 'license' readonly: true,
}, tab: 'license'
license_date: { },
label: 'Expires On', license_key: {
type: 'text', label: 'License Key',
readonly: true, type: 'textarea',
tab: 'license' 'class': 'modal-input-xlarge',
}, readonly: true,
time_remaining: { tab: 'license'
label: 'Time Remaining', },
type: 'text', license_date: {
readonly: true, label: 'Expires On',
tab: 'license' type: 'text',
}, readonly: true,
available_instances: { tab: 'license'
label: 'Available', },
type: 'text', time_remaining: {
readonly: true, label: 'Time Remaining',
tab: 'managed' type: 'text',
}, readonly: true,
current_instances: { tab: 'license'
label: 'Used', },
type: 'text', available_instances: {
readonly: true, label: 'Available',
tab: 'managed' type: 'text',
}, readonly: true,
free_instances: { tab: 'managed'
label: 'Remaining', },
type: 'text', current_instances: {
readonly: true, label: 'Used',
controlNGClass: 'free_instances_class', type: 'text',
labelNGClass: 'free_instances_class', readonly: true,
tab: 'managed' tab: 'managed'
},
free_instances: {
label: 'Remaining',
type: 'text',
readonly: true,
controlNGClass: 'free_instances_class',
labelNGClass: 'free_instances_class',
tab: 'managed'
}
} }
} });
});

View File

@@ -11,45 +11,47 @@
* @name forms.function:LicenseUpdate * @name forms.function:LicenseUpdate
* @description This form is for updating a license * @description This form is for updating a license
*/ */
angular.module('LicenseUpdateFormDefinition', [])
.value('LicenseUpdateForm', {
name: 'license', export default
well: false, angular.module('LicenseUpdateFormDefinition', [])
.value('LicenseUpdateForm', {
fields: { name: 'license',
license_json: { well: false,
label: 'License File',
type: 'textarea', fields: {
addRequired: true, license_json: {
editRequird: true, label: 'License File',
rows: 10, type: 'textarea',
'default': '---' addRequired: true,
editRequird: true,
rows: 10,
'default': '---'
},
eula: {
label: 'End User License Agreement',
type: 'textarea',
addRequired: true,
editRequird: true,
rows: 5,
readonly: true
},
eula_agreement: {
label: 'I agree to the End User License Agreement',
type: 'checkbox',
addRequired: true,
editRequird: true
}
}, },
eula: { buttons: {
label: 'End User License Agreement', form_submit: {
type: 'textarea', label: "Submit",
addRequired: true, "class": "pull-right btn-primary",
editRequird: true, ngClick: "submitLicenseKey()",
rows: 5, // ngDisabled: "true"
readonly: true }
}, },
eula_agreement: {
label: 'I agree to the End User License Agreement',
type: 'checkbox',
addRequired: true,
editRequird: true
}
},
buttons: {
form_submit: {
label: "Submit",
"class": "pull-right btn-primary",
ngClick: "submitLicenseKey()",
// ngDisabled: "true"
}
},
related: { } related: { }
}); //LicenseUpdateForm }); //LicenseUpdateForm

View File

@@ -11,92 +11,94 @@
* @name forms.function:LogViewerOptions * @name forms.function:LogViewerOptions
* @description This form is for the page to view logs * @description This form is for the page to view logs
*/ */
angular.module('LogViewerOptionsDefinition', [])
.value('LogViewerOptionsForm', {
name: 'status', export default
well: false, angular.module('LogViewerOptionsDefinition', [])
.value('LogViewerOptionsForm', {
fields: { name: 'status',
"job_template": { well: false,
label: "Job Template",
type: "text", fields: {
readonly: true "job_template": {
}, label: "Job Template",
"inventory": { type: "text",
label: "Inventory", readonly: true
type: "text", },
readonly: true "inventory": {
}, label: "Inventory",
"project": { type: "text",
label: "Project", readonly: true
type: "text", },
readonly: true "project": {
}, label: "Project",
"playbook": { type: "text",
label: "Playbook", readonly: true
type: "text", },
readonly: true "playbook": {
}, label: "Playbook",
"credential": { type: "text",
label: "Credential", readonly: true
type: "text", },
readonly: true "credential": {
}, label: "Credential",
"cloud credential": { type: "text",
label: "Cloud Cred.", readonly: true
type: "text", },
readonly: true "cloud credential": {
}, label: "Cloud Cred.",
"forks": { type: "text",
label: "Forks", readonly: true
type: "text", },
readonly: true "forks": {
}, label: "Forks",
"limit": { type: "text",
label: "Limit", readonly: true
type: "text", },
readonly: true "limit": {
}, label: "Limit",
"verbosity": { type: "text",
label: "Verbosity", readonly: true
type: "text", },
readonly: true "verbosity": {
}, label: "Verbosity",
"job_tags": { type: "text",
label: "Job Tags", readonly: true
type: "text", },
readonly: true "job_tags": {
}, label: "Job Tags",
"inventory_source": { type: "text",
label: "Group", readonly: true
type: "text", },
readonly: true "inventory_source": {
}, label: "Group",
"source": { type: "text",
label: "Source", readonly: true
type: "text", },
readonly: true "source": {
}, label: "Source",
"source_path": { type: "text",
label: "Source Path", readonly: true
type: "text", },
readonly: true "source_path": {
}, label: "Source Path",
"source_regions":{ type: "text",
label: "Regions", readonly: true
type: "text", },
readonly: true "source_regions":{
}, label: "Regions",
"overwrite": { type: "text",
label: "Overwrite", readonly: true
type: "text", },
readonly: true "overwrite": {
}, label: "Overwrite",
"overwrite_vars": { type: "text",
label: "Overwrite Vars", readonly: true
type: "text", },
readonly: true "overwrite_vars": {
label: "Overwrite Vars",
type: "text",
readonly: true
}
} }
} });
});

View File

@@ -11,50 +11,52 @@
* @name forms.function:LogViewerStatus * @name forms.function:LogViewerStatus
* @description Form definition for LogViewer.js helper * @description Form definition for LogViewer.js helper
*/ */
angular.module('LogViewerStatusDefinition', [])
.value('LogViewerStatusForm', {
name: 'status', export default
well: false, angular.module('LogViewerStatusDefinition', [])
.value('LogViewerStatusForm', {
fields: { name: 'status',
"name": { well: false,
label: "Name",
type: "text", fields: {
readonly: true, "name": {
}, label: "Name",
"status": { type: "text",
label: "Status", readonly: true,
type: "text", },
readonly: true "status": {
}, label: "Status",
"license_error": { type: "text",
label: "License Error", readonly: true
type: "text", },
readonly: true "license_error": {
}, label: "License Error",
"started": { type: "text",
label: "Started", readonly: true
type: "date", },
"filter": "date:'MM/dd/yy HH:mm:ss'", "started": {
readonly: true label: "Started",
}, type: "date",
"finished": { "filter": "date:'MM/dd/yy HH:mm:ss'",
label: "Finished", readonly: true
type: "date", },
"filter": "date:'MM/dd/yy HH:mm:ss'", "finished": {
readonly: true label: "Finished",
}, type: "date",
"elapsed": { "filter": "date:'MM/dd/yy HH:mm:ss'",
label: "Elapsed", readonly: true
type: "text", },
readonly: true "elapsed": {
}, label: "Elapsed",
"launch_type": { type: "text",
label: "Launch Type", readonly: true
type: "text", },
readonly: true "launch_type": {
label: "Launch Type",
type: "text",
readonly: true
}
} }
}
}); });

View File

@@ -11,151 +11,153 @@
* @name forms.function:Organizations * @name forms.function:Organizations
* @description This form is for adding/editing an organization * @description This form is for adding/editing an organization
*/ */
angular.module('OrganizationFormDefinition', [])
.value('OrganizationForm', {
addTitle: 'Create Organization', //Title in add mode export default
editTitle: '{{ name }}', //Title in edit mode angular.module('OrganizationFormDefinition', [])
name: 'organization', //entity or model name in singular form .value('OrganizationForm', {
well: true,
collapse: true,
collapseTitle: "Properties",
collapseMode: 'edit',
collapseOpen: true,
actions: { addTitle: 'Create Organization', //Title in add mode
stream: { editTitle: '{{ name }}', //Title in edit mode
'class': "btn-primary btn-xs activity-btn", name: 'organization', //entity or model name in singular form
ngClick: "showActivity()", well: true,
awToolTip: "View Activity Stream", collapse: true,
dataPlacement: "top", collapseTitle: "Properties",
icon: "icon-comments-alt", collapseMode: 'edit',
mode: 'edit', collapseOpen: true,
iconSize: 'large'
}
},
fields: { actions: {
name: { stream: {
label: 'Name', 'class': "btn-primary btn-xs activity-btn",
type: 'text', ngClick: "showActivity()",
addRequired: true, awToolTip: "View Activity Stream",
editRequired: true, dataPlacement: "top",
capitalize: false icon: "icon-comments-alt",
}, mode: 'edit',
description: { iconSize: 'large'
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
}
},
buttons: { //for now always generates <button> 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: {
users: {
type: 'collection',
title: 'Users',
iterator: 'user',
index: false,
open: false,
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) fields: {
type: 'collection', name: {
title: 'Administrators', label: 'Name',
iterator: 'admin', // Singular form of name (e.g. thing) type: 'text',
index: false, addRequired: true,
open: false, // Open accordion on load? editRequired: true,
base: '/users', capitalize: false
actions: { // Actions displayed top right of list },
add: { description: {
ngClick: "add('admins')", label: 'Description',
icon: 'icon-plus', type: 'text',
label: 'Add', addRequired: false,
awToolTip: 'Add new administrator' editRequired: false
}
},
buttons: { //for now always generates <button> 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: {
users: {
type: 'collection',
title: 'Users',
iterator: 'user',
index: false,
open: false,
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'
}
} }
}, },
fields: {
username: { admins: { // Assumes a plural name (e.g. things)
key: true, type: 'collection',
label: 'Username' title: 'Administrators',
iterator: 'admin', // Singular form of name (e.g. thing)
index: false,
open: false, // Open accordion on load?
base: '/users',
actions: { // Actions displayed top right of list
add: {
ngClick: "add('admins')",
icon: 'icon-plus',
label: 'Add',
awToolTip: 'Add new administrator'
}
}, },
first_name: { fields: {
label: 'First Name' username: {
key: true,
label: 'Username'
},
first_name: {
label: 'First Name'
},
last_name: {
label: 'Last Name'
}
}, },
last_name: { fieldActions: { // Actions available on each row
label: 'Last Name' edit: {
} label: 'Edit',
}, ngClick: "edit('users', admin.id, admin.username)",
fieldActions: { // Actions available on each row icon: 'icon-edit',
edit: { awToolTip: 'Edit administrator',
label: 'Edit', 'class': 'btn-default'
ngClick: "edit('users', admin.id, admin.username)", },
icon: 'icon-edit', "delete": {
awToolTip: 'Edit administrator', label: 'Delete',
'class': 'btn-default' ngClick: "delete('admins', admin.id, admin.username, 'administrators')",
}, icon: 'icon-trash',
"delete": { "class": 'btn-danger',
label: 'Delete', awToolTip: 'Remove administrator'
ngClick: "delete('admins', admin.id, admin.username, 'administrators')", }
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Remove administrator'
} }
} }
} }
} }); //OrganizationForm
}); //OrganizationForm

View File

@@ -12,131 +12,133 @@
* @name forms.function:Permissions * @name forms.function:Permissions
* @description This form is for adding/editing persmissions * @description This form is for adding/editing persmissions
*/ */
angular.module('PermissionFormDefinition', [])
.value('PermissionsForm', {
addTitle: 'Add Permission', //Title in add mode export default
editTitle: '{{ name }}', //Title in edit mode angular.module('PermissionFormDefinition', [])
name: 'permission', //entity or model name in singular form .value('PermissionsForm', {
well: true, //Wrap the form with TB well
forceListeners: true,
stream: { addTitle: 'Add Permission', //Title in add mode
'class': "btn-primary btn-xs activity-btn", editTitle: '{{ name }}', //Title in edit mode
ngClick: "showActivity()", name: 'permission', //entity or model name in singular form
awToolTip: "View Activity Stream", well: true, //Wrap the form with TB well
dataPlacement: "top", forceListeners: true,
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
},
fields: { stream: {
category: { 'class': "btn-primary btn-xs activity-btn",
label: 'Permission Type', ngClick: "showActivity()",
labelClass: 'prepend-asterisk', awToolTip: "View Activity Stream",
type: 'radio_group', dataPlacement: "top",
options: [{ 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: 'Job Template',
value: 'Deploy'
}],
ngChange: 'selectCategory()'
},
name: {
label: 'Name',
type: 'text',
addRequired: true,
editRequired: true,
capitalize: false
},
description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
},
user: {
label: 'User',
type: 'hidden'
},
team: {
label: 'Team',
type: 'hidden'
},
project: {
label: 'Project',
type: 'lookup',
sourceModel: 'project',
sourceField: 'name',
ngShow: "category == 'Deploy'",
ngClick: 'lookUpProject()',
awRequiredWhen: {
variable: "projectrequired",
init: "false"
}
},
inventory: {
label: 'Inventory', label: 'Inventory',
value: 'Inventory', type: 'lookup',
selected: true sourceModel: 'inventory',
}, { sourceField: 'name',
label: 'Job Template', ngClick: 'lookUpInventory()',
value: 'Deploy' awRequiredWhen: {
}], variable: "inventoryrequired",
ngChange: 'selectCategory()' init: "true"
}, }
name: { },
label: 'Name', permission_type: {
type: 'text', label: 'Permission',
addRequired: true, labelClass: 'prepend-asterisk',
editRequired: true, type: 'radio_group',
capitalize: false options: [{
}, label: 'Read',
description: { value: 'read',
label: 'Description', ngShow: "category == 'Inventory'"
type: 'text', }, {
addRequired: false, label: 'Write',
editRequired: false value: 'write',
}, ngShow: "category == 'Inventory'"
user: { }, {
label: 'User', label: 'Admin',
type: 'hidden' value: 'admin',
}, ngShow: "category == 'Inventory'"
team: { }, {
label: 'Team', label: 'Create',
type: 'hidden' value: 'create',
}, ngShow: "category == 'Deploy'"
project: { }, {
label: 'Project', label: 'Run',
type: 'lookup', value: 'run',
sourceModel: 'project', ngShow: "category == 'Deploy'"
sourceField: 'name', }, {
ngShow: "category == 'Deploy'", label: 'Check',
ngClick: 'lookUpProject()', value: 'check',
awRequiredWhen: { ngShow: "category == 'Deploy'"
variable: "projectrequired", }],
init: "false" helpCollapse: [{
hdr: 'Permission',
ngBind: 'permissionTypeHelp'
}]
} }
}, },
inventory: {
label: 'Inventory', buttons: {
type: 'lookup', save: {
sourceModel: 'inventory', ngClick: 'formSave()',
sourceField: 'name', ngDisabled: true
ngClick: 'lookUpInventory()', },
awRequiredWhen: { reset: {
variable: "inventoryrequired", ngClick: 'formReset()',
init: "true" ngDisabled: 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: 'Create',
value: 'create',
ngShow: "category == 'Deploy'"
}, {
label: 'Run',
value: 'run',
ngShow: "category == 'Deploy'"
}, {
label: 'Check',
value: 'check',
ngShow: "category == 'Deploy'"
}],
helpCollapse: [{
hdr: 'Permission',
ngBind: 'permissionTypeHelp'
}]
}
},
buttons: { related: { }
save: {
ngClick: 'formSave()',
ngDisabled: true
},
reset: {
ngClick: 'formReset()',
ngDisabled: true
}
},
related: { } }); // Form
}); // Form

View File

@@ -11,40 +11,42 @@
* @name forms.function:ProjectStatus * @name forms.function:ProjectStatus
* @description This form is for adding/editing project status * @description This form is for adding/editing project status
*/ */
angular.module('ProjectStatusDefinition', [])
.value('ProjectStatusForm', {
name: 'project_update', export default
editTitle: 'SCM Status', angular.module('ProjectStatusDefinition', [])
well: false, .value('ProjectStatusForm', {
'class': 'horizontal-narrow',
fields: { name: 'project_update',
created: { editTitle: 'SCM Status',
label: 'Created', well: false,
type: 'text', 'class': 'horizontal-narrow',
readonly: true
}, fields: {
status: { created: {
label: 'Status', label: 'Created',
type: 'text', type: 'text',
readonly: true readonly: true
}, },
result_stdout: { status: {
label: 'Std Out', label: 'Status',
type: 'textarea', type: 'text',
ngShow: "result_stdout", readonly: true
'class': 'mono-space', },
readonly: true, result_stdout: {
rows: 15 label: 'Std Out',
}, type: 'textarea',
result_traceback: { ngShow: "result_stdout",
label: 'Traceback', 'class': 'mono-space',
type: 'textarea', readonly: true,
ngShow: "result_traceback", rows: 15
'class': 'mono-space', },
readonly: true, result_traceback: {
rows: 15 label: 'Traceback',
type: 'textarea',
ngShow: "result_traceback",
'class': 'mono-space',
readonly: true,
rows: 15
}
} }
} }); //Form
}); //Form

View File

@@ -12,6 +12,8 @@
* @name forms.function:Projects * @name forms.function:Projects
* @description This form is for adding/editing projects * @description This form is for adding/editing projects
*/ */
export default
angular.module('ProjectFormDefinition', ['SchedulesListDefinition']) angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
.value('ProjectsFormObject', { .value('ProjectsFormObject', {
@@ -330,4 +332,4 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
} }
return ProjectsFormObject; return ProjectsFormObject;
}; };
}]); }]);

View File

@@ -11,248 +11,250 @@
* @name forms.function:Source * @name forms.function:Source
* @description This form is for group model * @description This form is for group model
*/ */
angular.module('SourceFormDefinition', [])
.value('SourceForm', {
addTitle: 'Create Source', export default
editTitle: 'Edit Source', angular.module('SourceFormDefinition', [])
showTitle: false, .value('SourceForm', {
cancelButton: false,
name: 'source',
well: false,
fields: { addTitle: 'Create Source',
source: { editTitle: 'Edit Source',
label: 'Source', showTitle: false,
type: 'select', cancelButton: false,
ngOptions: 'source.label for source in source_type_options track by source.value', name: 'source',
ngChange: 'sourceChange()', well: false,
addRequired: false,
editRequired: false fields: {
}, source: {
source_path: { label: 'Source',
label: 'Script Path', type: 'select',
ngShow: "source && source.value == 'file'", ngOptions: 'source.label for source in source_type_options track by source.value',
type: 'text', ngChange: 'sourceChange()',
awRequiredWhen: { addRequired: false,
variable: "sourcePathRequired", editRequired: false
init: "false" },
source_path: {
label: 'Script Path',
ngShow: "source && source.value == 'file'",
type: 'text',
awRequiredWhen: {
variable: "sourcePathRequired",
init: "false"
}
},
credential: {
label: 'Cloud Credential',
type: 'lookup',
ngShow: "source && source.value !== 'manual' && source.value !== 'custom'",
sourceModel: 'credential',
sourceField: 'name',
ngClick: 'lookUpCredential()',
addRequired: false,
editRequired: false
},
source_regions: {
label: 'Regions',
type: 'text',
ngShow: "source && (source.value == 'rax' || source.value == 'ec2' || source.value == 'gce' || source.value == 'azure')",
addRequired: false,
editRequired: false,
awMultiselect: 'source_region_choices',
dataTitle: 'Source Regions',
dataPlacement: 'right',
awPopOver: "<p>Click on the regions field to see a list of regions for your cloud provider. You can select multiple regions, " +
"or choose <em>All</em> to include all regions. Tower will only be updated with Hosts associated with the selected regions." +
"</p>",
dataContainer: 'body'
},
instance_filters: {
label: 'Instance Filters',
type: 'text',
ngShow: "source && source.value == 'ec2'",
addRequired: false,
editRequired: false,
dataTitle: 'Instance Filters',
dataPlacement: 'right',
awPopOver: "<p>Provide a comma-separated list of filter expressions. " +
"Hosts are imported to Tower when <em>ANY</em> of the filters match.</p>" +
"Limit to hosts having a tag:<br />\n" +
"<blockquote>tag-key=TowerManaged</blockquote>\n" +
"Limit to hosts using either key pair:<br />\n" +
"<blockquote>key-name=staging, key-name=production</blockquote>\n" +
"Limit to hosts where the Name tag begins with <em>test</em>:<br />\n" +
"<blockquote>tag:Name=test*</blockquote>\n" +
"<p>View the <a href=\"http://docs.aws.amazon.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html\" target=\"_blank\">Describe Instances documentation</a> " +
"for a complete list of supported filters.</p>",
dataContainer: 'body'
},
group_by: {
label: 'Only Group By',
type: 'text',
ngShow: "source && source.value == 'ec2'",
addRequired: false,
editRequired: false,
awMultiselect: 'group_by_choices',
dataTitle: 'Only Group By',
dataPlacement: 'right',
awPopOver: "<p>Select which groups to create automatically. " +
"Tower will create group names similar to the following examples based on the options selected:</p><ul>" +
"<li>Availability Zone: <strong>zones &raquo; us-east-1b</strong></li>" +
"<li>Image ID: <strong>images &raquo; ami-b007ab1e</strong></li>" +
"<li>Instance ID: <strong>instances &raquo; i-ca11ab1e</strong></li>" +
"<li>Instance Type: <strong>types &raquo; type_m1_medium</strong></li>" +
"<li>Key Name: <strong>keys &raquo; key_testing</strong></li>" +
"<li>Region: <strong>regions &raquo; us-east-1</strong></li>" +
"<li>Security Group: <strong>security_groups &raquo; security_group_default</strong></li>" +
"<li>Tags: <strong>tags &raquo; tag_Name &raquo; tag_Name_host1</strong></li>" +
"<li>VPC ID: <strong>vpcs &raquo; vpc-5ca1ab1e</strong></li>" +
"</ul><p>If blank, all groups above are created except <em>Instance ID</em>.</p>",
dataContainer: 'body'
},
source_script: {
label : "Custom Inventory Script",
labelClass: 'prepend-asterisk',
type: 'lookup',
ngShow: "source && source.value === 'custom'",
sourceModel: 'source_script',
sourceField: 'name',
ngClick: 'lookUpSource_script()' , //'lookUpCustom_inventory()',
addRequired: true,
editRequired: true
},
extra_vars: {
label: 'Environment Variables', //"{{vars_label}}" ,
ngShow: "source && source.value=='custom' ",
type: 'textarea',
addRequired: false,
editRequired: false,
rows: 6,
'default': '---',
parseTypeName: 'envParseType',
dataTitle: "Environment Variables",
dataPlacement: 'right',
awPopOver: "<p>Provide key/value pairs using either YAML or JSON.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n",
dataContainer: 'body'
},
source_vars: {
label: 'Source Variables', //"{{vars_label}}" ,
ngShow: "source && (source.value == 'file' || source.value == 'ec2')",
type: 'textarea',
addRequired: false,
editRequird: false,
rows: 6,
'default': '---',
parseTypeName: 'envParseType',
dataTitle: "Source Variables",
dataPlacement: 'right',
awPopOver: "<p>Override variables found in ec2.ini and used by the inventory update script. For a detailed description of these variables " +
"<a href=\"https://github.com/ansible/ansible/blob/devel/plugins/inventory/ec2.ini\" target=\"_blank\">" +
"view ec2.ini in the Ansible github repo.</a></p>" +
"<p>Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n" +
'<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p>' +
'<p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">docs.ansible.com</a></p>',
dataContainer: 'body'
},
inventory_variables: {
label: 'Source Variables', //"{{vars_label}}" ,
ngShow: "source && (source.value == 'vmware')",
type: 'textarea',
addRequired: false,
editRequird: false,
rows: 6,
'default': '---',
parseTypeName: 'envParseType',
dataTitle: "Source Variables",
dataPlacement: 'right',
awPopOver: "<p>Override variables found in vmware.ini and used by the inventory update script. For a detailed description of these variables " +
"<a href=\"https://github.com/ansible/ansible/blob/devel/plugins/inventory/vmware.ini\" target=\"_blank\">" +
"view vmware.ini in the Ansible github repo.</a></p>" +
"<p>Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n" +
'<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p>' +
'<p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">docs.ansible.com</a></p>',
dataContainer: 'body'
},
checkbox_group: {
label: 'Update Options',
type: 'checkbox_group',
ngShow: "source && (source.value !== 'manual' && source.value !== null)",
fields: [{
name: 'overwrite',
label: 'Overwrite',
type: 'checkbox',
ngShow: "source.value !== 'manual' && source.value !== null",
addRequired: false,
editRequired: false,
awPopOver: '<p>If checked, all child groups and hosts not found on the external source will be deleted from ' +
'the local inventory.</p><p>When not checked, local child hosts and groups not found on the external source will ' +
'remain untouched by the inventory update process.</p>',
dataTitle: 'Overwrite',
dataContainer: 'body',
dataPlacement: 'right',
labelClass: 'checkbox-options'
}, {
name: 'overwrite_vars',
label: 'Overwrite Variables',
type: 'checkbox',
ngShow: "source.value !== 'manual' && source.value !== null",
addRequired: false,
editRequired: false,
awPopOver: '<p>If checked, all variables for child groups and hosts will be removed and replaced by those ' +
'found on the external source.</p><p>When not checked, a merge will be performed, combining local variables with ' +
'those found on the external source.</p>',
dataTitle: 'Overwrite Variables',
dataContainer: 'body',
dataPlacement: 'right',
labelClass: 'checkbox-options'
}, {
name: 'update_on_launch',
label: 'Update on Launch',
type: 'checkbox',
ngShow: "source.value !== 'manual' && source.value !== null",
addRequired: false,
editRequired: false,
awPopOver: '<p>Each time a job runs using this inventory, refresh the inventory from the selected source before ' +
'executing job tasks.</p>',
dataTitle: 'Update on Launch',
dataContainer: 'body',
dataPlacement: 'right',
labelClass: 'checkbox-options'
}]
},
update_cache_timeout: {
label: "Cache Timeout <span class=\"small-text\"> (seconds)</span>",
id: 'source-cache-timeout',
type: 'number',
integer: true,
min: 0,
ngShow: "source && source.value !== 'manual' && update_on_launch",
spinner: true,
"default": 0,
addRequired: false,
editRequired: false,
awPopOver: '<p>Time in seconds to consider an inventory sync to be current. During job runs and callbacks the task system will ' +
'evaluate the timestamp of the latest sync. If it is older than Cache Timeout, it is not considered current, ' +
'and a new inventory sync will be performed.</p>',
dataTitle: 'Cache Timeout',
dataPlacement: 'right',
dataContainer: "body"
} }
}, },
credential: {
label: 'Cloud Credential',
type: 'lookup',
ngShow: "source && source.value !== 'manual' && source.value !== 'custom'",
sourceModel: 'credential',
sourceField: 'name',
ngClick: 'lookUpCredential()',
addRequired: false,
editRequired: false
},
source_regions: {
label: 'Regions',
type: 'text',
ngShow: "source && (source.value == 'rax' || source.value == 'ec2' || source.value == 'gce' || source.value == 'azure')",
addRequired: false,
editRequired: false,
awMultiselect: 'source_region_choices',
dataTitle: 'Source Regions',
dataPlacement: 'right',
awPopOver: "<p>Click on the regions field to see a list of regions for your cloud provider. You can select multiple regions, " +
"or choose <em>All</em> to include all regions. Tower will only be updated with Hosts associated with the selected regions." +
"</p>",
dataContainer: 'body'
},
instance_filters: {
label: 'Instance Filters',
type: 'text',
ngShow: "source && source.value == 'ec2'",
addRequired: false,
editRequired: false,
dataTitle: 'Instance Filters',
dataPlacement: 'right',
awPopOver: "<p>Provide a comma-separated list of filter expressions. " +
"Hosts are imported to Tower when <em>ANY</em> of the filters match.</p>" +
"Limit to hosts having a tag:<br />\n" +
"<blockquote>tag-key=TowerManaged</blockquote>\n" +
"Limit to hosts using either key pair:<br />\n" +
"<blockquote>key-name=staging, key-name=production</blockquote>\n" +
"Limit to hosts where the Name tag begins with <em>test</em>:<br />\n" +
"<blockquote>tag:Name=test*</blockquote>\n" +
"<p>View the <a href=\"http://docs.aws.amazon.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html\" target=\"_blank\">Describe Instances documentation</a> " +
"for a complete list of supported filters.</p>",
dataContainer: 'body'
},
group_by: {
label: 'Only Group By',
type: 'text',
ngShow: "source && source.value == 'ec2'",
addRequired: false,
editRequired: false,
awMultiselect: 'group_by_choices',
dataTitle: 'Only Group By',
dataPlacement: 'right',
awPopOver: "<p>Select which groups to create automatically. " +
"Tower will create group names similar to the following examples based on the options selected:</p><ul>" +
"<li>Availability Zone: <strong>zones &raquo; us-east-1b</strong></li>" +
"<li>Image ID: <strong>images &raquo; ami-b007ab1e</strong></li>" +
"<li>Instance ID: <strong>instances &raquo; i-ca11ab1e</strong></li>" +
"<li>Instance Type: <strong>types &raquo; type_m1_medium</strong></li>" +
"<li>Key Name: <strong>keys &raquo; key_testing</strong></li>" +
"<li>Region: <strong>regions &raquo; us-east-1</strong></li>" +
"<li>Security Group: <strong>security_groups &raquo; security_group_default</strong></li>" +
"<li>Tags: <strong>tags &raquo; tag_Name &raquo; tag_Name_host1</strong></li>" +
"<li>VPC ID: <strong>vpcs &raquo; vpc-5ca1ab1e</strong></li>" +
"</ul><p>If blank, all groups above are created except <em>Instance ID</em>.</p>",
dataContainer: 'body'
},
source_script: {
label : "Custom Inventory Script",
labelClass: 'prepend-asterisk',
type: 'lookup',
ngShow: "source && source.value === 'custom'",
sourceModel: 'source_script',
sourceField: 'name',
ngClick: 'lookUpSource_script()' , //'lookUpCustom_inventory()',
addRequired: true,
editRequired: true
},
extra_vars: {
label: 'Environment Variables', //"{{vars_label}}" ,
ngShow: "source && source.value=='custom' ",
type: 'textarea',
addRequired: false,
editRequired: false,
rows: 6,
'default': '---',
parseTypeName: 'envParseType',
dataTitle: "Environment Variables",
dataPlacement: 'right',
awPopOver: "<p>Provide key/value pairs using either YAML or JSON.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n",
dataContainer: 'body'
},
source_vars: {
label: 'Source Variables', //"{{vars_label}}" ,
ngShow: "source && (source.value == 'file' || source.value == 'ec2')",
type: 'textarea',
addRequired: false,
editRequird: false,
rows: 6,
'default': '---',
parseTypeName: 'envParseType',
dataTitle: "Source Variables",
dataPlacement: 'right',
awPopOver: "<p>Override variables found in ec2.ini and used by the inventory update script. For a detailed description of these variables " +
"<a href=\"https://github.com/ansible/ansible/blob/devel/plugins/inventory/ec2.ini\" target=\"_blank\">" +
"view ec2.ini in the Ansible github repo.</a></p>" +
"<p>Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n" +
'<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p>' +
'<p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">docs.ansible.com</a></p>',
dataContainer: 'body'
},
inventory_variables: {
label: 'Source Variables', //"{{vars_label}}" ,
ngShow: "source && (source.value == 'vmware')",
type: 'textarea',
addRequired: false,
editRequird: false,
rows: 6,
'default': '---',
parseTypeName: 'envParseType',
dataTitle: "Source Variables",
dataPlacement: 'right',
awPopOver: "<p>Override variables found in vmware.ini and used by the inventory update script. For a detailed description of these variables " +
"<a href=\"https://github.com/ansible/ansible/blob/devel/plugins/inventory/vmware.ini\" target=\"_blank\">" +
"view vmware.ini in the Ansible github repo.</a></p>" +
"<p>Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n" +
'<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p>' +
'<p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">docs.ansible.com</a></p>',
dataContainer: 'body'
},
checkbox_group: {
label: 'Update Options',
type: 'checkbox_group',
ngShow: "source && (source.value !== 'manual' && source.value !== null)",
fields: [{ buttons: {
name: 'overwrite',
label: 'Overwrite',
type: 'checkbox',
ngShow: "source.value !== 'manual' && source.value !== null",
addRequired: false,
editRequired: false,
awPopOver: '<p>If checked, all child groups and hosts not found on the external source will be deleted from ' +
'the local inventory.</p><p>When not checked, local child hosts and groups not found on the external source will ' +
'remain untouched by the inventory update process.</p>',
dataTitle: 'Overwrite',
dataContainer: 'body',
dataPlacement: 'right',
labelClass: 'checkbox-options'
}, {
name: 'overwrite_vars',
label: 'Overwrite Variables',
type: 'checkbox',
ngShow: "source.value !== 'manual' && source.value !== null",
addRequired: false,
editRequired: false,
awPopOver: '<p>If checked, all variables for child groups and hosts will be removed and replaced by those ' +
'found on the external source.</p><p>When not checked, a merge will be performed, combining local variables with ' +
'those found on the external source.</p>',
dataTitle: 'Overwrite Variables',
dataContainer: 'body',
dataPlacement: 'right',
labelClass: 'checkbox-options'
}, {
name: 'update_on_launch',
label: 'Update on Launch',
type: 'checkbox',
ngShow: "source.value !== 'manual' && source.value !== null",
addRequired: false,
editRequired: false,
awPopOver: '<p>Each time a job runs using this inventory, refresh the inventory from the selected source before ' +
'executing job tasks.</p>',
dataTitle: 'Update on Launch',
dataContainer: 'body',
dataPlacement: 'right',
labelClass: 'checkbox-options'
}]
}, },
update_cache_timeout: {
label: "Cache Timeout <span class=\"small-text\"> (seconds)</span>",
id: 'source-cache-timeout',
type: 'number',
integer: true,
min: 0,
ngShow: "source && source.value !== 'manual' && update_on_launch",
spinner: true,
"default": 0,
addRequired: false,
editRequired: false,
awPopOver: '<p>Time in seconds to consider an inventory sync to be current. During job runs and callbacks the task system will ' +
'evaluate the timestamp of the latest sync. If it is older than Cache Timeout, it is not considered current, ' +
'and a new inventory sync will be performed.</p>',
dataTitle: 'Cache Timeout',
dataPlacement: 'right',
dataContainer: "body"
}
},
buttons: { related: { }
}, });
related: { }
});

View File

@@ -11,60 +11,62 @@
* @name forms.function:SurveyMaker * @name forms.function:SurveyMaker
* @description This form is for adding/editing a survey * @description This form is for adding/editing a survey
*/ */
angular.module('SurveyMakerFormDefinition', [])
.value('SurveyMakerForm', {
addTitle: 'Add Survey', //Title in add mode export default
editTitle: 'Edit Survey', //Title in edit mode angular.module('SurveyMakerFormDefinition', [])
name: 'survey_maker', //entity or model name in singular form .value('SurveyMakerForm', {
// // well: true,
breadCrumbs: false, addTitle: 'Add Survey', //Title in add mode
editTitle: 'Edit Survey', //Title in edit mode
name: 'survey_maker', //entity or model name in singular form
// // well: true,
breadCrumbs: false,
fields: { fields: {
survey_name: { survey_name: {
type: 'custom', type: 'custom',
control: '<div class="row">'+ control: '<div class="row">'+
// '<div class="col-sm-6"> // '<div class="col-sm-6">
// <div class="form-group">'+ // <div class="form-group">'+
// '<label for="survey_name"><span class="label-text prepend-asterisk">Survey Name</span></label> // '<label for="survey_name"><span class="label-text prepend-asterisk">Survey Name</span></label>
// <div>'+ // <div>'+
// '<input type="text" ng-model="survey_name" name="survey_name" id="survey_maker_survey_name" class="form-control ng-pristine ng-invalid ng-invalid-required" required="" capitalize>'+ // '<input type="text" ng-model="survey_name" name="survey_name" id="survey_maker_survey_name" class="form-control ng-pristine ng-invalid ng-invalid-required" required="" capitalize>'+
// '<div class="error ng-hide" id="survey_maker-survey_name-required-error" ng-show="survey_maker_form.survey_name.$dirty &amp;&amp; survey_maker_form.survey_name.$error.required">Please enter a survey name.</div>'+ // '<div class="error ng-hide" id="survey_maker-survey_name-required-error" ng-show="survey_maker_form.survey_name.$dirty &amp;&amp; survey_maker_form.survey_name.$error.required">Please enter a survey name.</div>'+
// '<div class="error api-error ng-binding" id="survey_maker-survey_name-api-error" ng-bind="survey_name_api_error"></div>'+ // '<div class="error api-error ng-binding" id="survey_maker-survey_name-api-error" ng-bind="survey_name_api_error"></div>'+
// '</div></div></div>'+ // '</div></div></div>'+
// '<div class="col-sm-6"><div class="form-group">'+ // '<div class="col-sm-6"><div class="form-group">'+
// '<label for="survey_description"><span class="label-text">Survey Description</span></label><div>'+ // '<label for="survey_description"><span class="label-text">Survey Description</span></label><div>'+
// '<input type="text" ng-model="survey_description" name="survey_description" id="survey_maker_survey_description" class="form-control ng-pristine ng-valid">'+ // '<input type="text" ng-model="survey_description" name="survey_description" id="survey_maker_survey_description" class="form-control ng-pristine ng-valid">'+
// '<div class="error api-error ng-binding" id="survey_maker-survey_description-api-error" ng-bind="survey_description_api_error"></div>'+ // '<div class="error api-error ng-binding" id="survey_maker-survey_description-api-error" ng-bind="survey_description_api_error"></div>'+
// '</div></div></div>'+ // '</div></div></div>'+
'<div class="col-sm-12">'+ '<div class="col-sm-12">'+
'<label for="survey"><span class="label-text prepend-asterisk">Questions</span></label>'+ '<label for="survey"><span class="label-text prepend-asterisk">Questions</span></label>'+
'<div id="survey_maker_question_area"></div>'+ '<div id="survey_maker_question_area"></div>'+
'<div id="finalized_questions"></div>'+ '<div id="finalized_questions"></div>'+
'<button style="display:none" type="button" class="btn btn-sm btn-primary" id="add_question_btn" ng-click="addNewQuestion()" aw-tool-tip="Create a new question" data-placement="top" data-original-title="" title="" disabled><i class="fa fa-plus fa-lg"></i> Add Question</button>'+ '<button style="display:none" type="button" class="btn btn-sm btn-primary" id="add_question_btn" ng-click="addNewQuestion()" aw-tool-tip="Create a new question" data-placement="top" data-original-title="" title="" disabled><i class="fa fa-plus fa-lg"></i> Add Question</button>'+
'<div id="new_question"></div>'+ '<div id="new_question"></div>'+
'</div>'+ '</div>'+
'</div>'//</div>' '</div>'//</div>'
// label: 'Survey Name', // label: 'Survey Name',
// type: 'text', // type: 'text',
// addRequired: true, // addRequired: true,
// editRequired: true, // editRequired: true,
// capitalize: false, // capitalize: false,
// // column: 1 // // column: 1
},
}, },
}, // buttons: { //for now always generates <button> tags
// save: {
// buttons: { //for now always generates <button> tags // ngClick: 'formSave()', //$scope.function to call on click, optional
// save: { // ngDisabled: true //Disable when $pristine or $invalid, optional
// 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
// }
// } // }
// reset: {
// ngClick: 'formReset()',
// ngDisabled: true //Disabled when $pristine
// }
// }
}); });

View File

@@ -11,261 +11,263 @@
* @name forms.function:Questions * @name forms.function:Questions
* @description This form is for adding a question * @description This form is for adding a question
*/ */
angular.module('SurveyQuestionFormDefinition', [])
.value('SurveyQuestionForm', {
addTitle: 'Add Question', export default
editTitle: 'Edit Question', angular.module('SurveyQuestionFormDefinition', [])
base: 'survey_question', .value('SurveyQuestionForm', {
name: 'survey_question',
well: true,
twoColumns: true,
breadcrumbs: false,
fields: { addTitle: 'Add Question',
question_name: { editTitle: 'Edit Question',
realName: 'question_text', base: 'survey_question',
label: 'Name', name: 'survey_question',
type: 'text', well: true,
addRequired: true, twoColumns: true,
editRequired: true, breadcrumbs: false,
column: 1,
awSurveyQuestion: true
},
question_description: {
realName: 'question_description',
label: 'Description',
type: 'text',
// rows: 2,
addRequired: false,
editRequired: false,
column: 1
},
// variable: {
// label: 'Answer Variable Name',
// type: 'text',
// addRequired: true,
// editRequired: true,
// column: 1,
// awPopOver: '<p>The suggested format for variable names are lowercase, underscore-separated descriptive nouns.</p>'+
// '<p>For example: <br>foo_bar<br>\n user_id<br>\n host_name<br>' ,
// dataTitle: 'Answer Variable Name',
// dataPlacement: 'right',
// dataContainer: "body"
// },
variable: {
ealName: 'variable',
type: 'custom',
control:'<label for="variable"><span class="label-text prepend-asterisk">Answer Variable Name</span>'+
'<a id="awp-variable" href="" aw-pop-over="<p>The suggested format for variable names is lowercase and underscore-separated. Also note that this field cannot accept variable names with spaces.</p><p>For example: <br>foo_bar<br>'+
'user_id<br>host_name<br><div class=&quot;popover-footer&quot;><span class=&quot;key&quot;>esc</span> or click to close</div>" '+
'data-placement="right" data-container="body" data-title="Answer Variable Name" class="help-link" data-original-title="" title="" tabindex="-1"><i class="fa fa-question-circle"></i></a> </label>'+
'<div><input type="text" ng-model="variable" name="variable" id="survey_question_variable" class="form-control ng-pristine ng-invalid ng-invalid-required" required="" aw-survey-variable-name>'+
'<div class="error ng-hide" id="survey_question-variable-required-error" ng-show="survey_question_form.variable.$dirty &amp;&amp; survey_question_form.variable.$error.required">Please enter an answer variable name.</div>'+
'<div class="error ng-hide" id="survey_question-variable-variable-error" ng-show="survey_question_form.variable.$dirty &amp;&amp; survey_question_form.variable.$error.variable">Please remove the illegal character from the survey question variable name.</div>'+
'<div class="error ng-hide" id=survey_question-variable-duplicate-error" ng-show="duplicate">This question variable is already in use. Please enter a different variable name.</div>' +
'<div class="error api-error ng-binding" id="survey_question-variable-api-error" ng-bind="variable_api_error"></div>'+
'</div>',
addRequired: true,
editRequired: true,
column: 1
},
type: {
realName: 'answer_type',
label: 'Answer Type',
type: 'select',
defaultText: 'Choose an answer type',
ngOptions: 'answer_types.name for answer_types in answer_types track by answer_types.type',
addRequired: true,
editRequired: true,
column: 2,
ngChange: 'typeChange()'
},
choices: {
realName: 'answer_options',
label: 'Multiple Choice Options',
type: 'textarea',
rows: 3,
addRequired: true,
editRequired: true,
ngRequired: "type.type=== 'multiselect' || type.type=== 'multiplechoice' " ,
ngShow: 'type.type=== "multiselect" || type.type=== "multiplechoice" ',
awPopOver: '<p>Type an option on each line.</p>'+
'<p>For example the following input:<br><br>Apple<br>\n Banana<br>\n Cherry<br><br>would be displayed as:</p>\n'+
'<ol><li>Apple</li><li>Banana</li><li>Cherry</li></ol>',
dataTitle: 'Multiple Choice Options',
dataPlacement: 'right',
dataContainer: "body",
column: 2
},
text_options: {
realName: 'answer_options',
type: 'custom',
control:'<div class="row">'+
'<div class="col-xs-6">'+
'<label for="text_min"><span class="label-text">Minimum Length</span></label><input id="text_min" type="number" name="text_min" ng-model="text_min" min=0 aw-min="0" aw-max="text_max" class="form-control" integer />'+
'<div class="error" ng-show="survey_question_form.text_min.$error.number || survey_question_form.text_min.$error.integer">The minimum length you entered is not a number. Please enter a number.</div>'+
'<div class="error" ng-show="survey_question_form.text_min.$error.awMax">The minimium length is too high. Please enter a lower number.</div>'+
'<div class="error" ng-show="survey_question_form.text_min.$error.awMin">The minimum length is too low. Please enter a positive number.</div>'+
'</div>'+
'<div class="col-xs-6">'+
'<label for="text_max"><span class="label-text">Maximum Length</span></label><input id="text_max" type="number" name="text_max" ng-model="text_max" aw-min="text_min || 0" class="form-control" integer >'+
'<div class="error" ng-show="survey_question_form.text_max.$error.number || survey_question_form.text_max.$error.integer">The maximum length you entered is not a number. Please enter a number.</div>'+
'<div class="error" ng-show="survey_question_form.text_max.$error.awMin">The maximum length is too low. Please enter a number larger than the minimum length you set.</div>'+
'</div>'+
'</div>',
ngShow: 'type.type==="text" ',
addRequired: true,
editRequired: true,
column: 2
},
textarea_options: {
realName: 'answer_options',
type: 'custom',
control:'<div class="row">'+
'<div class="col-xs-6">'+
'<label for="textarea_min"><span class="label-text">Minimum Length</span></label><input id="textarea_min" type="number" name="textarea_min" ng-model="textarea_min" min=0 aw-min="0" aw-max="textarea_max" class="form-control" integer />'+
'<div class="error" ng-show="survey_question_form.textarea_min.$error.number || survey_question_form.textarea_min.$error.integer">The minimum length you entered is not a number. Please enter a number.</div>'+
'<div class="error" ng-show="survey_question_form.textarea_min.$error.awMax">The minimium length is too high. Please enter a lower number.</div>'+
'<div class="error" ng-show="survey_question_form.textarea_min.$error.awMin">The minimum length is too low. Please enter a positive number.</div>'+
'</div>'+
'<div class="col-xs-6">'+
'<label for="textarea_max"><span class="label-text">Maximum Length</span></label><input id="textarea_max" type="number" name="textarea_max" ng-model="textarea_max" aw-min="textarea_min || 0" class="form-control" integer >'+
'<div class="error" ng-show="survey_question_form.textarea_max.$error.number || survey_question_form.textarea_max.$error.integer">The maximum length you entered is not a number. Please enter a number.</div>'+
'<div class="error" ng-show="survey_question_form.textarea_max.$error.awMin">The maximum length is too low. Please enter a number larger than the minimum length you set.</div>'+
'</div>'+
'</div>',
ngShow: 'type.type==="textarea" ',
addRequired: true,
editRequired: true,
column: 2
},
int_options: {
realName: 'answer_options',
type: 'custom',
control:'<div class="row">'+
'<div class="col-xs-6">'+
'<label for="minimum"><span class="label-text">Minimum</span></label><input id="int_min" type="number" name="int_min" ng-model="int_min" aw-max="int_max" class="form-control" integer >'+
'<div class="error" ng-show="survey_question_form.int_min.$error.number || survey_question_form.int_min.$error.integer">Please enter a valid integer.</div>'+
'<div class="error" ng-show="survey_question_form.int_min.$error.awMax">Please enter a smaller integer.</div>'+
'</div>'+
'<div class="col-xs-6">'+
'<label for="minimum"><span class="label-text">Maximum</span></label><input id="int_max" type="number" name="int_max" ng-model="int_max" aw-min="int_min" class="form-control" integer >'+
'<div class="error" ng-show="survey_question_form.int_max.$error.number || survey_question_form.int_max.$error.integer">Please enter a valid integer.</div>'+
'<div class="error" ng-show="survey_question_form.int_max.$error.awMin">Please enter a larger integer.</div>'+
'</div>'+
'</div>',
ngShow: 'type.type==="integer" ',
addRequired: true,
editRequired: true,
column: 2
},
float_options: {
realName: 'answer_options',
type: 'custom',
control: '<div class="row">'+
'<div class="col-xs-6">'+
'<label for="minimum"><span class="label-text">Minimum</span></label><input id="float_min" type="number" name="float_min" ng-model="float_min" class="form-control" smart-float aw-max="float_max">'+
'<div class="error" ng-show="survey_question_form.float_min.$error.float">Please enter a valid float.</div>'+
'<div class="error" ng-show="survey_question_form.float_min.$error.awMax">Please enter a smaller float.</div>'+
'</div>'+
'<div class="col-xs-6">'+
'<label for="maximum"><span class="label-text">Maximum</span></label><input id="float_max" type="number" name="float_max" ng-model="float_max" class="form-control" smart-float aw-min="float_min">'+
'<div class="error" ng-show="survey_question_form.float_max.$error.float">Please enter a valid float.</div>'+
'<div class="error" ng-show="survey_question_form.float_max.$error.awMin">Please enter a larger float.</div>'+
'</div>'+ fields: {
'</div>', question_name: {
ngShow: 'type.type==="float" ', realName: 'question_text',
addRequired: true, label: 'Name',
editRequired: true, type: 'text',
column: 2 addRequired: true,
editRequired: true,
column: 1,
awSurveyQuestion: true
},
question_description: {
realName: 'question_description',
label: 'Description',
type: 'text',
// rows: 2,
addRequired: false,
editRequired: false,
column: 1
},
// variable: {
// label: 'Answer Variable Name',
// type: 'text',
// addRequired: true,
// editRequired: true,
// column: 1,
// awPopOver: '<p>The suggested format for variable names are lowercase, underscore-separated descriptive nouns.</p>'+
// '<p>For example: <br>foo_bar<br>\n user_id<br>\n host_name<br>' ,
// dataTitle: 'Answer Variable Name',
// dataPlacement: 'right',
// dataContainer: "body"
// },
variable: {
ealName: 'variable',
type: 'custom',
control:'<label for="variable"><span class="label-text prepend-asterisk">Answer Variable Name</span>'+
'<a id="awp-variable" href="" aw-pop-over="<p>The suggested format for variable names is lowercase and underscore-separated. Also note that this field cannot accept variable names with spaces.</p><p>For example: <br>foo_bar<br>'+
'user_id<br>host_name<br><div class=&quot;popover-footer&quot;><span class=&quot;key&quot;>esc</span> or click to close</div>" '+
'data-placement="right" data-container="body" data-title="Answer Variable Name" class="help-link" data-original-title="" title="" tabindex="-1"><i class="fa fa-question-circle"></i></a> </label>'+
'<div><input type="text" ng-model="variable" name="variable" id="survey_question_variable" class="form-control ng-pristine ng-invalid ng-invalid-required" required="" aw-survey-variable-name>'+
'<div class="error ng-hide" id="survey_question-variable-required-error" ng-show="survey_question_form.variable.$dirty &amp;&amp; survey_question_form.variable.$error.required">Please enter an answer variable name.</div>'+
'<div class="error ng-hide" id="survey_question-variable-variable-error" ng-show="survey_question_form.variable.$dirty &amp;&amp; survey_question_form.variable.$error.variable">Please remove the illegal character from the survey question variable name.</div>'+
'<div class="error ng-hide" id=survey_question-variable-duplicate-error" ng-show="duplicate">This question variable is already in use. Please enter a different variable name.</div>' +
'<div class="error api-error ng-binding" id="survey_question-variable-api-error" ng-bind="variable_api_error"></div>'+
'</div>',
addRequired: true,
editRequired: true,
column: 1
},
type: {
realName: 'answer_type',
label: 'Answer Type',
type: 'select',
defaultText: 'Choose an answer type',
ngOptions: 'answer_types.name for answer_types in answer_types track by answer_types.type',
addRequired: true,
editRequired: true,
column: 2,
ngChange: 'typeChange()'
},
choices: {
realName: 'answer_options',
label: 'Multiple Choice Options',
type: 'textarea',
rows: 3,
addRequired: true,
editRequired: true,
ngRequired: "type.type=== 'multiselect' || type.type=== 'multiplechoice' " ,
ngShow: 'type.type=== "multiselect" || type.type=== "multiplechoice" ',
awPopOver: '<p>Type an option on each line.</p>'+
'<p>For example the following input:<br><br>Apple<br>\n Banana<br>\n Cherry<br><br>would be displayed as:</p>\n'+
'<ol><li>Apple</li><li>Banana</li><li>Cherry</li></ol>',
dataTitle: 'Multiple Choice Options',
dataPlacement: 'right',
dataContainer: "body",
column: 2
},
text_options: {
realName: 'answer_options',
type: 'custom',
control:'<div class="row">'+
'<div class="col-xs-6">'+
'<label for="text_min"><span class="label-text">Minimum Length</span></label><input id="text_min" type="number" name="text_min" ng-model="text_min" min=0 aw-min="0" aw-max="text_max" class="form-control" integer />'+
'<div class="error" ng-show="survey_question_form.text_min.$error.number || survey_question_form.text_min.$error.integer">The minimum length you entered is not a number. Please enter a number.</div>'+
'<div class="error" ng-show="survey_question_form.text_min.$error.awMax">The minimium length is too high. Please enter a lower number.</div>'+
'<div class="error" ng-show="survey_question_form.text_min.$error.awMin">The minimum length is too low. Please enter a positive number.</div>'+
'</div>'+
'<div class="col-xs-6">'+
'<label for="text_max"><span class="label-text">Maximum Length</span></label><input id="text_max" type="number" name="text_max" ng-model="text_max" aw-min="text_min || 0" class="form-control" integer >'+
'<div class="error" ng-show="survey_question_form.text_max.$error.number || survey_question_form.text_max.$error.integer">The maximum length you entered is not a number. Please enter a number.</div>'+
'<div class="error" ng-show="survey_question_form.text_max.$error.awMin">The maximum length is too low. Please enter a number larger than the minimum length you set.</div>'+
'</div>'+
'</div>',
ngShow: 'type.type==="text" ',
addRequired: true,
editRequired: true,
column: 2
},
textarea_options: {
realName: 'answer_options',
type: 'custom',
control:'<div class="row">'+
'<div class="col-xs-6">'+
'<label for="textarea_min"><span class="label-text">Minimum Length</span></label><input id="textarea_min" type="number" name="textarea_min" ng-model="textarea_min" min=0 aw-min="0" aw-max="textarea_max" class="form-control" integer />'+
'<div class="error" ng-show="survey_question_form.textarea_min.$error.number || survey_question_form.textarea_min.$error.integer">The minimum length you entered is not a number. Please enter a number.</div>'+
'<div class="error" ng-show="survey_question_form.textarea_min.$error.awMax">The minimium length is too high. Please enter a lower number.</div>'+
'<div class="error" ng-show="survey_question_form.textarea_min.$error.awMin">The minimum length is too low. Please enter a positive number.</div>'+
'</div>'+
'<div class="col-xs-6">'+
'<label for="textarea_max"><span class="label-text">Maximum Length</span></label><input id="textarea_max" type="number" name="textarea_max" ng-model="textarea_max" aw-min="textarea_min || 0" class="form-control" integer >'+
'<div class="error" ng-show="survey_question_form.textarea_max.$error.number || survey_question_form.textarea_max.$error.integer">The maximum length you entered is not a number. Please enter a number.</div>'+
'<div class="error" ng-show="survey_question_form.textarea_max.$error.awMin">The maximum length is too low. Please enter a number larger than the minimum length you set.</div>'+
'</div>'+
'</div>',
ngShow: 'type.type==="textarea" ',
addRequired: true,
editRequired: true,
column: 2
},
int_options: {
realName: 'answer_options',
type: 'custom',
control:'<div class="row">'+
'<div class="col-xs-6">'+
'<label for="minimum"><span class="label-text">Minimum</span></label><input id="int_min" type="number" name="int_min" ng-model="int_min" aw-max="int_max" class="form-control" integer >'+
'<div class="error" ng-show="survey_question_form.int_min.$error.number || survey_question_form.int_min.$error.integer">Please enter a valid integer.</div>'+
'<div class="error" ng-show="survey_question_form.int_min.$error.awMax">Please enter a smaller integer.</div>'+
'</div>'+
'<div class="col-xs-6">'+
'<label for="minimum"><span class="label-text">Maximum</span></label><input id="int_max" type="number" name="int_max" ng-model="int_max" aw-min="int_min" class="form-control" integer >'+
'<div class="error" ng-show="survey_question_form.int_max.$error.number || survey_question_form.int_max.$error.integer">Please enter a valid integer.</div>'+
'<div class="error" ng-show="survey_question_form.int_max.$error.awMin">Please enter a larger integer.</div>'+
'</div>'+
'</div>',
ngShow: 'type.type==="integer" ',
addRequired: true,
editRequired: true,
column: 2
},
float_options: {
realName: 'answer_options',
type: 'custom',
control: '<div class="row">'+
'<div class="col-xs-6">'+
'<label for="minimum"><span class="label-text">Minimum</span></label><input id="float_min" type="number" name="float_min" ng-model="float_min" class="form-control" smart-float aw-max="float_max">'+
'<div class="error" ng-show="survey_question_form.float_min.$error.float">Please enter a valid float.</div>'+
'<div class="error" ng-show="survey_question_form.float_min.$error.awMax">Please enter a smaller float.</div>'+
'</div>'+
'<div class="col-xs-6">'+
'<label for="maximum"><span class="label-text">Maximum</span></label><input id="float_max" type="number" name="float_max" ng-model="float_max" class="form-control" smart-float aw-min="float_min">'+
'<div class="error" ng-show="survey_question_form.float_max.$error.float">Please enter a valid float.</div>'+
'<div class="error" ng-show="survey_question_form.float_max.$error.awMin">Please enter a larger float.</div>'+
'</div>'+
'</div>',
ngShow: 'type.type==="float" ',
addRequired: true,
editRequired: true,
column: 2
},
default: {
realName: 'default_answer',
label: 'Default Answer',
type: 'text',
addRequired: false,
editRequired: false,
column: 2,
ngHide: 'type.type === "textarea" || type.type === "multiselect" || type.type === "integer" || type.type === "float" '
},
// default_text: {
// realName: 'default_answer',
// type: 'custom',
// control: '<div>'+
// '<label for="default_text"><span class="label-text">Default Answer</span></label>'+
// '<input type="text" ng-model="default_text" name="default_text" class="form-control" />'+
// '<div class="error" ng-show="survey_question_form.default_text.$error.minlength || survey_question_form.default_text.$error.maxlength"> The answer must be between {{text_min}} to {{text_max}} characters long!</div>'+
// '</div>',
// column: 2,
// ngShow: 'type.type === "text" '
// },
default_multiselect: {
realName: 'default_answer',
label: 'Default Answer',
type: 'textarea',
rows: 3,
addRequired: false,
editRequired: false,
column: 2,
ngShow: 'type.type === "multiselect" '
},
default_int: {
realName: 'default_answer',
type: 'custom',
control: '<div>'+
'<label for="default_int"><span class="label-text">Default Answer</span></label>'+
'<input type="number" ng-model="default_int" name="default_int" aw-min="int_min" aw-max="int_max" class="form-control" integer />'+
'<div class="error" ng-show="survey_question_form.default_int.$error.number || survey_question_form.default_int.$error.integer">Please enter a valid integer.</div>'+
'<div class="error" ng-show="survey_question_form.default_int.$error.awMin || survey_question_form.default_int.$error.awMax"> Please enter a value in the range of {{int_min}} to {{int_max}}.</div>'+
'</div>',
column: 2,
ngShow: 'type.type === "integer" '
},
default_float: {
realName: 'default_answer',
type: 'custom',
control: '<div>'+
'<label for="default_float"><span class="label-text">Default Answer</span></label>'+
'<input type="number" ng-model="default_float" name="default_float" aw-min="float_min" aw-max="float_max" class="form-control" />'+
'<div class="error" ng-show="survey_question_form.default_float.$error.number || survey_question_form.default_float.$error.float">Please enter a valid float.</div>'+
'<div class="error" ng-show="survey_question_form.default_float.$error.awMin || survey_question_form.default_float.$error.awMax"> Please enter a value in the range of {{float_min}} to {{float_max}}!</div>'+
'</div>',
column: 2,
ngShow: 'type.type=== "float" '
},
default_textarea: {
realName: 'default_answer',
label: 'Default Answer',
type: 'textarea',
rows: 3,
addRequired: false,
editRequired: false,
column: 2,
ngShow: 'type.type === "textarea" '
},
required: {
realName: 'required_answer',
label: 'Required',
type: 'checkbox',
addRequired: false,
editRequired: false,
column: 2
}
}, },
default: { buttons: {
realName: 'default_answer', question_cancel : {
label: 'Default Answer', label: 'Cancel',
type: 'text', 'class' : 'btn btn-default',
addRequired: false, ngClick: 'cancelQuestion($event)'
editRequired: false, },
column: 2, submit_question: {
ngHide: 'type.type === "textarea" || type.type === "multiselect" || type.type === "integer" || type.type === "float" ' ngClick: 'submitQuestion($event)',
}, ngDisabled: true, //'survey_question.$valid', //"!question_name || !variable || !type || ((type.type==='multiplechoice' || type.type === 'multiselect' ) && !choices)", //|| type.type===multiselect ',//'!question_name || !variable || !type' ,
// default_text: { 'class': 'btn btn-sm btn-primary',
// realName: 'default_answer', label: 'Add Question'
// type: 'custom', }
// control: '<div>'+
// '<label for="default_text"><span class="label-text">Default Answer</span></label>'+
// '<input type="text" ng-model="default_text" name="default_text" class="form-control" />'+
// '<div class="error" ng-show="survey_question_form.default_text.$error.minlength || survey_question_form.default_text.$error.maxlength"> The answer must be between {{text_min}} to {{text_max}} characters long!</div>'+
// '</div>',
// column: 2,
// ngShow: 'type.type === "text" '
// },
default_multiselect: {
realName: 'default_answer',
label: 'Default Answer',
type: 'textarea',
rows: 3,
addRequired: false,
editRequired: false,
column: 2,
ngShow: 'type.type === "multiselect" '
},
default_int: {
realName: 'default_answer',
type: 'custom',
control: '<div>'+
'<label for="default_int"><span class="label-text">Default Answer</span></label>'+
'<input type="number" ng-model="default_int" name="default_int" aw-min="int_min" aw-max="int_max" class="form-control" integer />'+
'<div class="error" ng-show="survey_question_form.default_int.$error.number || survey_question_form.default_int.$error.integer">Please enter a valid integer.</div>'+
'<div class="error" ng-show="survey_question_form.default_int.$error.awMin || survey_question_form.default_int.$error.awMax"> Please enter a value in the range of {{int_min}} to {{int_max}}.</div>'+
'</div>',
column: 2,
ngShow: 'type.type === "integer" '
},
default_float: {
realName: 'default_answer',
type: 'custom',
control: '<div>'+
'<label for="default_float"><span class="label-text">Default Answer</span></label>'+
'<input type="number" ng-model="default_float" name="default_float" aw-min="float_min" aw-max="float_max" class="form-control" />'+
'<div class="error" ng-show="survey_question_form.default_float.$error.number || survey_question_form.default_float.$error.float">Please enter a valid float.</div>'+
'<div class="error" ng-show="survey_question_form.default_float.$error.awMin || survey_question_form.default_float.$error.awMax"> Please enter a value in the range of {{float_min}} to {{float_max}}!</div>'+
'</div>',
column: 2,
ngShow: 'type.type=== "float" '
},
default_textarea: {
realName: 'default_answer',
label: 'Default Answer',
type: 'textarea',
rows: 3,
addRequired: false,
editRequired: false,
column: 2,
ngShow: 'type.type === "textarea" '
},
required: {
realName: 'required_answer',
label: 'Required',
type: 'checkbox',
addRequired: false,
editRequired: false,
column: 2
} }
},
buttons: {
question_cancel : {
label: 'Cancel',
'class' : 'btn btn-default',
ngClick: 'cancelQuestion($event)'
},
submit_question: {
ngClick: 'submitQuestion($event)',
ngDisabled: true, //'survey_question.$valid', //"!question_name || !variable || !type || ((type.type==='multiplechoice' || type.type === 'multiselect' ) && !choices)", //|| type.type===multiselect ',//'!question_name || !variable || !type' ,
'class': 'btn btn-sm btn-primary',
label: 'Add Question'
}
}
}); });

View File

@@ -11,265 +11,267 @@
* @name forms.function:Teams * @name forms.function:Teams
* @description This form is for adding/editing teams * @description This form is for adding/editing teams
*/ */
angular.module('TeamFormDefinition', [])
.value('TeamForm', {
addTitle: 'Create Team', //Legend in add mode export default
editTitle: '{{ name }}', //Legend in edit mode angular.module('TeamFormDefinition', [])
name: 'team', .value('TeamForm', {
well: true,
collapse: true,
collapseTitle: "Properties",
collapseMode: 'edit',
collapseOpen: true,
actions: { addTitle: 'Create Team', //Legend in add mode
stream: { editTitle: '{{ name }}', //Legend in edit mode
'class': "btn-primary btn-xs activity-btn", name: 'team',
ngClick: "showActivity()", well: true,
awToolTip: "View Activity Stream", collapse: true,
dataPlacement: "top", collapseTitle: "Properties",
icon: "icon-comments-alt", collapseMode: 'edit',
mode: 'edit', collapseOpen: true,
iconSize: 'large'
}
},
fields: { actions: {
name: { stream: {
label: 'Name', 'class': "btn-primary btn-xs activity-btn",
type: 'text', ngClick: "showActivity()",
addRequired: true, awToolTip: "View Activity Stream",
editRequired: true, dataPlacement: "top",
capitalize: false icon: "icon-comments-alt",
}, mode: 'edit',
description: { iconSize: 'large'
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
},
organization: {
label: 'Organization',
type: 'lookup',
sourceModel: 'organization',
sourceField: 'name',
ngClick: 'lookUpOrganization()',
awRequiredWhen: {
variable: "teamrequired",
init: "true"
} }
}
},
buttons: {
save: {
ngClick: 'formSave()',
ngDisabled: true
}, },
reset: {
ngClick: 'formReset()',
ngDisabled: true
}
},
related: { fields: {
name: {
credentials: { label: 'Name',
type: 'collection', type: 'text',
title: 'Credentials', addRequired: true,
iterator: 'credential', editRequired: true,
open: false, capitalize: false
index: false,
actions: {
add: {
ngClick: "add('credentials')",
icon: 'icon-plus',
label: 'Add',
add: 'Add a new credential'
}
}, },
description: {
fields: { label: 'Description',
name: { type: 'text',
key: true, addRequired: false,
label: 'Name' editRequired: false
},
description: {
label: 'Description'
}
}, },
organization: {
fieldActions: { label: 'Organization',
edit: { type: 'lookup',
label: 'Edit', sourceModel: 'organization',
ngClick: "edit('credentials', credential.id, credential.name)", sourceField: 'name',
icon: 'icon-edit', ngClick: 'lookUpOrganization()',
awToolTip: 'Modify the credential', awRequiredWhen: {
'class': 'btn btn-default' variable: "teamrequired",
}, init: "true"
"delete": {
label: 'Delete',
ngClick: "delete('credentials', credential.id, credential.name, 'credentials')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Remove the credential'
} }
} }
}, },
permissions: { buttons: {
type: 'collection', save: {
title: 'Permissions', ngClick: 'formSave()',
iterator: 'permission', ngDisabled: true
open: false,
index: false,
actions: {
add: {
ngClick: "add('permissions')",
icon: 'icon-plus',
label: 'Add',
awToolTip: 'Add a permission for this user',
ngShow: 'PermissionAddAllowed'
}
}, },
reset: {
fields: { ngClick: 'formReset()',
name: { ngDisabled: true
key: true,
label: '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)",
icon: 'icon-edit',
awToolTip: 'Edit the permission',
'class': 'btn btn-default'
},
"delete": {
label: 'Delete',
ngClick: "delete('permissions', permission.id, permission.name, 'permissions')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Delete the permission',
ngShow: 'PermissionAddAllowed'
}
}
},
projects: {
type: 'collection',
title: 'Projects',
iterator: 'project',
open: false,
index: false,
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: { related: {
type: 'collection',
title: 'Users',
iterator: 'user',
open: false,
index: false,
actions: { credentials: {
add: { type: 'collection',
ngClick: "add('users')", title: 'Credentials',
icon: 'icon-plus', iterator: 'credential',
label: 'Add', open: false,
awToolTip: 'Add a user' index: false,
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)",
icon: 'icon-edit',
awToolTip: 'Modify the credential',
'class': 'btn btn-default'
},
"delete": {
label: 'Delete',
ngClick: "delete('credentials', credential.id, credential.name, 'credentials')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Remove the credential'
}
} }
}, },
fields: { permissions: {
username: { type: 'collection',
key: true, title: 'Permissions',
label: 'Username' iterator: 'permission',
open: false,
index: false,
actions: {
add: {
ngClick: "add('permissions')",
icon: 'icon-plus',
label: 'Add',
awToolTip: 'Add a permission for this user',
ngShow: 'PermissionAddAllowed'
}
}, },
first_name: {
label: 'First Name' fields: {
name: {
key: true,
label: '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'
}
}, },
last_name: {
label: 'Last Name' fieldActions: {
edit: {
label: 'Edit',
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')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Delete the permission',
ngShow: 'PermissionAddAllowed'
}
}
},
projects: {
type: 'collection',
title: 'Projects',
iterator: 'project',
open: false,
index: false,
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'
}
} }
}, },
fieldActions: { users: {
edit: { type: 'collection',
label: 'Edit', title: 'Users',
ngClick: "edit('users', user.id, user.username)", iterator: 'user',
icon: 'icon-edit', open: false,
awToolTip: 'Edit user', index: false,
'class': 'btn btn-default'
actions: {
add: {
ngClick: "add('users')",
icon: 'icon-plus',
label: 'Add',
awToolTip: 'Add a user'
}
}, },
"delete": {
label: 'Delete', fields: {
ngClick: "delete('users', user.id, user.username, 'users')", username: {
icon: 'icon-terash', key: true,
"class": 'btn-danger', label: 'Username'
awToolTip: 'Remove user' },
first_name: {
label: 'First Name'
},
last_name: {
label: 'Last Name'
}
},
fieldActions: {
edit: {
label: 'Edit',
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')",
icon: 'icon-terash',
"class": 'btn-danger',
awToolTip: 'Remove user'
}
} }
} }
} }
} }); //InventoryForm
}); //InventoryForm

View File

@@ -11,288 +11,290 @@
* @name forms.function:Users * @name forms.function:Users
* @description This form is for adding/editing users * @description This form is for adding/editing users
*/ */
angular.module('UserFormDefinition', [])
.value('UserForm', {
addTitle: 'Create User', export default
editTitle: '{{ username }}', angular.module('UserFormDefinition', [])
name: 'user', .value('UserForm', {
well: true,
forceListeners: true,
collapse: true,
collapseTitle: "Properties",
collapseMode: 'edit',
collapseOpen: true,
actions: { addTitle: 'Create User',
stream: { editTitle: '{{ username }}',
'class': "btn-primary btn-xs activity-btn", name: 'user',
ngClick: "showActivity()", well: true,
awToolTip: "View Activity Stream", forceListeners: true,
dataPlacement: "top", collapse: true,
icon: "icon-comments-alt", collapseTitle: "Properties",
mode: 'edit', collapseMode: 'edit',
iconSize: 'large' collapseOpen: true,
}
},
fields: { actions: {
first_name: { stream: {
label: 'First Name', 'class': "btn-primary btn-xs activity-btn",
type: 'text', ngClick: "showActivity()",
addRequired: true, awToolTip: "View Activity Stream",
editRequired: true, dataPlacement: "top",
capitalize: true icon: "icon-comments-alt",
}, mode: 'edit',
last_name: { iconSize: 'large'
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',
sourceModel: 'organization',
sourceField: 'name',
ngClick: 'lookUpOrganization()',
excludeMode: 'edit',
awRequiredWhen: {
variable: "orgrequired",
init: true
}
},
username: {
label: 'Username',
type: 'text',
awRequiredWhen: {
variable: "not_ldap_user",
init: true
},
autocomplete: false
},
password: {
label: 'Password',
type: 'password',
ngShow: 'ldap_user == false',
addRequired: true,
editRequired: false,
ngChange: "clearPWConfirm('password_confirm')",
autocomplete: false,
chkPass: true
},
password_confirm: {
label: 'Confirm Password',
type: 'password',
ngShow: 'ldap_user == false',
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'password',
autocomplete: false
},
is_superuser: {
label: 'Superuser (User has full system administration privileges.)',
type: 'checkbox',
trueValue: 'true',
falseValue: 'false',
"default": 'false',
ngShow: "current_user['is_superuser'] == true"
},
ldap_user: {
label: 'Created by LDAP',
type: 'checkbox',
readonly: true
}
},
buttons: {
save: {
ngClick: 'formSave()',
ngDisabled: true
},
reset: {
ngClick: 'formReset()',
ngDisabled: true
}
},
related: {
credentials: {
type: 'collection',
title: 'Credentials',
iterator: 'credential',
open: false,
index: false,
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)",
icon: 'icon-edit',
awToolTip: 'Edit the credential',
'class': 'btn btn-default'
},
"delete": {
label: 'Delete',
ngClick: "delete('credentials', credential.id, credential.name, 'credentials')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Delete the credential'
}
} }
}, },
permissions: { fields: {
type: 'collection', first_name: {
title: 'Permissions', label: 'First Name',
iterator: 'permission', type: 'text',
open: false, addRequired: true,
index: false, editRequired: true,
capitalize: true
},
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',
sourceModel: 'organization',
sourceField: 'name',
ngClick: 'lookUpOrganization()',
excludeMode: 'edit',
awRequiredWhen: {
variable: "orgrequired",
init: true
}
},
username: {
label: 'Username',
type: 'text',
awRequiredWhen: {
variable: "not_ldap_user",
init: true
},
autocomplete: false
},
password: {
label: 'Password',
type: 'password',
ngShow: 'ldap_user == false',
addRequired: true,
editRequired: false,
ngChange: "clearPWConfirm('password_confirm')",
autocomplete: false,
chkPass: true
},
password_confirm: {
label: 'Confirm Password',
type: 'password',
ngShow: 'ldap_user == false',
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'password',
autocomplete: false
},
is_superuser: {
label: 'Superuser (User has full system administration privileges.)',
type: 'checkbox',
trueValue: 'true',
falseValue: 'false',
"default": 'false',
ngShow: "current_user['is_superuser'] == true"
},
ldap_user: {
label: 'Created by LDAP',
type: 'checkbox',
readonly: true
}
},
actions: { buttons: {
add: { save: {
ngClick: "add('permissions')", ngClick: 'formSave()',
icon: 'icon-plus', ngDisabled: true
label: 'Add', },
awToolTip: 'Add a permission for this user', reset: {
ngShow: 'PermissionAddAllowed' ngClick: 'formReset()',
ngDisabled: true
}
},
related: {
credentials: {
type: 'collection',
title: 'Credentials',
iterator: 'credential',
open: false,
index: false,
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)",
icon: 'icon-edit',
awToolTip: 'Edit the credential',
'class': 'btn btn-default'
},
"delete": {
label: 'Delete',
ngClick: "delete('credentials', credential.id, credential.name, 'credentials')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Delete the credential'
}
} }
}, },
fields: { permissions: {
name: { type: 'collection',
key: true, title: 'Permissions',
label: 'Name', iterator: 'permission',
ngClick: "edit('permissions', permission.id, permission.name)" open: false,
index: false,
actions: {
add: {
ngClick: "add('permissions')",
icon: 'icon-plus',
label: 'Add',
awToolTip: 'Add a permission for this user',
ngShow: 'PermissionAddAllowed'
}
}, },
inventory: {
label: 'Inventory', fields: {
sourceModel: 'inventory', name: {
sourceField: 'name', key: true,
ngBind: 'permission.summary_fields.inventory.name' label: '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'
}
}, },
project: {
label: 'Project', fieldActions: {
sourceModel: 'project', edit: {
sourceField: 'name', label: 'Edit',
ngBind: 'permission.summary_fields.project.name' ngClick: "edit('permissions', permission.id, permission.name)",
}, icon: 'icon-edit',
permission_type: { awToolTip: 'Edit the permission',
label: 'Permission' 'class': 'btn btn-default'
},
"delete": {
label: 'Delete',
ngClick: "delete('permissions', permission.id, permission.name, 'permissions')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Delete the permission',
ngShow: 'PermissionAddAllowed'
}
} }
}, },
fieldActions: { admin_of_organizations: { // Assumes a plural name (e.g. things)
edit: { type: 'collection',
label: 'Edit', title: 'Admin of Organizations',
ngClick: "edit('permissions', permission.id, permission.name)", iterator: 'adminof', // Singular form of name (e.g. thing)
icon: 'icon-edit', open: false, // Open accordion on load?
awToolTip: 'Edit the permission', index: false,
'class': 'btn btn-default' base: '/organizations',
},
"delete": { actions: {},
label: 'Delete',
ngClick: "delete('permissions', permission.id, permission.name, 'permissions')", fields: {
icon: 'icon-trash', name: {
"class": 'btn-danger', key: true,
awToolTip: 'Delete the permission', label: 'Name'
ngShow: 'PermissionAddAllowed' },
description: {
label: 'Description'
}
} }
} },
}, organizations: {
type: 'collection',
title: 'Organizations',
iterator: 'organization',
index: false,
open: false,
admin_of_organizations: { // Assumes a plural name (e.g. things) actions: {},
type: 'collection',
title: 'Admin of Organizations',
iterator: 'adminof', // Singular form of name (e.g. thing)
open: false, // Open accordion on load?
index: false,
base: '/organizations',
actions: {}, fields: {
name: {
fields: { key: true,
name: { label: 'Name'
key: true, },
label: 'Name' description: {
}, label: 'Description'
description: { }
label: 'Description'
} }
} },
},
organizations: { teams: {
type: 'collection', type: 'collection',
title: 'Organizations', title: 'Teams',
iterator: 'organization', iterator: 'team',
index: false, open: false,
open: false, index: false,
actions: {}, actions: {},
fields: { fields: {
name: { name: {
key: true, key: true,
label: 'Name' label: 'Name'
}, },
description: { description: {
label: 'Description' label: 'Description'
} }
}
},
teams: {
type: 'collection',
title: 'Teams',
iterator: 'team',
open: false,
index: false,
actions: {},
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
} }
} }
} }
}
}); //UserForm }); //UserForm

11
awx/ui/static/js/help.js Normal file
View File

@@ -0,0 +1,11 @@
import ChromeSocketHelp from "tower/help/ChromeSocketHelp";
import FirefoxSocketHelp from "tower/help/FirefoxSocketHelp";
import InventoryGroups from "tower/help/InventoryGroups";
import SafariSocketHelp from "tower/help/SafariSocketHelp";
export
{ ChromeSocketHelp,
FirefoxSocketHelp,
InventoryGroups,
SafariSocketHelp
};

View File

@@ -18,7 +18,7 @@
* @name help.function:ChromeSocketHelp * @name help.function:ChromeSocketHelp
* @description This help modal gives instructions on what the user should do if not connected to the web sockets while using Chrome. * @description This help modal gives instructions on what the user should do if not connected to the web sockets while using Chrome.
*/ */
'use strict';
angular.module('ChromeSocketHelpDefinition', []) angular.module('ChromeSocketHelpDefinition', [])
.value('ChromeSocketHelp', { .value('ChromeSocketHelp', {

View File

@@ -11,7 +11,7 @@
* @name help.function:FirefoxSocketHelp * @name help.function:FirefoxSocketHelp
* @description This help modal gives instructions on what the user should do if not connected to the web sockets while using Firefox. * @description This help modal gives instructions on what the user should do if not connected to the web sockets while using Firefox.
*/ */
'use strict';
angular.module('FFSocketHelpDefinition', []) angular.module('FFSocketHelpDefinition', [])
.value('FFSocketHelp', { .value('FFSocketHelp', {

View File

@@ -12,7 +12,7 @@
* @name help.function:InventoryGroups * @name help.function:InventoryGroups
* @description This help modal walks the user how to add groups to an inventory or a subgroup to an existing group. * @description This help modal walks the user how to add groups to an inventory or a subgroup to an existing group.
*/ */
'use strict';
angular.module('InventoryGroupsHelpDefinition', []) angular.module('InventoryGroupsHelpDefinition', [])
.value('InventoryGroupsHelp', { .value('InventoryGroupsHelp', {

View File

@@ -11,7 +11,7 @@
* @name help.function:SafariSocketHelp * @name help.function:SafariSocketHelp
* @description This help modal gives instructions on what the user should do if not connected to the web sockets while using Safari. Safari does not support websockets. * @description This help modal gives instructions on what the user should do if not connected to the web sockets while using Safari. Safari does not support websockets.
*/ */
'use strict';
angular.module('SafariSocketHelpDefinition', []) angular.module('SafariSocketHelpDefinition', [])
.value('SafariSocketHelp', { .value('SafariSocketHelp', {

View File

@@ -0,0 +1,82 @@
import 'tower/forms';
import 'tower/lists';
import AboutAnsible from "tower/helpers/AboutAnsible";
import Access from "tower/helpers/Access";
import Children from "tower/helpers/Children";
import ConfigureTower from "tower/helpers/ConfigureTower";
import Credentials from "tower/helpers/Credentials";
import CustomInventory from "tower/helpers/CustomInventory";
import EventViewer from "tower/helpers/EventViewer";
import Events from "tower/helpers/Events";
import Groups from "tower/helpers/Groups";
import HostEventsViewer from "tower/helpers/HostEventsViewer";
import Hosts from "tower/helpers/Hosts";
import JobDetail from "tower/helpers/JobDetail";
import JobSubmission from "tower/helpers/JobSubmission";
import JobTemplates from "tower/helpers/JobTemplates";
import Jobs from "tower/helpers/Jobs";
import License from "tower/helpers/License";
import LoadConfig from "tower/helpers/LoadConfig";
import LogViewer from "tower/helpers/LogViewer";
import Lookup from "tower/helpers/Lookup";
import PaginationHelpers from "tower/helpers/PaginationHelpers";
import Parse from "tower/helpers/Parse";
import Permissions from "tower/helpers/Permissions";
import ProjectPath from "tower/helpers/ProjectPath";
import Projects from "tower/helpers/Projects";
import Schedules from "tower/helpers/Schedules";
import Selection from "tower/helpers/Selection";
import SocketHelper from "tower/helpers/SocketHelper";
import Survey from "tower/helpers/Survey";
import Users from "tower/helpers/Users";
import Variables from "tower/helpers/Variables";
import ApiDefaults from "tower/helpers/api-defaults";
import inventory from "tower/helpers/inventory";
import MD5 from "tower/helpers/md5";
import RefreshRelated from "tower/helpers/refresh-related";
import Refresh from "tower/helpers/refresh";
import RelatedSearch from "tower/helpers/related-search";
import Search from "tower/helpers/search";
import Teams from "tower/helpers/teams";
export
{ AboutAnsible,
Access,
Children,
ConfigureTower,
Credentials,
CustomInventory,
EventViewer,
Events,
Groups,
HostEventsViewer,
Hosts,
JobDetail,
JobSubmission,
JobTemplates,
Jobs,
License,
LoadConfig,
LogViewer,
Lookup,
PaginationHelpers,
Parse,
Permissions,
ProjectPath,
Projects,
Schedules,
Selection,
SocketHelper,
Survey,
Users,
Variables,
ApiDefaults,
inventory,
MD5,
RefreshRelated,
Refresh,
RelatedSearch,
Search,
Teams
};

View File

@@ -16,76 +16,77 @@
* @name helpers.function:AboutAnsible * @name helpers.function:AboutAnsible
* @description This is the code for the About Ansible modal window that pops up with cowsay giving company/tower info and copyright information. * @description This is the code for the About Ansible modal window that pops up with cowsay giving company/tower info and copyright information.
*/ */
'use strict';
angular.module('AboutAnsibleHelpModal', ['RestServices', 'Utilities','ModalDialog'])
.factory('AboutAnsibleHelp', ['$rootScope', '$compile', '$location' , 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait', 'CreateDialog',
function ($rootScope, $compile , $location, Rest, GetBasePath, ProcessErrors, Wait, CreateDialog) {
return function () {
var scope= $rootScope.$new(), export default
url; angular.module('AboutAnsibleHelpModal', ['RestServices', 'Utilities','ModalDialog'])
.factory('AboutAnsibleHelp', ['$rootScope', '$compile', '$location' , 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait', 'CreateDialog',
function ($rootScope, $compile , $location, Rest, GetBasePath, ProcessErrors, Wait, CreateDialog) {
return function () {
url = GetBasePath('config'); var scope= $rootScope.$new(),
Rest.setUrl(url); url;
Rest.get()
.success(function (data){ url = GetBasePath('config');
scope.$emit('BuildAboutDialog', data); Rest.setUrl(url);
}) Rest.get()
.error(function (data, status) { .success(function (data){
ProcessErrors(scope, data, status, null, { hdr: 'Error!', scope.$emit('BuildAboutDialog', data);
msg: 'Failed to get: ' + url + ' GET returned: ' + status }); })
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to get: ' + url + ' GET returned: ' + status });
});
if (scope.removeDialogReady) {
scope.removeDialogReady();
}
scope.removeDialogReady = scope.$on('DialogReady', function() {
// element = angular.element(document.getElementById('about-modal-dialog'));
// $compile(element)(scope);
$('#about-modal-dialog').dialog('open');
}); });
if (scope.removeBuildAboutDialog) {
if (scope.removeDialogReady) { scope.removeBuildAboutDialog();
scope.removeDialogReady();
}
scope.removeDialogReady = scope.$on('DialogReady', function() {
// element = angular.element(document.getElementById('about-modal-dialog'));
// $compile(element)(scope);
$('#about-modal-dialog').dialog('open');
});
if (scope.removeBuildAboutDialog) {
scope.removeBuildAboutDialog();
}
scope.removeBuildAboutDialog = scope.$on('BuildAboutDialog', function(e, data) {
var spaces, i, j,
paddedStr = "",
version = data.version.replace(/-.*$/,'');
spaces = Math.floor((16-version.length)/2);
for( i=0; i<=spaces; i++){
paddedStr = paddedStr +" ";
} }
paddedStr = paddedStr+version; scope.removeBuildAboutDialog = scope.$on('BuildAboutDialog', function(e, data) {
for( j = paddedStr.length; j<16; j++){ var spaces, i, j,
paddedStr = paddedStr + " "; paddedStr = "",
} version = data.version.replace(/-.*$/,'');
$('#about-modal-version').html(paddedStr);
scope.modalOK = function(){ spaces = Math.floor((16-version.length)/2);
$('#about-modal-dialog').dialog('close'); for( i=0; i<=spaces; i++){
}; paddedStr = paddedStr +" ";
CreateDialog({
id: 'about-modal-dialog',
scope: scope,
// buttons: [],
width: 710,
height: 380,
minWidth: 300,
resizable: false,
// title: , //'<img src="static/img/tower_login_logo.png">' ,//'About Ansible',
callback: 'DialogReady',
onOpen: function(){
$('#dialog-ok-button').focus();
$('#about-modal-dialog').scrollTop(0);
$('#about-modal-dialog').css('overflow-x', 'hidden');
$('.ui-widget-overlay').css('width', '100%');
} }
paddedStr = paddedStr+version;
for( j = paddedStr.length; j<16; j++){
paddedStr = paddedStr + " ";
}
$('#about-modal-version').html(paddedStr);
scope.modalOK = function(){
$('#about-modal-dialog').dialog('close');
};
CreateDialog({
id: 'about-modal-dialog',
scope: scope,
// buttons: [],
width: 710,
height: 380,
minWidth: 300,
resizable: false,
// title: , //'<img src="static/img/tower_login_logo.png">' ,//'About Ansible',
callback: 'DialogReady',
onOpen: function(){
$('#dialog-ok-button').focus();
$('#about-modal-dialog').scrollTop(0);
$('#about-modal-dialog').css('overflow-x', 'hidden');
$('.ui-widget-overlay').css('width', '100%');
}
});
}); });
});
}; };
} }
]); ]);

View File

@@ -12,57 +12,57 @@
* @description routines checking user access * @description routines checking user access
*/ */
'use strict';
angular.module('AccessHelper', ['RestServices', 'Utilities']) export default
angular.module('AccessHelper', ['RestServices', 'Utilities'])
.factory('CheckAccess', ['$rootScope', 'Alert', 'Rest', 'GetBasePath', 'ProcessErrors', '$cookieStore', function ($rootScope, Alert, Rest, GetBasePath, ProcessErrors, $cookieStore) { .factory('CheckAccess', ['$rootScope', 'Alert', 'Rest', 'GetBasePath', 'ProcessErrors', '$cookieStore', function ($rootScope, Alert, Rest, GetBasePath, ProcessErrors, $cookieStore) {
return function (params) { return function (params) {
// set PermissionAddAllowed to true or false based on user access. admins and org admins are granted // set PermissionAddAllowed to true or false based on user access. admins and org admins are granted
// accesss. // accesss.
var scope = params.scope, var scope = params.scope,
callback = params.callback || undefined, callback = params.callback || undefined,
me; me;
// uer may have refreshed the browser, in which case retrieve current user info from session cookie // uer may have refreshed the browser, in which case retrieve current user info from session cookie
me = ($rootScope.current_user) ? $rootScope.current_user : $cookieStore.get('current_user'); me = ($rootScope.current_user) ? $rootScope.current_user : $cookieStore.get('current_user');
if (me.is_superuser) { if (me.is_superuser) {
scope.PermissionAddAllowed = true; scope.PermissionAddAllowed = true;
if(callback){ if(callback){
scope.$emit(callback); scope.$emit(callback);
} }
} else { } else {
if (me.related.admin_of_organizations) { if (me.related.admin_of_organizations) {
Rest.setUrl(me.related.admin_of_organizations); Rest.setUrl(me.related.admin_of_organizations);
Rest.get() Rest.get()
.success(function (data) { .success(function (data) {
if (data.results.length > 0) { if (data.results.length > 0) {
scope.PermissionAddAllowed = true; scope.PermissionAddAllowed = true;
} else { } else {
scope.PermissionAddAllowed = false; scope.PermissionAddAllowed = false;
} }
if(callback){ if(callback){
scope.$emit(callback); scope.$emit(callback);
} }
}) })
.error(function (data, status) { .error(function (data, status) {
ProcessErrors(scope, data, status, null, { ProcessErrors(scope, data, status, null, {
hdr: 'Error!', hdr: 'Error!',
msg: 'Call to ' + me.related.admin_of_organizations + msg: 'Call to ' + me.related.admin_of_organizations +
' failed. DELETE returned status: ' + status ' failed. DELETE returned status: ' + status
});
}); });
}); }
} }
}
//if (!access) { //if (!access) {
// Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.'); // Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
//} //}
//return access; //return access;
}; };
}]) }])
.factory('IsAdmin', ['$rootScope', function($rootScope) { .factory('IsAdmin', ['$rootScope', function($rootScope) {
return function() { return ($rootScope.current_user && $rootScope.current_user.is_superuser); }; return function() { return ($rootScope.current_user && $rootScope.current_user.is_superuser); };
}]); }]);

View File

@@ -11,101 +11,101 @@
* 'show' attribute of each job_event in the set of job_events. * 'show' attribute of each job_event in the set of job_events.
* See the filter in job_events.js list. * See the filter in job_events.js list.
*/ */
'use strict';
angular.module('ChildrenHelper', ['RestServices', 'Utilities']) export default
.factory('ToggleChildren', ['$location', 'Store', function ($location, Store) { angular.module('ChildrenHelper', ['RestServices', 'Utilities'])
return function (params) { .factory('ToggleChildren', ['$location', 'Store', function ($location, Store) {
return function (params) {
var scope = params.scope, var scope = params.scope,
list = params.list, list = params.list,
id = params.id, id = params.id,
set = scope[list.name], set = scope[list.name],
clicked, clicked,
//base = $location.path().replace(/^\//, '').split('/')[0], //base = $location.path().replace(/^\//, '').split('/')[0],
path = $location.path(), path = $location.path(),
local_child_store; local_child_store;
function updateExpand(key, expand) { function updateExpand(key, expand) {
var found = false; var found = false;
local_child_store.every(function(child, i) { local_child_store.every(function(child, i) {
if (child.key === key) { if (child.key === key) {
local_child_store[i].expand = expand; local_child_store[i].expand = expand;
found = true; found = true;
return false; return false;
} }
return true; return true;
}); });
if (!found) { if (!found) {
local_child_store.push({ key: key, expand: expand }); local_child_store.push({ key: key, expand: expand });
}
}
function updateShow(key, show) {
var found = false;
local_child_store.every(function(child, i) {
if (child.key === key) {
local_child_store[i].show = show;
found = true;
return false;
}
return true;
});
if (!found) {
local_child_store.push({ key: key, show: show });
}
}
function expand(node) {
var i, has_children = false;
for (i = node + 1; i < set.length; i++) {
if (set[i].parent === set[node].id) {
updateShow(set[i].key, true);
set[i].show = true;
} }
} }
set[node].ngicon = (has_children) ? 'fa fa-minus-square-o node-toggle' : 'fa fa-minus-square-o node-toggle';
}
function collapse(node) { function updateShow(key, show) {
var i, has_children = false; var found = false;
for (i = node + 1; i < set.length; i++) { local_child_store.every(function(child, i) {
if (set[i].parent === set[node].id) { if (child.key === key) {
set[i].show = false; local_child_store[i].show = show;
has_children = true; found = true;
updateShow(set[i].key, false); return false;
if (set[i].related.children) { }
collapse(i); return true;
});
if (!found) {
local_child_store.push({ key: key, show: show });
}
}
function expand(node) {
var i, has_children = false;
for (i = node + 1; i < set.length; i++) {
if (set[i].parent === set[node].id) {
updateShow(set[i].key, true);
set[i].show = true;
} }
} }
set[node].ngicon = (has_children) ? 'fa fa-minus-square-o node-toggle' : 'fa fa-minus-square-o node-toggle';
} }
set[node].ngicon = (has_children) ? 'fa fa-plus-square-o node-toggle' : 'fa fa-square-o node-toggle';
}
local_child_store = Store(path + '_children'); function collapse(node) {
if (!local_child_store) { var i, has_children = false;
local_child_store = []; for (i = node + 1; i < set.length; i++) {
} if (set[i].parent === set[node].id) {
set[i].show = false;
// Scan the array list and find the clicked element has_children = true;
set.every(function(row, i) { updateShow(set[i].key, false);
if (row.id === id) { if (set[i].related.children) {
clicked = i; collapse(i);
return false; }
}
}
set[node].ngicon = (has_children) ? 'fa fa-plus-square-o node-toggle' : 'fa fa-square-o node-toggle';
} }
return true;
});
// Expand or collapse children based on clicked element's icon local_child_store = Store(path + '_children');
if (/plus-square-o/.test(set[clicked].ngicon)) { if (!local_child_store) {
// Expand: lookup and display children local_child_store = [];
expand(clicked); }
updateExpand(set[clicked].key, true);
} else if (/minus-square-o/.test(set[clicked].ngicon)) { // Scan the array list and find the clicked element
collapse(clicked); set.every(function(row, i) {
updateExpand(set[clicked].key, false); if (row.id === id) {
} clicked = i;
Store(path + '_children', local_child_store); return false;
}; }
} return 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);
updateExpand(set[clicked].key, true);
} else if (/minus-square-o/.test(set[clicked].ngicon)) {
collapse(clicked);
updateExpand(set[clicked].key, false);
}
Store(path + '_children', local_child_store);
};
}
]);

View File

@@ -11,459 +11,459 @@
* *
*/ */
'use strict';
angular.module('ConfigureTowerHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ModalDialog', export default
'GeneratorHelpers']) angular.module('ConfigureTowerHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ModalDialog',
'GeneratorHelpers'])
.factory('ConfigureTower', ['Wait', '$location' , '$compile', 'CreateDialog', 'ConfigureTowerJobsList', 'GenerateList', 'GetBasePath' , 'SearchInit' , 'PaginateInit', 'PlaybookRun', 'LoadSchedulesScope', .factory('ConfigureTower', ['Wait', '$location' , '$compile', 'CreateDialog', 'ConfigureTowerJobsList', 'GenerateList', 'GetBasePath' , 'SearchInit' , 'PaginateInit', 'PlaybookRun', 'LoadSchedulesScope',
'SchedulesList', 'SchedulesControllerInit' , 'ConfigureTowerSchedule', 'Rest' , 'ProcessErrors', 'SchedulesList', 'SchedulesControllerInit' , 'ConfigureTowerSchedule', 'Rest' , 'ProcessErrors',
function(Wait, $location, $compile, CreateDialog, ConfigureTowerJobsList, GenerateList, GetBasePath, SearchInit, PaginateInit, PlaybookRun, LoadSchedulesScope, function(Wait, $location, $compile, CreateDialog, ConfigureTowerJobsList, GenerateList, GetBasePath, SearchInit, PaginateInit, PlaybookRun, LoadSchedulesScope,
SchedulesList, SchedulesControllerInit, ConfigureTowerSchedule, Rest, ProcessErrors) { SchedulesList, SchedulesControllerInit, ConfigureTowerSchedule, Rest, ProcessErrors) {
return function(params) { return function(params) {
// Set modal dimensions based on viewport width // Set modal dimensions based on viewport width
var scope = params.scope.$new(), var scope = params.scope.$new(),
parent_scope = params.scope, parent_scope = params.scope,
callback = 'OpenConfig', callback = 'OpenConfig',
defaultUrl = GetBasePath('system_job_templates'), defaultUrl = GetBasePath('system_job_templates'),
list = ConfigureTowerJobsList, list = ConfigureTowerJobsList,
view = GenerateList, e, view = GenerateList, e,
scheduleUrl = GetBasePath('system_job_templates'), scheduleUrl = GetBasePath('system_job_templates'),
buttons = [ buttons = [
{ {
"label": "Close", "label": "Close",
"onClick": function() {
// $(this).dialog('close');
scope.cancelConfigure();
},
"icon": "fa-times",
"class": "btn btn-default",
"id": "configure-close-button"
}
];
scope.cleanupJob = true;
if(scope.removeOpenConfig) {
scope.removeOpenConfig();
}
scope.removeOpenConfig = scope.$on('OpenConfig', function() {
$('#configure-tower-dialog').dialog('open');
$('#configure-close-button').focus();
$('#configure-close-button').blur();
});
view.inject( list, {
id : 'configure-jobs',
mode: 'edit',
scope: scope,
breadCrumbs: false,
showSearch: false
});
SearchInit({
scope: scope,
set: 'configure_jobs',
list: list,
url: defaultUrl
});
PaginateInit({
scope: scope,
list: list,
url: defaultUrl
});
scope.search(list.iterator);
SchedulesControllerInit({
scope: scope,
parent_scope: parent_scope,
// list: list
});
CreateDialog({
id: 'configure-tower-dialog',
title: 'Management Jobs',
target: 'configure-tower-dialog',
scope: scope,
buttons: buttons,
width: 670,
height: 800,
minWidth: 400,
callback: callback,
onClose: function () {
// Destroy on close
$('.tooltip').each(function () {
// Remove any lingering tooltip <div> elements
$(this).remove();
});
$('.popover').each(function () {
// remove lingering popover <div> elements
$(this).remove();
});
$("#configure-jobs").show();
$("#configure-schedules-form-container").hide();
$('#configure-schedules-list').empty();
$('#configure-schedules-form').empty();
$('#configure-schedules-detail').empty();
$('#configure-tower-dialog').hide();
$(this).dialog('destroy');
scope.cancelConfigure();
},
});
// Cancel
scope.cancelConfigure = function () {
try {
$('#configure-tower-dialog').dialog('close');
$("#configure-save-button").remove();
}
catch(e) {
//ignore
}
if (scope.searchCleanup) {
scope.searchCleanup();
}
// if (!Empty(parent_scope) && parent_scope.restoreSearch) {
// parent_scope.restoreSearch();
// }
else {
Wait('stop');
}
};
scope.submitJob = function (id, name) {
Wait('start');
defaultUrl = GetBasePath('system_job_templates')+id+'/launch/';
CreateDialog({
id: 'prompt-for-days' ,
title: name,
scope: scope,
width: 500,
height: 300,
minWidth: 200,
callback: 'PromptForDays',
onOpen: function(){
e = angular.element(document.getElementById('prompt_for_days_form'));
scope.prompt_for_days_form.days_to_keep.$setViewValue(30);
$compile(e)(scope);
$('#prompt-for-days-launch').attr("ng-disabled", 'prompt_for_days_form.$invalid');
e = angular.element(document.getElementById('prompt-for-days-launch'));
$compile(e)(scope);
},
buttons: [{
"label": "Cancel",
"onClick": function() { "onClick": function() {
$(this).dialog('close'); // $(this).dialog('close');
scope.cancelConfigure();
}, },
"icon": "fa-times", "icon": "fa-times",
"class": "btn btn-default", "class": "btn btn-default",
"id": "prompt-for-days-cancel" "id": "configure-close-button"
},{ }
"label": "Launch", ];
"onClick": function() {
var extra_vars = {"days": scope.days_to_keep },
data = {};
data.extra_vars = JSON.stringify(extra_vars);
Rest.setUrl(defaultUrl); scope.cleanupJob = true;
Rest.post(data)
.success(function() {
Wait('stop');
$("#prompt-for-days").dialog("close");
$("#configure-tower-dialog").dialog('close');
$location.path('/jobs/');
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed updating job ' + scope.job_template_id + ' with variables. POST returned: ' + status });
});
},
"icon": "fa-rocket",
"class": "btn btn-primary",
"id": "prompt-for-days-launch"
}]
});
if (scope.removePromptForDays) { if(scope.removeOpenConfig) {
scope.removePromptForDays(); scope.removeOpenConfig();
} }
scope.removePromptForDays = scope.$on('PromptForDays', function() { scope.removeOpenConfig = scope.$on('OpenConfig', function() {
// $('#configure-tower-dialog').dialog('close'); $('#configure-tower-dialog').dialog('open');
$('#prompt-for-days').show(); $('#configure-close-button').focus();
$('#prompt-for-days').dialog('open'); $('#configure-close-button').blur();
Wait('stop');
}); });
view.inject( list, {
id : 'configure-jobs',
mode: 'edit',
scope: scope,
breadCrumbs: false,
showSearch: false
});
SearchInit({
scope: scope,
set: 'configure_jobs',
list: list,
url: defaultUrl
});
PaginateInit({
scope: scope,
list: list,
url: defaultUrl
});
scope.search(list.iterator);
SchedulesControllerInit({
scope: scope,
parent_scope: parent_scope,
// list: list
});
CreateDialog({
id: 'configure-tower-dialog',
title: 'Management Jobs',
target: 'configure-tower-dialog',
scope: scope,
buttons: buttons,
width: 670,
height: 800,
minWidth: 400,
callback: callback,
onClose: function () {
// Destroy on close
$('.tooltip').each(function () {
// Remove any lingering tooltip <div> elements
$(this).remove();
});
$('.popover').each(function () {
// remove lingering popover <div> elements
$(this).remove();
});
$("#configure-jobs").show();
$("#configure-schedules-form-container").hide();
$('#configure-schedules-list').empty();
$('#configure-schedules-form').empty();
$('#configure-schedules-detail').empty();
$('#configure-tower-dialog').hide();
$(this).dialog('destroy');
scope.cancelConfigure();
},
});
// Cancel
scope.cancelConfigure = function () {
try {
$('#configure-tower-dialog').dialog('close');
$("#configure-save-button").remove();
}
catch(e) {
//ignore
}
if (scope.searchCleanup) {
scope.searchCleanup();
}
// if (!Empty(parent_scope) && parent_scope.restoreSearch) {
// parent_scope.restoreSearch();
// }
else {
Wait('stop');
}
};
scope.submitJob = function (id, name) {
Wait('start');
defaultUrl = GetBasePath('system_job_templates')+id+'/launch/';
CreateDialog({
id: 'prompt-for-days' ,
title: name,
scope: scope,
width: 500,
height: 300,
minWidth: 200,
callback: 'PromptForDays',
onOpen: function(){
e = angular.element(document.getElementById('prompt_for_days_form'));
scope.prompt_for_days_form.days_to_keep.$setViewValue(30);
$compile(e)(scope);
$('#prompt-for-days-launch').attr("ng-disabled", 'prompt_for_days_form.$invalid');
e = angular.element(document.getElementById('prompt-for-days-launch'));
$compile(e)(scope);
},
buttons: [{
"label": "Cancel",
"onClick": function() {
$(this).dialog('close');
},
"icon": "fa-times",
"class": "btn btn-default",
"id": "prompt-for-days-cancel"
},{
"label": "Launch",
"onClick": function() {
var extra_vars = {"days": scope.days_to_keep },
data = {};
data.extra_vars = JSON.stringify(extra_vars);
Rest.setUrl(defaultUrl);
Rest.post(data)
.success(function() {
Wait('stop');
$("#prompt-for-days").dialog("close");
$("#configure-tower-dialog").dialog('close');
$location.path('/jobs/');
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed updating job ' + scope.job_template_id + ' with variables. POST returned: ' + status });
});
},
"icon": "fa-rocket",
"class": "btn btn-primary",
"id": "prompt-for-days-launch"
}]
});
if (scope.removePromptForDays) {
scope.removePromptForDays();
}
scope.removePromptForDays = scope.$on('PromptForDays', function() {
// $('#configure-tower-dialog').dialog('close');
$('#prompt-for-days').show();
$('#prompt-for-days').dialog('open');
Wait('stop');
});
};
scope.configureSchedule = function(id, name) {
Rest.setUrl(scheduleUrl+id+'/schedules/');
Rest.get()
.success(function(data) {
if(data.count>0){
scope.days=data.results[0].extra_data.days;
ConfigureTowerSchedule({
scope: scope,
mode: 'edit',
url: scheduleUrl+id+'/schedules/'
});
} else {
ConfigureTowerSchedule({
scope: scope,
mode: 'add',
url: scheduleUrl+id+'/schedules/',
name: name
});
}
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed getting schedule information' });
});
};
parent_scope.refreshJobs = function(){
scope.search(SchedulesList.iterator);
};
};
}])
.factory('ConfigureTowerSchedule', ['$compile','SchedulerInit', 'Rest', 'Wait', 'SetSchedulesInnerDialogSize', 'SchedulePost', 'ProcessErrors', 'GetBasePath', 'Empty', 'Prompt',
function($compile, SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize, SchedulePost, ProcessErrors, GetBasePath, Empty, Prompt) {
return function(params) {
var parent_scope = params.scope,
mode = params.mode, // 'add' or 'edit'
url = params.url,
scope = parent_scope.$new(),
id = params.id || undefined,
name = params.name || undefined,
schedule = {},
scheduler,
target,
showForm,
list,
detail,
restoreList,
container,
elem;
Wait('start');
// $('#configure-jobs').hide();
detail = $('#configure-schedules-detail').hide();
list = $('#configure-schedules-list');
target = $('#configure-schedules-form');
container = $('#configure-schedules-form-container');
$("#configure-jobs").show();
$("#configure-schedules-form-container").hide();
scope.mode = mode;
// Clean up any lingering stuff
container.hide();
target.empty();
$('.tooltip').each(function () {
$(this).remove();
});
$('.popover').each(function () {
$(this).remove();
});
$("#configure-cancel-button").after('<button type="button" class="btn btn-primary btn-sm" id="configure-save-button" ng-click="saveScheduleForm()" style="margin-left:5px"><i class="fa fa-check"></i> Save</button>');
elem = angular.element(document.getElementById('configure-schedules-form-container'));
$compile(elem)(scope);
if (scope.removeScheduleReady) {
scope.removeScheduleReady();
}
scope.removeScheduleReady = scope.$on('ScheduleReady', function() {
// Insert the scheduler widget into the hidden div
scheduler = SchedulerInit({ scope: scope, requireFutureStartTime: false });
scheduler.inject('configure-schedules-form', false);
scheduler.injectDetail('configure-schedules-detail', false);
scheduler.clear();
scope.formShowing = true;
scope.showRRuleDetail = false;
scope.schedulesTitle = (mode === 'edit') ? 'Edit Schedule' : 'Create Schedule';
// display the scheduler widget
showForm = function() {
$('#configure-jobs').show('slide', { direction: 'left' }, 500);
$('#configure-jobs').hide();
Wait('stop');
$('#configure-schedules-overlay').width($('#configure-schedules-tab')
.width()).height($('#configure-schedules-tab').height()).show();
container.width($('#configure-schedules-tab').width() - 18);
SetSchedulesInnerDialogSize();
container.show('slide', { direction: 'right' }, 300);
// scope.schedulerPurgeDays = (!Empty(scope.days)) ? Number(scope.days) : 30;
target.show();
if(mode==="add"){
scope.$apply(function(){
scope.schedulerPurgeDays = 30;
scope.schedulerName = name+' Schedule';
});
}
if (mode === 'edit') {
scope.$apply(function() {
scheduler.setRRule(schedule.rrule);
scheduler.setName(schedule.name);
scope.schedulerPurgeDays = (!Empty(scope.days)) ? Number(scope.days) : 30;
});
}
};
setTimeout(function() { showForm(); }, 1000);
});
restoreList = function() {
// $('#group-save-button').prop('disabled', false);
$('#configure-jobs').show('slide', { direction: 'right' }, 500);
// $('#configure-jobs').width($('#configure-jobs').width()).height($('#configure-jobs').height()).hide();
// parent_scope.refreshSchedules();
list.show('slide', { direction: 'right' }, 500);
$('#configure-schedules-overlay').width($('#configure-schedules-tab').width()).height($('#configure-schedules-tab').height()).hide();
parent_scope.refreshSchedules();
}; };
scope.configureSchedule = function(id, name) { scope.showScheduleDetail = function() {
Rest.setUrl(scheduleUrl+id+'/schedules/'); if (scope.formShowing) {
if (scheduler.isValid()) {
detail.width($('#configure-schedules-form').width()).height($('#configure-schedules-form').height());
target.hide();
detail.show();
scope.formShowing = false;
}
}
else {
detail.hide();
target.show();
scope.formShowing = true;
}
};
if (scope.removeScheduleSaved) {
scope.removeScheduleSaved();
}
scope.removeScheduleSaved = scope.$on('ScheduleSaved', function() {
Wait('stop');
$("#configure-save-button").remove();
container.hide('slide', { direction: 'left' }, 500, restoreList);
scope.$destroy();
});
scope.saveScheduleForm = function() {
var extra_vars;
if (scheduler.isValid()) {
scope.schedulerIsValid = true;
url = (mode==="edit") ? GetBasePath('schedules')+id+'/' : url;
extra_vars = {
"days" : scope.scheduler_form.schedulerPurgeDays.$viewValue
};
schedule.extra_data = JSON.stringify(extra_vars);
SchedulePost({
scope: scope,
url: url,
scheduler: scheduler,
callback: 'ScheduleSaved',
mode: mode,
schedule: schedule
});
}
else {
scope.schedulerIsValid = false;
}
};
scope.deleteSystemSchedule = function(){
var hdr = 'Delete Schedule',
action = function () {
Wait('start');
Rest.setUrl(schedule.url);
Rest.destroy()
.success(function () {
$('#prompt-modal').modal('hide');
Wait('stop');
// scope.$emit(callback, id);
scope.cancelScheduleForm();
})
.error(function (data, status) {
try {
$('#prompt-modal').modal('hide');
}
catch(e) {
// ignore
}
ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url +
' failed. DELETE returned: ' + status });
});
};
Prompt({
hdr: hdr,
body: "<div class=\"alert alert-info\">Are you sure you want to delete the <em>" + scope.schedulerName + "</em> schedule?</div>",
action: action,
backdrop: false
});
// }
// } else {
// //a schedule doesn't exist
// $("#prompt_action_btn").text('OK');
// $('#prompt_cancel_btn').hide();
// var action2 = function(){
// $('#prompt-modal').modal('hide');
// $("#prompt_action_btn").text('Yes');
// $('#prompt_cancel_btn').show();
// };
// Prompt({
// hdr: "Delete",
// body: "<div class=\"alert alert-info\">No schedule exists for that job. </div>",
// action: action2,
// backdrop: false
// });
// }
// })
// .error(function(data, status) {
// ProcessErrors(scope, data, status, null, { hdr: 'Error!',
// msg: 'Failed updating job ' + scope.job_template_id + ' with variables. PUT returned: ' + status });
// });
};
scope.cancelScheduleForm = function() {
container.hide('slide', { direction: 'right' }, 500, restoreList);
$("#configure-save-button").remove();
scope.$destroy();
};
if (mode === 'edit') {
// Get the existing record
Rest.setUrl(url); //GetBasePath('schedules')+id+'/');
Rest.get() Rest.get()
.success(function(data) { .success(function(data) {
if(data.count>0){ schedule = data.results[0];
scope.days=data.results[0].extra_data.days; id = schedule.id;
ConfigureTowerSchedule({ if (!/DTSTART/.test(schedule.rrule)) {
scope: scope, schedule.rrule += ";DTSTART=" + schedule.dtstart.replace(/\.\d+Z$/,'Z');
mode: 'edit',
url: scheduleUrl+id+'/schedules/'
});
} else {
ConfigureTowerSchedule({
scope: scope,
mode: 'add',
url: scheduleUrl+id+'/schedules/',
name: name
});
} }
schedule.rrule = schedule.rrule.replace(/ RRULE:/,';');
schedule.rrule = schedule.rrule.replace(/DTSTART:/,'DTSTART=');
scope.$emit('ScheduleReady');
}) })
.error(function(data, status) { .error(function(data,status){
ProcessErrors(scope, data, status, null, { hdr: 'Error!', ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed getting schedule information' }); msg: 'Failed to get: ' + url + ' GET returned: ' + status });
}); });
};
parent_scope.refreshJobs = function(){
scope.search(SchedulesList.iterator);
};
};
}])
.factory('ConfigureTowerSchedule', ['$compile','SchedulerInit', 'Rest', 'Wait', 'SetSchedulesInnerDialogSize', 'SchedulePost', 'ProcessErrors', 'GetBasePath', 'Empty', 'Prompt',
function($compile, SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize, SchedulePost, ProcessErrors, GetBasePath, Empty, Prompt) {
return function(params) {
var parent_scope = params.scope,
mode = params.mode, // 'add' or 'edit'
url = params.url,
scope = parent_scope.$new(),
id = params.id || undefined,
name = params.name || undefined,
schedule = {},
scheduler,
target,
showForm,
list,
detail,
restoreList,
container,
elem;
Wait('start');
// $('#configure-jobs').hide();
detail = $('#configure-schedules-detail').hide();
list = $('#configure-schedules-list');
target = $('#configure-schedules-form');
container = $('#configure-schedules-form-container');
$("#configure-jobs").show();
$("#configure-schedules-form-container").hide();
scope.mode = mode;
// Clean up any lingering stuff
container.hide();
target.empty();
$('.tooltip').each(function () {
$(this).remove();
});
$('.popover').each(function () {
$(this).remove();
});
$("#configure-cancel-button").after('<button type="button" class="btn btn-primary btn-sm" id="configure-save-button" ng-click="saveScheduleForm()" style="margin-left:5px"><i class="fa fa-check"></i> Save</button>');
elem = angular.element(document.getElementById('configure-schedules-form-container'));
$compile(elem)(scope);
if (scope.removeScheduleReady) {
scope.removeScheduleReady();
}
scope.removeScheduleReady = scope.$on('ScheduleReady', function() {
// Insert the scheduler widget into the hidden div
scheduler = SchedulerInit({ scope: scope, requireFutureStartTime: false });
scheduler.inject('configure-schedules-form', false);
scheduler.injectDetail('configure-schedules-detail', false);
scheduler.clear();
scope.formShowing = true;
scope.showRRuleDetail = false;
scope.schedulesTitle = (mode === 'edit') ? 'Edit Schedule' : 'Create Schedule';
// display the scheduler widget
showForm = function() {
$('#configure-jobs').show('slide', { direction: 'left' }, 500);
$('#configure-jobs').hide();
Wait('stop');
$('#configure-schedules-overlay').width($('#configure-schedules-tab')
.width()).height($('#configure-schedules-tab').height()).show();
container.width($('#configure-schedules-tab').width() - 18);
SetSchedulesInnerDialogSize();
container.show('slide', { direction: 'right' }, 300);
// scope.schedulerPurgeDays = (!Empty(scope.days)) ? Number(scope.days) : 30;
target.show();
if(mode==="add"){
scope.$apply(function(){
scope.schedulerPurgeDays = 30;
scope.schedulerName = name+' Schedule';
});
}
if (mode === 'edit') {
scope.$apply(function() {
scheduler.setRRule(schedule.rrule);
scheduler.setName(schedule.name);
scope.schedulerPurgeDays = (!Empty(scope.days)) ? Number(scope.days) : 30;
});
}
};
setTimeout(function() { showForm(); }, 1000);
});
restoreList = function() {
// $('#group-save-button').prop('disabled', false);
$('#configure-jobs').show('slide', { direction: 'right' }, 500);
// $('#configure-jobs').width($('#configure-jobs').width()).height($('#configure-jobs').height()).hide();
// parent_scope.refreshSchedules();
list.show('slide', { direction: 'right' }, 500);
$('#configure-schedules-overlay').width($('#configure-schedules-tab').width()).height($('#configure-schedules-tab').height()).hide();
parent_scope.refreshSchedules();
};
scope.showScheduleDetail = function() {
if (scope.formShowing) {
if (scheduler.isValid()) {
detail.width($('#configure-schedules-form').width()).height($('#configure-schedules-form').height());
target.hide();
detail.show();
scope.formShowing = false;
}
} }
else { else {
detail.hide(); scope.$emit('ScheduleReady');
target.show();
scope.formShowing = true;
} }
}; };
}]);
if (scope.removeScheduleSaved) {
scope.removeScheduleSaved();
}
scope.removeScheduleSaved = scope.$on('ScheduleSaved', function() {
Wait('stop');
$("#configure-save-button").remove();
container.hide('slide', { direction: 'left' }, 500, restoreList);
scope.$destroy();
});
scope.saveScheduleForm = function() {
var extra_vars;
if (scheduler.isValid()) {
scope.schedulerIsValid = true;
url = (mode==="edit") ? GetBasePath('schedules')+id+'/' : url;
extra_vars = {
"days" : scope.scheduler_form.schedulerPurgeDays.$viewValue
};
schedule.extra_data = JSON.stringify(extra_vars);
SchedulePost({
scope: scope,
url: url,
scheduler: scheduler,
callback: 'ScheduleSaved',
mode: mode,
schedule: schedule
});
}
else {
scope.schedulerIsValid = false;
}
};
scope.deleteSystemSchedule = function(){
var hdr = 'Delete Schedule',
action = function () {
Wait('start');
Rest.setUrl(schedule.url);
Rest.destroy()
.success(function () {
$('#prompt-modal').modal('hide');
Wait('stop');
// scope.$emit(callback, id);
scope.cancelScheduleForm();
})
.error(function (data, status) {
try {
$('#prompt-modal').modal('hide');
}
catch(e) {
// ignore
}
ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url +
' failed. DELETE returned: ' + status });
});
};
Prompt({
hdr: hdr,
body: "<div class=\"alert alert-info\">Are you sure you want to delete the <em>" + scope.schedulerName + "</em> schedule?</div>",
action: action,
backdrop: false
});
// }
// } else {
// //a schedule doesn't exist
// $("#prompt_action_btn").text('OK');
// $('#prompt_cancel_btn').hide();
// var action2 = function(){
// $('#prompt-modal').modal('hide');
// $("#prompt_action_btn").text('Yes');
// $('#prompt_cancel_btn').show();
// };
// Prompt({
// hdr: "Delete",
// body: "<div class=\"alert alert-info\">No schedule exists for that job. </div>",
// action: action2,
// backdrop: false
// });
// }
// })
// .error(function(data, status) {
// ProcessErrors(scope, data, status, null, { hdr: 'Error!',
// msg: 'Failed updating job ' + scope.job_template_id + ' with variables. PUT returned: ' + status });
// });
};
scope.cancelScheduleForm = function() {
container.hide('slide', { direction: 'right' }, 500, restoreList);
$("#configure-save-button").remove();
scope.$destroy();
};
if (mode === 'edit') {
// Get the existing record
Rest.setUrl(url); //GetBasePath('schedules')+id+'/');
Rest.get()
.success(function(data) {
schedule = data.results[0];
id = schedule.id;
if (!/DTSTART/.test(schedule.rrule)) {
schedule.rrule += ";DTSTART=" + schedule.dtstart.replace(/\.\d+Z$/,'Z');
}
schedule.rrule = schedule.rrule.replace(/ RRULE:/,';');
schedule.rrule = schedule.rrule.replace(/DTSTART:/,'DTSTART=');
scope.$emit('ScheduleReady');
})
.error(function(data,status){
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to get: ' + url + ' GET returned: ' + status });
});
}
else {
scope.$emit('ScheduleReady');
}
};
}]);

View File

@@ -5,263 +5,287 @@
* *
* *
*/ */
/** /**
* @ngdoc function * @ngdoc function
* @name helpers.function:Credentials * @name helpers.function:Credentials
* @description Functions shared amongst Credential related controllers * @description Functions shared amongst Credential related controllers
*/ */
'use strict';
export default
angular.module('CredentialsHelper', ['Utilities']) angular.module('CredentialsHelper', ['Utilities'])
.factory('KindChange', ['Empty', .factory('KindChange', ['Empty',
function (Empty) { function (Empty) {
return function (params) { return function (params) {
var scope = params.scope, var scope = params.scope,
reset = params.reset, reset = params.reset,
collapse, id; collapse, id;
$('.popover').each(function() { $('.popover').each(function() {
// remove lingering popover <div>. Seems to be a bug in TB3 RC1 // remove lingering popover <div>. Seems to be a bug in TB3 RC1
$(this).remove(); $(this).remove();
}); });
$('.tooltip').each( function() { $('.tooltip').each( function() {
// close any lingering tool tipss // close any lingering tool tipss
$(this).hide(); $(this).hide();
}); });
// Put things in a default state // Put things in a default state
scope.usernameLabel = 'Username'; scope.usernameLabel = 'Username';
scope.aws_required = false; scope.aws_required = false;
scope.email_required = false; scope.email_required = false;
scope.rackspace_required = false; scope.rackspace_required = false;
scope.sshKeyDataLabel = 'SSH Private Key'; scope.sshKeyDataLabel = 'SSH Private Key';
scope.username_required = false; // JT-- added username_required b/c mutliple 'kinds' need username to be required (GCE) scope.username_required = false; // JT-- added username_required b/c mutliple 'kinds' need username to be required (GCE)
scope.key_required = false; // JT -- doing the same for key and project scope.key_required = false; // JT -- doing the same for key and project
scope.project_required = false; scope.project_required = false;
scope.subscription_required = false; scope.subscription_required = false;
scope.key_description = "Paste the contents of the SSH private key file."; scope.key_description = "Paste the contents of the SSH private key file.<div class=\"popover-footer\"><span class=\"key\">esc</span> or click to close</div>";
scope.key_hint= "drag and drop an SSH private key file on the field below"; scope.key_hint= "drag and drop an SSH private key file on the field below";
scope.host_required = false; scope.host_required = false;
scope.password_required = false; scope.password_required = false;
scope.hostLabel = ''; scope.hostLabel = '';
if (!Empty(scope.kind)) { $('.popover').each(function() {
// Apply kind specific settings // remove lingering popover <div>. Seems to be a bug in TB3 RC1
switch (scope.kind.value) { $(this).remove();
case 'aws': });
scope.aws_required = true; $('.tooltip').each( function() {
break; // close any lingering tool tipss
case 'rax': $(this).hide();
scope.rackspace_required = true; });
scope.username_required = true; // Put things in a default state
break; scope.usernameLabel = 'Username';
case 'ssh': scope.aws_required = false;
scope.usernameLabel = 'Username'; //formally 'SSH Username' scope.email_required = false;
break; scope.rackspace_required = false;
case 'scm': scope.sshKeyDataLabel = 'SSH Private Key';
scope.sshKeyDataLabel = 'SCM Private Key'; scope.username_required = false; // JT-- added username_required b/c mutliple 'kinds' need username to be required (GCE)
break; scope.key_required = false; // JT -- doing the same for key and project
case 'gce': scope.project_required = false;
scope.usernameLabel = 'Service Account Email Address'; scope.subscription_required = false;
scope.sshKeyDataLabel = 'RSA Private Key'; scope.key_description = "Paste the contents of the SSH private key file.";
scope.email_required = true; scope.key_hint= "drag and drop an SSH private key file on the field below";
scope.key_required = true; scope.host_required = false;
scope.project_required = true; scope.password_required = false;
scope.key_description = 'Paste the contents of the PEM file associated with the service account email.'; scope.hostLabel = '';
scope.key_hint= "drag and drop a private key file on the field below";
break;
case 'azure':
scope.usernameLabel = "Subscription ID";
scope.sshKeyDataLabel = 'Management Certificate';
scope.subscription_required = true;
scope.key_required = true;
scope.key_description = "Paste the contents of the PEM file that corresponds to the certificate you uploaded in the Microsoft Azure console.";
scope.key_hint= "drag and drop a management certificate file on the field below";
break;
case 'vmware':
scope.username_required = true;
scope.host_required = true;
scope.password_required = true;
scope.hostLabel = "vCenter Host";
break;
}
}
// Reset all the field values related to Kind. if (!Empty(scope.kind)) {
if (reset) { // Apply kind specific settings
scope.access_key = null; switch (scope.kind.value) {
scope.secret_key = null; case 'aws':
scope.api_key = null; scope.aws_required = true;
scope.username = null; break;
scope.password = null; case 'rax':
scope.password_confirm = null; scope.rackspace_required = true;
scope.ssh_key_data = null; scope.username_required = true;
scope.ssh_key_unlock = null; break;
scope.ssh_key_unlock_confirm = null; case 'ssh':
scope.sudo_username = null; scope.usernameLabel = 'Username'; //formally 'SSH Username'
scope.sudo_password = null; break;
scope.sudo_password_confirm = null; case 'scm':
scope.su_username = null; scope.sshKeyDataLabel = 'SCM Private Key';
scope.su_password = null; break;
scope.su_password_confirm = null; case 'gce':
} scope.usernameLabel = 'Service Account Email Address';
scope.sshKeyDataLabel = 'RSA Private Key';
scope.email_required = true;
scope.key_required = true;
scope.project_required = true;
scope.key_description = 'Paste the contents of the PEM file associated with the service account email.';
scope.key_hint= "drag and drop a private key file on the field below";
break;
case 'azure':
scope.usernameLabel = "Subscription ID";
scope.sshKeyDataLabel = 'Management Certificate';
scope.subscription_required = true;
scope.key_required = true;
scope.key_description = "Paste the contents of the PEM file that corresponds to the certificate you uploaded in the Microsoft Azure console.";
scope.key_hint= "drag and drop a management certificate file on the field below";
break;
case 'vmware':
scope.username_required = true;
scope.host_required = true;
scope.password_required = true;
scope.hostLabel = "vCenter Host";
break;
}
}
// Collapse or open help widget based on whether scm value is selected // Reset all the field values related to Kind.
collapse = $('#credential_kind').parent().find('.panel-collapse').first(); if (reset) {
id = collapse.attr('id'); scope.access_key = null;
if (!Empty(scope.kind) && scope.kind.value !== '') { scope.secret_key = null;
if ($('#' + id + '-icon').hasClass('icon-minus')) { scope.api_key = null;
scope.accordionToggle('#' + id); scope.username = null;
} scope.password = null;
} else { scope.password_confirm = null;
if ($('#' + id + '-icon').hasClass('icon-plus')) { scope.ssh_key_data = null;
scope.accordionToggle('#' + id); scope.ssh_key_unlock = null;
} scope.ssh_key_unlock_confirm = null;
} scope.sudo_username = null;
scope.sudo_password = null;
scope.sudo_password_confirm = null;
scope.su_username = null;
scope.su_password = null;
scope.su_password_confirm = null;
}
}; // 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', [ .factory('OwnerChange', [
function () { function () {
return function (params) { return function (params) {
var scope = params.scope, var scope = params.scope,
owner = scope.owner; owner = scope.owner;
if (owner === 'team') { if (owner === 'team') {
scope.team_required = true; scope.team_required = true;
scope.user_required = false; scope.user_required = false;
scope.user = null; scope.user = null;
scope.user_username = null; scope.user_username = null;
} else { } else {
scope.team_required = false; scope.team_required = false;
scope.user_required = true; scope.user_required = true;
scope.team = null; scope.team = null;
scope.team_name = null; scope.team_name = null;
} }
}; };
} }
]) ])
.factory('LoginMethodChange', [ .factory('LoginMethodChange', [
function () { function () {
return function (params) { return function (params) {
var scope = params.scope, var scope = params.scope,
login_method = scope.login_method; login_method = scope.login_method;
if (login_method !== 'sudo') { if (login_method !== 'sudo') {
scope.sudo_username = null; scope.sudo_username = null;
scope.sudo_password = null; scope.sudo_password = null;
} }
if (login_method !== 'su') { if (login_method !== 'su') {
scope.su_username = null; scope.su_username = null;
scope.su_password = null; scope.su_password = null;
} }
}; };
} }
]) ])
.factory('FormSave', ['$location', 'Alert', 'Rest', 'ProcessErrors', 'Empty', 'GetBasePath', 'CredentialForm', 'ReturnToCaller', 'Wait', .factory('FormSave', ['$location', 'Alert', 'Rest', 'ProcessErrors', 'Empty', 'GetBasePath', 'CredentialForm', 'ReturnToCaller', 'Wait',
function ($location, Alert, Rest, ProcessErrors, Empty, GetBasePath, CredentialForm, ReturnToCaller, Wait) { function ($location, Alert, Rest, ProcessErrors, Empty, GetBasePath, CredentialForm, ReturnToCaller, Wait) {
return function (params) { return function (params) {
var scope = params.scope, var scope = params.scope,
mode = params.mode, mode = params.mode,
form = CredentialForm, form = CredentialForm,
data = {}, fld, url; data = {}, fld, url;
for (fld in form.fields) { for (fld in form.fields) {
if (fld !== 'access_key' && fld !== 'secret_key' && fld !== 'ssh_username' && if (fld !== 'access_key' && fld !== 'secret_key' && fld !== 'ssh_username' &&
fld !== 'ssh_password') { fld !== 'ssh_password') {
if (scope[fld] === null) { if (scope[fld] === null) {
data[fld] = ""; data[fld] = "";
} else { } else {
data[fld] = scope[fld]; data[fld] = scope[fld];
} }
} }
} }
if (!Empty(scope.team)) { if (!Empty(scope.team)) {
data.team = scope.team; data.team = scope.team;
data.user = ""; data.user = "";
} else { } else {
data.user = scope.user; data.user = scope.user;
data.team = ""; data.team = "";
} }
data.kind = scope.kind.value; data.kind = scope.kind.value;
switch (data.kind) { switch (data.kind) {
case 'ssh': case 'ssh':
data.password = scope.ssh_password; data.password = scope.ssh_password;
break; break;
case 'aws': case 'aws':
data.username = scope.access_key; data.username = scope.access_key;
data.password = scope.secret_key; data.password = scope.secret_key;
break; break;
case 'rax': case 'rax':
data.password = scope.api_key; data.password = scope.api_key;
break; break;
case 'gce': case 'gce':
data.username = scope.email_address; data.username = scope.email_address;
data.project = scope.project; data.project = scope.project;
break; break;
case 'azure': case 'azure':
data.username = scope.subscription_id; data.username = scope.subscription_id;
} }
if (Empty(data.team) && Empty(data.user)) { 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 ' + 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'); 'user, select a User. To allow a team of users to access this credential, select a Team.', 'alert-danger');
} else { } else {
Wait('start'); Wait('start');
if (mode === 'add') { if (mode === 'add') {
url = (!Empty(data.team)) ? GetBasePath('teams') + data.team + '/credentials/' : url = (!Empty(data.team)) ? GetBasePath('teams') + data.team + '/credentials/' :
GetBasePath('users') + data.user + '/credentials/'; GetBasePath('users') + data.user + '/credentials/';
Rest.setUrl(url); Rest.setUrl(url);
Rest.post(data) Rest.post(data)
.success(function () { .success(function () {
Wait('stop'); Wait('stop');
var base = $location.path().replace(/^\//, '').split('/')[0]; var base = $location.path().replace(/^\//, '').split('/')[0];
if (base === 'credentials') { if (base === 'credentials') {
ReturnToCaller(); ReturnToCaller();
} }
else { else {
ReturnToCaller(1); ReturnToCaller(1);
} }
}) })
.error(function (data, status) { .error(function (data, status) {
Wait('stop'); Wait('stop');
ProcessErrors(scope, data, status, form, { ProcessErrors(scope, data, status, form, {
hdr: 'Error!', hdr: 'Error!',
msg: 'Failed to create new Credential. POST status: ' + status msg: 'Failed to create new Credential. POST status: ' + status
}); });
}); });
} else { } else {
url = GetBasePath('credentials') + scope.id + '/'; url = GetBasePath('credentials') + scope.id + '/';
Rest.setUrl(url); Rest.setUrl(url);
Rest.put(data) Rest.put(data)
.success(function () { .success(function () {
Wait('stop'); Wait('stop');
var base = $location.path().replace(/^\//, '').split('/')[0]; var base = $location.path().replace(/^\//, '').split('/')[0];
if (base === 'credentials') { if (base === 'credentials') {
ReturnToCaller(); ReturnToCaller();
} }
else { else {
ReturnToCaller(1); ReturnToCaller(1);
} }
}) })
.error(function (data, status) { .error(function (data, status) {
Wait('stop'); Wait('stop');
ProcessErrors(scope, data, status, form, { ProcessErrors(scope, data, status, form, {
hdr: 'Error!', hdr: 'Error!',
msg: 'Failed to update Credential. PUT status: ' + status msg: 'Failed to update Credential. PUT status: ' + status
}); });
}); });
} }
} }
}; };
} }
]); ]);

View File

@@ -11,347 +11,347 @@
* *
*/ */
'use strict';
angular.module('CreateCustomInventoryHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ModalDialog', export default
'GeneratorHelpers', 'CustomInventoryFormDefinition']) angular.module('CreateCustomInventoryHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ModalDialog',
'GeneratorHelpers', 'CustomInventoryFormDefinition'])
.factory('CreateCustomInventory', ['Wait', 'CreateDialog', 'CustomInventoryList', 'GenerateList', 'GetBasePath' , 'SearchInit' , 'PaginateInit', 'PlaybookRun', 'CustomInventoryAdd', .factory('CreateCustomInventory', ['Wait', 'CreateDialog', 'CustomInventoryList', 'GenerateList', 'GetBasePath' , 'SearchInit' , 'PaginateInit', 'PlaybookRun', 'CustomInventoryAdd',
'SchedulesList', 'CustomInventoryEdit', 'Rest' , 'ProcessErrors', 'CustomInventoryForm', 'GenerateForm', 'Prompt', 'SchedulesList', 'CustomInventoryEdit', 'Rest' , 'ProcessErrors', 'CustomInventoryForm', 'GenerateForm', 'Prompt',
function(Wait, CreateDialog, CustomInventoryList, GenerateList, GetBasePath, SearchInit, PaginateInit, PlaybookRun, CustomInventoryAdd, function(Wait, CreateDialog, CustomInventoryList, GenerateList, GetBasePath, SearchInit, PaginateInit, PlaybookRun, CustomInventoryAdd,
SchedulesList, CustomInventoryEdit, Rest, ProcessErrors, CustomInventoryForm, GenerateForm, Prompt) { SchedulesList, CustomInventoryEdit, Rest, ProcessErrors, CustomInventoryForm, GenerateForm, Prompt) {
return function(params) { return function(params) {
// Set modal dimensions based on viewport width // Set modal dimensions based on viewport width
var scope = params.parent_scope.$new(), var scope = params.parent_scope.$new(),
callback = 'OpenConfig', callback = 'OpenConfig',
defaultUrl = GetBasePath('inventory_scripts'), defaultUrl = GetBasePath('inventory_scripts'),
list = CustomInventoryList, list = CustomInventoryList,
view = GenerateList, view = GenerateList,
buttons = [ buttons = [
{ {
"label": "Close", "label": "Close",
"onClick": function() { "onClick": function() {
// $(this).dialog('close'); // $(this).dialog('close');
scope.cancelConfigure();
},
"icon": "fa-times",
"class": "btn btn-default",
"id": "script-close-button"
}
];
scope.cleanupJob = true;
if(scope.removeOpenConfig) {
scope.removeOpenConfig();
}
scope.removeOpenConfig = scope.$on('OpenConfig', function() {
$('#custom-script-dialog').dialog('open');
$('#script-close-button').focus();
$('#script-close-button').blur();
});
view.inject( list, {
id : 'custom-script-dialog',
mode: 'edit',
scope: scope,
breadCrumbs: false,
activityStream: false,
showSearch: true
});
SearchInit({
scope: scope,
set: 'source_scripts' , // 'custom_inventories',
list: list,
url: defaultUrl
});
PaginateInit({
scope: scope,
list: list,
url: defaultUrl
});
scope.search(list.iterator);
// SchedulesControllerInit({
// scope: scope,
// parent_scope: parent_scope,
// // list: list
// });
CreateDialog({
id: 'custom-script-dialog',
title: 'Inventory Scripts',
target: 'custom-script-dialog',
scope: scope,
buttons: buttons,
width: 700,
height: 800,
minWidth: 400,
callback: callback,
onClose: function () {
// Destroy on close
$('.tooltip').each(function () {
// Remove any lingering tooltip <div> elements
$(this).remove();
});
$('.popover').each(function () {
// remove lingering popover <div> elements
$(this).remove();
});
// $("#configure-jobs").show();
// $("#configure-schedules-form-container").hide();
// $('#configure-schedules-list').empty();
// $('#configure-schedules-form').empty();
// $('#configure-schedules-detail').empty();
// $('#configure-tower-dialog').hide();
$(this).dialog('destroy');
scope.cancelConfigure(); scope.cancelConfigure();
}, },
"icon": "fa-times",
"class": "btn btn-default",
"id": "script-close-button"
}
];
scope.cleanupJob = true;
if(scope.removeOpenConfig) {
scope.removeOpenConfig();
}
scope.removeOpenConfig = scope.$on('OpenConfig', function() {
$('#custom-script-dialog').dialog('open');
$('#script-close-button').focus();
$('#script-close-button').blur();
});
view.inject( list, {
id : 'custom-script-dialog',
mode: 'edit',
scope: scope,
breadCrumbs: false,
activityStream: false,
showSearch: true
});
SearchInit({
scope: scope,
set: 'source_scripts' , // 'custom_inventories',
list: list,
url: defaultUrl
});
PaginateInit({
scope: scope,
list: list,
url: defaultUrl
});
scope.search(list.iterator);
// SchedulesControllerInit({
// scope: scope,
// parent_scope: parent_scope,
// // list: list
// });
CreateDialog({
id: 'custom-script-dialog',
title: 'Inventory Scripts',
target: 'custom-script-dialog',
scope: scope,
buttons: buttons,
width: 700,
height: 800,
minWidth: 400,
callback: callback,
onClose: function () {
// Destroy on close
$('.tooltip').each(function () {
// Remove any lingering tooltip <div> elements
$(this).remove();
});
$('.popover').each(function () {
// remove lingering popover <div> elements
$(this).remove();
});
// $("#configure-jobs").show();
// $("#configure-schedules-form-container").hide();
// $('#configure-schedules-list').empty();
// $('#configure-schedules-form').empty();
// $('#configure-schedules-detail').empty();
// $('#configure-tower-dialog').hide();
$(this).dialog('destroy');
scope.cancelConfigure();
},
});
// Cancel
scope.cancelConfigure = function () {
try {
$('#custom-script-dialog').dialog('close');
}
catch(e) {
//ignore
}
if (scope.searchCleanup) {
scope.searchCleanup();
}
// if (!Empty(parent_scope) && parent_scope.restoreSearch) {
// parent_scope.restoreSearch();
// }
else {
Wait('stop');
}
};
scope.editCustomInv = function(id){
CustomInventoryEdit({
scope: scope,
id: id
}); });
};
scope.deleteCustomInv = function(id, name){
var action = function () {
$('#prompt-modal').modal('hide');
Wait('start'); // Cancel
var url = defaultUrl + id + '/'; scope.cancelConfigure = function () {
Rest.setUrl(url); try {
Rest.destroy() $('#custom-script-dialog').dialog('close');
.success(function () { }
scope.search(list.iterator); catch(e) {
}) //ignore
.error(function (data, status) { }
ProcessErrors(scope, data, status, null, { hdr: 'Error!', if (scope.searchCleanup) {
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); scope.searchCleanup();
}); }
// if (!Empty(parent_scope) && parent_scope.restoreSearch) {
// parent_scope.restoreSearch();
// }
else {
Wait('stop');
}
}; };
Prompt({ scope.editCustomInv = function(id){
hdr: 'Delete', CustomInventoryEdit({
body: "<div class\"alert alert-info\">Are you sure you want to delete " + name + "?</div>", scope: scope,
action: action id: id
});
};
scope.deleteCustomInv = function(id, name){
var action = function () {
$('#prompt-modal').modal('hide');
Wait('start');
var url = defaultUrl + id + '/';
Rest.setUrl(url);
Rest.destroy()
.success(function () {
scope.search(list.iterator);
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
};
Prompt({
hdr: 'Delete',
body: "<div class\"alert alert-info\">Are you sure you want to delete " + name + "?</div>",
action: action
});
};
scope.addCustomInv = function(){
CustomInventoryAdd({
scope: scope
});
};
};
}])
.factory('CustomInventoryAdd', ['$compile','SchedulerInit', 'Rest', 'Wait', 'CustomInventoryList', 'CustomInventoryForm', 'ProcessErrors', 'GetBasePath', 'Empty', 'GenerateForm',
'SearchInit' , 'PaginateInit', 'GenerateList', 'LookUpInit', 'OrganizationList',
function($compile, SchedulerInit, Rest, Wait, CustomInventoryList, CustomInventoryForm, ProcessErrors, GetBasePath, Empty, GenerateForm,
SearchInit, PaginateInit, GenerateList, LookUpInit, OrganizationList) {
return function(params) {
var scope = params.scope,
generator = GenerateForm,
form = CustomInventoryForm,
view = GenerateList,
list = CustomInventoryList,
url = GetBasePath('inventory_scripts');
generator.inject(form, { id:'custom-script-dialog', mode: 'add' , scope:scope, related: false, breadCrumbs: false});
generator.reset();
LookUpInit({
url: GetBasePath('organization'),
scope: scope,
form: form,
// hdr: "Select Custom Inventory",
list: OrganizationList,
field: 'organization',
input_type: 'radio'
}); });
// Save
scope.formSave = function () {
generator.clearApiErrors();
Wait('start');
Rest.setUrl(url);
Rest.post({ name: scope.name, description: scope.description, organization: scope.organization, script: scope.script })
.success(function () {
view.inject( list, {
id : 'custom-script-dialog',
mode: 'edit',
scope: scope,
breadCrumbs: false,
activityStream: false,
showSearch: true
});
SearchInit({
scope: scope,
set: 'source_scripts', //'custom_inventories',
list: list,
url: url
});
PaginateInit({
scope: scope,
list: list,
url: url
});
scope.search(list.iterator);
Wait('stop');
Wait('stop');
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to add new inventory script. POST returned status: ' + status });
});
}; };
scope.addCustomInv = function(){ // Cancel
CustomInventoryAdd({ scope.formReset = function () {
scope: scope generator.reset();
});
}; };
}; };
}]) }])
.factory('CustomInventoryEdit', ['$compile','CustomInventoryList', 'Rest', 'Wait', 'GenerateList', 'CustomInventoryForm', 'ProcessErrors', 'GetBasePath', 'Empty', 'GenerateForm',
'SearchInit', 'PaginateInit', '$routeParams', 'OrganizationList', 'LookUpInit',
function($compile, CustomInventoryList, Rest, Wait, GenerateList, CustomInventoryForm, ProcessErrors, GetBasePath, Empty, GenerateForm,
SearchInit, PaginateInit, $routeParams, OrganizationList, LookUpInit) {
return function(params) {
var scope = params.scope,
id = params.id,
generator = GenerateForm,
form = CustomInventoryForm,
view = GenerateList,
list = CustomInventoryList,
master = {},
url = GetBasePath('inventory_scripts');
.factory('CustomInventoryAdd', ['$compile','SchedulerInit', 'Rest', 'Wait', 'CustomInventoryList', 'CustomInventoryForm', 'ProcessErrors', 'GetBasePath', 'Empty', 'GenerateForm', generator.inject(form, {
'SearchInit' , 'PaginateInit', 'GenerateList', 'LookUpInit', 'OrganizationList', id:'custom-script-dialog',
function($compile, SchedulerInit, Rest, Wait, CustomInventoryList, CustomInventoryForm, ProcessErrors, GetBasePath, Empty, GenerateForm, mode: 'edit' ,
SearchInit, PaginateInit, GenerateList, LookUpInit, OrganizationList) { scope:scope,
return function(params) { related: false,
var scope = params.scope, breadCrumbs: false,
generator = GenerateForm, activityStream: false
form = CustomInventoryForm, });
view = GenerateList, generator.reset();
list = CustomInventoryList, LookUpInit({
url = GetBasePath('inventory_scripts'); url: GetBasePath('organization'),
scope: scope,
form: form,
// hdr: "Select Custom Inventory",
list: OrganizationList,
field: 'organization',
input_type: 'radio'
});
generator.inject(form, { id:'custom-script-dialog', mode: 'add' , scope:scope, related: false, breadCrumbs: false}); // Retrieve detail record and prepopulate the form
generator.reset();
LookUpInit({
url: GetBasePath('organization'),
scope: scope,
form: form,
// hdr: "Select Custom Inventory",
list: OrganizationList,
field: 'organization',
input_type: 'radio'
});
// Save
scope.formSave = function () {
generator.clearApiErrors();
Wait('start'); Wait('start');
Rest.setUrl(url); Rest.setUrl(url + id+'/');
Rest.post({ name: scope.name, description: scope.description, organization: scope.organization, script: scope.script }) Rest.get()
.success(function () { .success(function (data) {
view.inject( list, { var fld;
id : 'custom-script-dialog', for (fld in form.fields) {
mode: 'edit', if (data[fld]) {
scope: scope, scope[fld] = data[fld];
breadCrumbs: false, master[fld] = data[fld];
activityStream: false, }
showSearch: true
});
SearchInit({ if (form.fields[fld].sourceModel && data.summary_fields &&
scope: scope, data.summary_fields[form.fields[fld].sourceModel]) {
set: 'source_scripts', //'custom_inventories', scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
list: list, data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
url: url master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
}); data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
PaginateInit({ }
scope: scope, }
list: list,
url: url
});
scope.search(list.iterator);
Wait('stop'); Wait('stop');
Wait('stop');
}) })
.error(function (data, status) { .error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!', ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to add new inventory script. POST returned status: ' + status }); msg: 'Failed to retrieve inventory script: ' + $routeParams.id + '. GET status: ' + status });
}); });
};
// Cancel scope.formSave = function () {
scope.formReset = function () { generator.clearApiErrors();
generator.reset(); Wait('start');
}; Rest.setUrl(url+ id+'/');
}; Rest.put({ name: scope.name, description: scope.description, organization: scope.organization, script: scope.script })
}]) .success(function () {
view.inject( list, {
id : 'custom-script-dialog',
mode: 'edit',
scope: scope,
breadCrumbs: false,
activityStream: false,
showSearch: true
});
.factory('CustomInventoryEdit', ['$compile','CustomInventoryList', 'Rest', 'Wait', 'GenerateList', 'CustomInventoryForm', 'ProcessErrors', 'GetBasePath', 'Empty', 'GenerateForm', SearchInit({
'SearchInit', 'PaginateInit', '$routeParams', 'OrganizationList', 'LookUpInit', scope: scope,
function($compile, CustomInventoryList, Rest, Wait, GenerateList, CustomInventoryForm, ProcessErrors, GetBasePath, Empty, GenerateForm, set: 'source_scripts', //'custom_inventories',
SearchInit, PaginateInit, $routeParams, OrganizationList, LookUpInit) { list: list,
return function(params) { url: url
var scope = params.scope, });
id = params.id, PaginateInit({
generator = GenerateForm, scope: scope,
form = CustomInventoryForm, list: list,
view = GenerateList, url: url
list = CustomInventoryList, });
master = {},
url = GetBasePath('inventory_scripts');
generator.inject(form, { scope.search(list.iterator);
id:'custom-script-dialog',
mode: 'edit' ,
scope:scope,
related: false,
breadCrumbs: false,
activityStream: false
});
generator.reset();
LookUpInit({
url: GetBasePath('organization'),
scope: scope,
form: form,
// hdr: "Select Custom Inventory",
list: OrganizationList,
field: 'organization',
input_type: 'radio'
});
// Retrieve detail record and prepopulate the form Wait('stop');
Wait('start');
Rest.setUrl(url + id+'/');
Rest.get()
.success(function (data) {
var fld;
for (fld in form.fields) {
if (data[fld]) {
scope[fld] = data[fld];
master[fld] = data[fld];
}
if (form.fields[fld].sourceModel && data.summary_fields && })
data.summary_fields[form.fields[fld].sourceModel]) { .error(function (data, status) {
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = ProcessErrors(scope, data, status, form, { hdr: 'Error!',
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; msg: 'Failed to add new inventory script. PUT returned status: ' + status });
master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = });
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; };
}
scope.formReset = function () {
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
} }
Wait('stop'); scope.organization_name = master.organization_name;
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to retrieve inventory script: ' + $routeParams.id + '. GET status: ' + status });
});
scope.formSave = function () { };
generator.clearApiErrors();
Wait('start');
Rest.setUrl(url+ id+'/');
Rest.put({ name: scope.name, description: scope.description, organization: scope.organization, script: scope.script })
.success(function () {
view.inject( list, {
id : 'custom-script-dialog',
mode: 'edit',
scope: scope,
breadCrumbs: false,
activityStream: false,
showSearch: true
});
SearchInit({
scope: scope,
set: 'source_scripts', //'custom_inventories',
list: list,
url: url
});
PaginateInit({
scope: scope,
list: list,
url: url
});
scope.search(list.iterator);
Wait('stop');
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to add new inventory script. PUT returned status: ' + status });
});
}; };
}]);
scope.formReset = function () {
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
}
scope.organization_name = master.organization_name;
};
};
}]);

File diff suppressed because it is too large Load Diff

View File

@@ -11,30 +11,54 @@
* @name helpers.function:Events * @name helpers.function:Events
* @description EventView - show the job_events form in a modal dialog * @description EventView - show the job_events form in a modal dialog
*/ */
'use strict';
angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefinition', 'JobEventsFormDefinition']) export default
angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefinition', 'JobEventsFormDefinition'])
.factory('EventView', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm', .factory('EventView', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'JobEventDataForm', 'Empty', 'JobEventsForm', 'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'JobEventDataForm', 'Empty', 'JobEventsForm',
function ($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath, function ($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath,
FormatDate, JobEventDataForm, Empty, JobEventsForm) { FormatDate, JobEventDataForm, Empty, JobEventsForm) {
return function (params) { return function (params) {
var event_id = params.event_id, var event_id = params.event_id,
generator = GenerateForm, generator = GenerateForm,
form = angular.copy(JobEventsForm), form = angular.copy(JobEventsForm),
scope, scope,
defaultUrl = GetBasePath('base') + 'job_events/' + event_id + '/'; defaultUrl = GetBasePath('base') + 'job_events/' + event_id + '/';
// Retrieve detail record and prepopulate the form // Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl); Rest.setUrl(defaultUrl);
Rest.get() Rest.get()
.success(function (data) { .success(function (data) {
var i, n, fld, rows, txt, cDate; var i, n, fld, rows, txt, cDate;
// If event_data is not available, remove fields that depend on it // 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') { 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) { for (fld in form.fields) {
switch (fld) { switch (fld) {
case 'start': case 'start':
@@ -44,196 +68,172 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
case 'stdout': case 'stdout':
case 'stderr': case 'stderr':
case 'msg': 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') {
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': 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
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_name':
case 'module_args': case 'module_args':
case 'rc': if (data.event_data && data.event_data.res) {
delete form.fields[fld]; if (data.event_data.res.invocation === undefined ||
data.event_data.res.invocation[fld] === undefined) {
delete form.fields[fld];
}
}
break; break;
} }
} }
}
if ($.isEmptyObject(data.event_data) || !data.event_data.res || typeof data.event_data.res !== 'string') { // load the form
delete form.fields.traceback; scope = generator.inject(form, {
}
// 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':
case 'msg':
case 'stdout':
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') {
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
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) {
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,
scope = generator.inject(JobEventDataForm, {
mode: 'edit', mode: 'edit',
modal: true, modal: true,
related: false, related: false
modal_selector: '#form-modal2',
modal_body_id: 'form-modal2-body',
modal_title_id: 'formModal2Header'
}); });
generator.reset(); generator.reset();
scope.formModal2Header = data.event_display.replace(/^\u00a0*/g, ''); scope.formModalAction = function () {
scope.event_data = JSON.stringify(data.event_data, null, '\t'); $('#form-modal').modal("hide");
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'); 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, '');
if (typeof data.event_data.res === 'string') { // Respond to View JSON button
scope.traceback = data.event_data.res; 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');
};
for (fld in form.fields) { if (typeof data.event_data.res === 'string') {
switch (fld) { scope.traceback = data.event_data.res;
case 'status':
if (data.failed) {
scope.status = 'error';
} else if (data.changed) {
scope.status = 'changed';
} else {
scope.status = 'success';
}
break;
case 'created':
cDate = new Date(data.created);
scope.created = FormatDate(cDate);
break;
case 'host':
if (data.summary_fields && data.summary_fields.host) {
scope.host = data.summary_fields.host.name;
}
break;
case 'id':
case 'task':
case 'play':
scope[fld] = data[fld];
break;
case 'start':
case 'end':
if (data.event_data && data.event_data.res && !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) {
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;
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];
}
break;
case 'module_name':
case 'module_args':
if (data.event_data.res && data.event_data.res.invocation) {
scope[fld] = data.event_data.res.invocation[fld];
}
break;
} }
}
if (!scope.$$phase) { for (fld in form.fields) {
scope.$digest(); switch (fld) {
} case 'status':
if (data.failed) {
scope.status = 'error';
} else if (data.changed) {
scope.status = 'changed';
} else {
scope.status = 'success';
}
break;
case 'created':
cDate = new Date(data.created);
scope.created = FormatDate(cDate);
break;
case 'host':
if (data.summary_fields && data.summary_fields.host) {
scope.host = data.summary_fields.host.name;
}
break;
case 'id':
case 'task':
case 'play':
scope[fld] = data[fld];
break;
case 'start':
case 'end':
if (data.event_data && data.event_data.res && !Empty(data.event_data.res[fld])) {
scope[fld] = data.event_data.res[fld];
}
}) break;
.error(function (data, status) { case 'results':
$('#form-modal').modal("hide"); if (Array.isArray(data.event_data.res[fld]) && data.event_data.res[fld].length > 0) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!', txt = '';
msg: 'Failed to retrieve event: ' + event_id + '. GET status: ' + status }); for (i = 0; i < data.event_data.res[fld].length; i++) {
}); txt += data.event_data.res[fld][i];
}; }
} if (txt !== '') {
]); scope[fld] = txt;
}
}
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];
}
break;
case 'module_name':
case 'module_args':
if (data.event_data.res && data.event_data.res.invocation) {
scope[fld] = data.event_data.res.invocation[fld];
}
break;
}
}
if (!scope.$$phase) {
scope.$digest();
}
})
.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 });
});
};
}
]);

File diff suppressed because it is too large Load Diff

View File

@@ -11,279 +11,279 @@
* @name helpers.function:HostEventsViewer * @name helpers.function:HostEventsViewer
* @description view a list of events for a given job and host * @description view a list of events for a given job and host
*/ */
'use strict';
angular.module('HostEventsViewerHelper', ['ModalDialog', 'Utilities', 'EventViewerHelper']) export default
angular.module('HostEventsViewerHelper', ['ModalDialog', 'Utilities', 'EventViewerHelper'])
.factory('HostEventsViewer', ['$log', '$compile', 'CreateDialog', 'Wait', 'GetBasePath', 'Empty', 'GetEvents', 'EventViewer', .factory('HostEventsViewer', ['$log', '$compile', 'CreateDialog', 'Wait', 'GetBasePath', 'Empty', 'GetEvents', 'EventViewer',
function($log, $compile, CreateDialog, Wait, GetBasePath, Empty, GetEvents, EventViewer) { function($log, $compile, CreateDialog, Wait, GetBasePath, Empty, GetEvents, EventViewer) {
return function(params) { return function(params) {
var parent_scope = params.scope, var parent_scope = params.scope,
scope = parent_scope.$new(true), scope = parent_scope.$new(true),
job_id = params.job_id, job_id = params.job_id,
url = params.url, url = params.url,
title = params.title, //optional title = params.title, //optional
fixHeight, buildTable, fixHeight, buildTable,
lastID, setStatus, buildRow, status; lastID, setStatus, buildRow, status;
// initialize the status dropdown // initialize the status dropdown
scope.host_events_status_options = [ scope.host_events_status_options = [
{ value: "all", name: "All" }, { value: "all", name: "All" },
{ value: "changed", name: "Changed" }, { value: "changed", name: "Changed" },
{ value: "failed", name: "Failed" }, { value: "failed", name: "Failed" },
{ value: "ok", name: "OK" }, { value: "ok", name: "OK" },
{ value: "unreachable", name: "Unreachable" } { value: "unreachable", name: "Unreachable" }
]; ];
scope.host_events_search_name = params.name; scope.host_events_search_name = params.name;
status = (params.status) ? params.status : 'all'; status = (params.status) ? params.status : 'all';
scope.host_events_status_options.every(function(opt, idx) { scope.host_events_status_options.every(function(opt, idx) {
if (opt.value === status) { if (opt.value === status) {
scope.host_events_search_status = scope.host_events_status_options[idx]; scope.host_events_search_status = scope.host_events_status_options[idx];
return false; return false;
}
return true;
});
if (!scope.host_events_search_status) {
scope.host_events_search_status = scope.host_events_status_options[0];
}
$log.debug('job_id: ' + job_id + ' url: ' + url + ' title: ' + title + ' name: ' + name + ' status: ' + status);
scope.eventsSearchActive = (scope.host_events_search_name) ? true : false;
if (scope.removeModalReady) {
scope.removeModalReady();
}
scope.removeModalReady = scope.$on('ModalReady', function() {
scope.hostViewSearching = false;
$('#host-events-modal-dialog').dialog('open');
});
if (scope.removeJobReady) {
scope.removeJobReady();
}
scope.removeEventReady = scope.$on('EventsReady', function(e, data, maxID) {
var elem, html;
lastID = maxID;
html = buildTable(data);
$('#host-events').html(html);
elem = angular.element(document.getElementById('host-events-modal-dialog'));
$compile(elem)(scope);
CreateDialog({
scope: scope,
width: 675,
height: 600,
minWidth: 450,
callback: 'ModalReady',
id: 'host-events-modal-dialog',
onResizeStop: fixHeight,
title: ( (title) ? title : 'Host Events' ),
onClose: function() {
try {
scope.$destroy();
}
catch(e) {
//ignore
}
},
onOpen: function() {
fixHeight();
} }
return true;
}); });
}); if (!scope.host_events_search_status) {
scope.host_events_search_status = scope.host_events_status_options[0];
if (scope.removeRefreshHTML) {
scope.removeRefreshHTML();
}
scope.removeRefreshHTML = scope.$on('RefreshHTML', function(e, data) {
var elem, html = buildTable(data);
$('#host-events').html(html);
scope.hostViewSearching = false;
elem = angular.element(document.getElementById('host-events'));
$compile(elem)(scope);
});
setStatus = function(result) {
var msg = '', status = 'ok', status_text = 'OK';
if (!result.task && result.event_data && result.event_data.res && result.event_data.res.ansible_facts) {
result.task = "Gathering Facts";
} }
if (result.event === "runner_on_no_hosts") {
msg = "No hosts remaining";
}
if (result.event === 'runner_on_unreachable') {
status = 'unreachable';
status_text = 'Unreachable';
}
else if (result.failed) {
status = 'failed';
status_text = 'Failed';
}
else if (result.changed) {
status = 'changed';
status_text = 'Changed';
}
if (result.event_data.res && result.event_data.res.msg) {
msg = result.event_data.res.msg;
}
result.msg = msg;
result.status = status;
result.status_text = status_text;
return result;
};
buildRow = function(res) { $log.debug('job_id: ' + job_id + ' url: ' + url + ' title: ' + title + ' name: ' + name + ' status: ' + status);
var html = '';
html += "<tr>\n";
html += "<td class=\"col-md-3\"><a href=\"\" ng-click=\"showDetails(" + res.id + ")\" aw-tool-tip=\"Click to view details\" data-placement=\"top\"><i class=\"fa icon-job-" + res.status + "\"></i> " + res.status_text + "</a></td>\n";
html += "<td class=\"col-md=3\" ng-non-bindable>" + res.host_name + "</td>\n";
html += "<td class=\"col-md-3\" ng-non-bindable>" + res.play + "</td>\n";
html += "<td class=\"col-md-3\" ng-non-bindable>" + res.task + "</td>\n";
html += "</tr>";
return html;
};
buildTable = function(data) {
var html = "<table class=\"table\">\n";
html += "<tbody>\n";
data.results.forEach(function(result) {
var res = setStatus(result);
html += buildRow(res);
});
html += "</tbody>\n";
html += "</table>\n";
return html;
};
fixHeight = function() {
var available_height = $('#host-events-modal-dialog').height() - $('#host-events-modal-dialog #search-form').height() - $('#host-events-modal-dialog #fixed-table-header').height();
$('#host-events').height(available_height);
$log.debug('set height to: ' + available_height);
// Check width and reset search fields
if ($('#host-events-modal-dialog').width() <= 450) {
$('#host-events-modal-dialog #status-field').css({'margin-left': '7px'});
}
else {
$('#host-events-modal-dialog #status-field').css({'margin-left': '15px'});
}
};
GetEvents({
url: url,
scope: scope,
callback: 'EventsReady'
});
scope.modalOK = function() {
$('#host-events-modal-dialog').dialog('close');
scope.$destroy();
};
scope.searchEvents = function() {
scope.eventsSearchActive = (scope.host_events_search_name) ? true : false; scope.eventsSearchActive = (scope.host_events_search_name) ? true : false;
GetEvents({
scope: scope,
url: url,
callback: 'RefreshHTML'
});
};
scope.searchEventKeyPress = function(e) { if (scope.removeModalReady) {
if (e.keyCode === 13) { scope.removeModalReady();
scope.searchEvents();
} }
}; scope.removeModalReady = scope.$on('ModalReady', function() {
scope.hostViewSearching = false;
scope.showDetails = function(id) { $('#host-events-modal-dialog').dialog('open');
EventViewer({
scope: parent_scope,
url: GetBasePath('jobs') + job_id + '/job_events/?id=' + id,
}); });
};
if (scope.removeEventsScrollDownBuild) { if (scope.removeJobReady) {
scope.removeEventsScrollDownBuild(); scope.removeJobReady();
} }
scope.removeEventsScrollDownBuild = scope.$on('EventScrollDownBuild', function(e, data, maxID) { scope.removeEventReady = scope.$on('EventsReady', function(e, data, maxID) {
var elem, html = ''; var elem, html;
lastID = maxID;
data.results.forEach(function(result) { lastID = maxID;
var res = setStatus(result); html = buildTable(data);
html += buildRow(res); $('#host-events').html(html);
elem = angular.element(document.getElementById('host-events-modal-dialog'));
$compile(elem)(scope);
CreateDialog({
scope: scope,
width: 675,
height: 600,
minWidth: 450,
callback: 'ModalReady',
id: 'host-events-modal-dialog',
onResizeStop: fixHeight,
title: ( (title) ? title : 'Host Events' ),
onClose: function() {
try {
scope.$destroy();
}
catch(e) {
//ignore
}
},
onOpen: function() {
fixHeight();
}
});
}); });
if (html) {
$('#host-events table tbody').append(html); if (scope.removeRefreshHTML) {
scope.removeRefreshHTML();
}
scope.removeRefreshHTML = scope.$on('RefreshHTML', function(e, data) {
var elem, html = buildTable(data);
$('#host-events').html(html);
scope.hostViewSearching = false;
elem = angular.element(document.getElementById('host-events')); elem = angular.element(document.getElementById('host-events'));
$compile(elem)(scope); $compile(elem)(scope);
}
});
scope.hostEventsScrollDown = function() {
GetEvents({
scope: scope,
url: url,
gt: lastID,
callback: 'EventScrollDownBuild'
}); });
};
}; setStatus = function(result) {
}]) var msg = '', status = 'ok', status_text = 'OK';
if (!result.task && result.event_data && result.event_data.res && result.event_data.res.ansible_facts) {
.factory('GetEvents', ['Rest', 'ProcessErrors', function(Rest, ProcessErrors) { result.task = "Gathering Facts";
return function(params) {
var url = params.url,
scope = params.scope,
gt = params.gt,
callback = params.callback;
if (scope.host_events_search_name) {
url += '?host_name=' + scope.host_events_search_name;
}
else {
url += '?host_name__isnull=false';
}
if (scope.host_events_search_status.value === 'changed') {
url += '&event__icontains=runner&changed=true';
}
else if (scope.host_events_search_status.value === 'failed') {
url += '&event__icontains=runner&failed=true';
}
else if (scope.host_events_search_status.value === 'ok') {
url += '&event=runner_on_ok&changed=false';
}
else if (scope.host_events_search_status.value === 'unreachable') {
url += '&event=runner_on_unreachable';
}
else if (scope.host_events_search_status.value === 'all') {
url += '&event__icontains=runner&not__event=runner_on_skipped';
}
if (gt) {
// used for endless scroll
url += '&id__gt=' + gt;
}
url += '&page_size=50&order=id';
scope.hostViewSearching = true;
Rest.setUrl(url);
Rest.get()
.success(function(data) {
var lastID;
scope.hostViewSearching = false;
if (data.results.length > 0) {
lastID = data.results[data.results.length - 1].id;
} }
scope.$emit(callback, data, lastID); if (result.event === "runner_on_no_hosts") {
}) msg = "No hosts remaining";
.error(function(data, status) { }
scope.hostViewSearching = false; if (result.event === 'runner_on_unreachable') {
ProcessErrors(scope, data, status, null, { hdr: 'Error!', status = 'unreachable';
msg: 'Failed to get events ' + url + '. GET returned: ' + status }); status_text = 'Unreachable';
}
else if (result.failed) {
status = 'failed';
status_text = 'Failed';
}
else if (result.changed) {
status = 'changed';
status_text = 'Changed';
}
if (result.event_data.res && result.event_data.res.msg) {
msg = result.event_data.res.msg;
}
result.msg = msg;
result.status = status;
result.status_text = status_text;
return result;
};
buildRow = function(res) {
var html = '';
html += "<tr>\n";
html += "<td class=\"col-md-3\"><a href=\"\" ng-click=\"showDetails(" + res.id + ")\" aw-tool-tip=\"Click to view details\" data-placement=\"top\"><i class=\"fa icon-job-" + res.status + "\"></i> " + res.status_text + "</a></td>\n";
html += "<td class=\"col-md=3\" ng-non-bindable>" + res.host_name + "</td>\n";
html += "<td class=\"col-md-3\" ng-non-bindable>" + res.play + "</td>\n";
html += "<td class=\"col-md-3\" ng-non-bindable>" + res.task + "</td>\n";
html += "</tr>";
return html;
};
buildTable = function(data) {
var html = "<table class=\"table\">\n";
html += "<tbody>\n";
data.results.forEach(function(result) {
var res = setStatus(result);
html += buildRow(res);
});
html += "</tbody>\n";
html += "</table>\n";
return html;
};
fixHeight = function() {
var available_height = $('#host-events-modal-dialog').height() - $('#host-events-modal-dialog #search-form').height() - $('#host-events-modal-dialog #fixed-table-header').height();
$('#host-events').height(available_height);
$log.debug('set height to: ' + available_height);
// Check width and reset search fields
if ($('#host-events-modal-dialog').width() <= 450) {
$('#host-events-modal-dialog #status-field').css({'margin-left': '7px'});
}
else {
$('#host-events-modal-dialog #status-field').css({'margin-left': '15px'});
}
};
GetEvents({
url: url,
scope: scope,
callback: 'EventsReady'
}); });
};
}]); scope.modalOK = function() {
$('#host-events-modal-dialog').dialog('close');
scope.$destroy();
};
scope.searchEvents = function() {
scope.eventsSearchActive = (scope.host_events_search_name) ? true : false;
GetEvents({
scope: scope,
url: url,
callback: 'RefreshHTML'
});
};
scope.searchEventKeyPress = function(e) {
if (e.keyCode === 13) {
scope.searchEvents();
}
};
scope.showDetails = function(id) {
EventViewer({
scope: parent_scope,
url: GetBasePath('jobs') + job_id + '/job_events/?id=' + id,
});
};
if (scope.removeEventsScrollDownBuild) {
scope.removeEventsScrollDownBuild();
}
scope.removeEventsScrollDownBuild = scope.$on('EventScrollDownBuild', function(e, data, maxID) {
var elem, html = '';
lastID = maxID;
data.results.forEach(function(result) {
var res = setStatus(result);
html += buildRow(res);
});
if (html) {
$('#host-events table tbody').append(html);
elem = angular.element(document.getElementById('host-events'));
$compile(elem)(scope);
}
});
scope.hostEventsScrollDown = function() {
GetEvents({
scope: scope,
url: url,
gt: lastID,
callback: 'EventScrollDownBuild'
});
};
};
}])
.factory('GetEvents', ['Rest', 'ProcessErrors', function(Rest, ProcessErrors) {
return function(params) {
var url = params.url,
scope = params.scope,
gt = params.gt,
callback = params.callback;
if (scope.host_events_search_name) {
url += '?host_name=' + scope.host_events_search_name;
}
else {
url += '?host_name__isnull=false';
}
if (scope.host_events_search_status.value === 'changed') {
url += '&event__icontains=runner&changed=true';
}
else if (scope.host_events_search_status.value === 'failed') {
url += '&event__icontains=runner&failed=true';
}
else if (scope.host_events_search_status.value === 'ok') {
url += '&event=runner_on_ok&changed=false';
}
else if (scope.host_events_search_status.value === 'unreachable') {
url += '&event=runner_on_unreachable';
}
else if (scope.host_events_search_status.value === 'all') {
url += '&event__icontains=runner&not__event=runner_on_skipped';
}
if (gt) {
// used for endless scroll
url += '&id__gt=' + gt;
}
url += '&page_size=50&order=id';
scope.hostViewSearching = true;
Rest.setUrl(url);
Rest.get()
.success(function(data) {
var lastID;
scope.hostViewSearching = false;
if (data.results.length > 0) {
lastID = data.results[data.results.length - 1].id;
}
scope.$emit(callback, data, lastID);
})
.error(function(data, status) {
scope.hostViewSearching = false;
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to get events ' + url + '. GET returned: ' + status });
});
};
}]);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -6,13 +6,13 @@
* Routines shared by job related controllers * Routines shared by job related controllers
* *
*/ */
/** /**
* @ngdoc function * @ngdoc function
* @name helpers.function:JobTemplatesHelper * @name helpers.function:JobTemplatesHelper
* @description Routines shared by job related controllers * @description Routines shared by job related controllers
*/ */
'use strict';
export default
angular.module('JobTemplatesHelper', ['Utilities']) angular.module('JobTemplatesHelper', ['Utilities'])
/* /*
@@ -21,181 +21,180 @@ angular.module('JobTemplatesHelper', ['Utilities'])
*/ */
.factory('CallbackHelpInit', ['$location', 'GetBasePath', 'Rest', 'JobTemplateForm', 'GenerateForm', '$routeParams', 'LoadBreadCrumbs', 'ProcessErrors', 'ParseTypeChange', .factory('CallbackHelpInit', ['$location', 'GetBasePath', 'Rest', 'JobTemplateForm', 'GenerateForm', '$routeParams', 'LoadBreadCrumbs', 'ProcessErrors', 'ParseTypeChange',
'ParseVariableString', 'Empty', 'LookUpInit', 'InventoryList', 'CredentialList','ProjectList', 'RelatedSearchInit', 'RelatedPaginateInit', 'ParseVariableString', 'Empty', 'LookUpInit', 'InventoryList', 'CredentialList','ProjectList', 'RelatedSearchInit', 'RelatedPaginateInit',
function($location, GetBasePath, Rest, JobTemplateForm, GenerateForm, $routeParams, LoadBreadCrumbs, ProcessErrors,ParseTypeChange, function($location, GetBasePath, Rest, JobTemplateForm, GenerateForm, $routeParams, LoadBreadCrumbs, ProcessErrors,ParseTypeChange,
ParseVariableString, Empty, LookUpInit, InventoryList, CredentialList, ProjectList, RelatedSearchInit, RelatedPaginateInit) { ParseVariableString, Empty, LookUpInit, InventoryList, CredentialList, ProjectList, RelatedSearchInit, RelatedPaginateInit) {
return function(params) { return function(params) {
var scope = params.scope, var scope = params.scope,
defaultUrl = GetBasePath('job_templates'), defaultUrl = GetBasePath('job_templates'),
// generator = GenerateForm, // generator = GenerateForm,
form = JobTemplateForm(), form = JobTemplateForm(),
// loadingFinishedCount = 0, // loadingFinishedCount = 0,
// base = $location.path().replace(/^\//, '').split('/')[0], // base = $location.path().replace(/^\//, '').split('/')[0],
master = {}, master = {},
id = $routeParams.template_id, id = $routeParams.template_id,
relatedSets = {}; relatedSets = {};
// checkSCMStatus, getPlaybooks, callback, // checkSCMStatus, getPlaybooks, callback,
// choicesCount = 0; // choicesCount = 0;
// The form uses awPopOverWatch directive to 'watch' scope.callback_help for changes. Each time the // The form uses awPopOverWatch directive to 'watch' scope.callback_help for changes. Each time the
// popover is activated, a function checks the value of scope.callback_help before constructing the content. // popover is activated, a function checks the value of scope.callback_help before constructing the content.
scope.setCallbackHelp = function() { scope.setCallbackHelp = function() {
scope.callback_help = "<p>With a provisioning callback URL and a host config key a host can contact Tower and request a configuration update using this job " + scope.callback_help = "<p>With a provisioning callback URL and a host config key a host can contact Tower and request a configuration update using this job " +
"template. The request from the host must be a POST. Here is an example using curl:</p>\n" + "template. The request from the host must be a POST. Here is an example using curl:</p>\n" +
"<pre>curl --data \"host_config_key=" + scope.example_config_key + "\" " + "<pre>curl --data \"host_config_key=" + scope.example_config_key + "\" " +
scope.callback_server_path + GetBasePath('job_templates') + scope.example_template_id + "/callback/</pre>\n" + scope.callback_server_path + GetBasePath('job_templates') + scope.example_template_id + "/callback/</pre>\n" +
"<p>Note the requesting host must be defined in the inventory associated with the job template. If Tower fails to " + "<p>Note the requesting host must be defined in the inventory associated with the job template. If Tower fails to " +
"locate the host, the request will be denied.</p>" + "locate the host, the request will be denied.</p>" +
"<p>Successful requests create an entry on the Jobs page, where results and history can be viewed.</p>"; "<p>Successful requests create an entry on the Jobs page, where results and history can be viewed.</p>";
}; };
// The md5 helper emits NewMD5Generated whenever a new key is available // The md5 helper emits NewMD5Generated whenever a new key is available
if (scope.removeNewMD5Generated) { if (scope.removeNewMD5Generated) {
scope.removeNewMD5Generated(); scope.removeNewMD5Generated();
} }
scope.removeNewMD5Generated = scope.$on('NewMD5Generated', function() { scope.removeNewMD5Generated = scope.$on('NewMD5Generated', function() {
scope.configKeyChange(); scope.configKeyChange();
}); });
// Fired when user enters a key value // Fired when user enters a key value
scope.configKeyChange = function() { scope.configKeyChange = function() {
scope.example_config_key = scope.host_config_key; scope.example_config_key = scope.host_config_key;
scope.setCallbackHelp(); scope.setCallbackHelp();
}; };
// Set initial values and construct help text // Set initial values and construct help text
scope.callback_server_path = $location.protocol() + '://' + $location.host() + (($location.port()) ? ':' + $location.port() : ''); scope.callback_server_path = $location.protocol() + '://' + $location.host() + (($location.port()) ? ':' + $location.port() : '');
scope.example_config_key = '5a8ec154832b780b9bdef1061764ae5a'; scope.example_config_key = '5a8ec154832b780b9bdef1061764ae5a';
scope.example_template_id = 'N'; scope.example_template_id = 'N';
scope.setCallbackHelp(); scope.setCallbackHelp();
scope.fillJobTemplate = function(){ scope.fillJobTemplate = function(){
// id = id || $rootScope.copy.id; // id = id || $rootScope.copy.id;
// Retrieve detail record and prepopulate the form // Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl + id); Rest.setUrl(defaultUrl + id);
Rest.get() Rest.get()
.success(function (data) { .success(function (data) {
var fld, i; var fld, i;
LoadBreadCrumbs({ path: '/job_templates/' + id, title: data.name }); LoadBreadCrumbs({ path: '/job_templates/' + id, title: data.name });
for (fld in form.fields) { for (fld in form.fields) {
if (fld !== 'variables' && data[fld] !== null && data[fld] !== undefined) { if (fld !== 'variables' && data[fld] !== null && data[fld] !== undefined) {
if (form.fields[fld].type === 'select') { if (form.fields[fld].type === 'select') {
if (scope[fld + '_options'] && scope[fld + '_options'].length > 0) { if (scope[fld + '_options'] && scope[fld + '_options'].length > 0) {
for (i = 0; i < scope[fld + '_options'].length; i++) { for (i = 0; i < scope[fld + '_options'].length; i++) {
if (data[fld] === scope[fld + '_options'][i].value) { if (data[fld] === scope[fld + '_options'][i].value) {
scope[fld] = scope[fld + '_options'][i]; scope[fld] = scope[fld + '_options'][i];
} }
} }
} else { } else {
scope[fld] = data[fld]; scope[fld] = data[fld];
} }
} else { } else {
scope[fld] = data[fld]; scope[fld] = data[fld];
if(fld ==='survey_enabled'){ if(fld ==='survey_enabled'){
// $scope.$emit('EnableSurvey', fld); // $scope.$emit('EnableSurvey', fld);
$('#job_templates_survey_enabled_chbox').attr('checked', scope[fld]); $('#job_templates_survey_enabled_chbox').attr('checked', scope[fld]);
if(Empty(data.summary_fields.survey)) { if(Empty(data.summary_fields.survey)) {
$('#job_templates_delete_survey_btn').hide(); $('#job_templates_delete_survey_btn').hide();
$('#job_templates_edit_survey_btn').hide(); $('#job_templates_edit_survey_btn').hide();
$('#job_templates_create_survey_btn').show(); $('#job_templates_create_survey_btn').show();
} }
else{ else{
$('#job_templates_delete_survey_btn').show(); $('#job_templates_delete_survey_btn').show();
$('#job_templates_edit_survey_btn').show(); $('#job_templates_edit_survey_btn').show();
$('#job_templates_create_survey_btn').hide(); $('#job_templates_create_survey_btn').hide();
scope.survey_exists = true; scope.survey_exists = true;
} }
} }
} }
master[fld] = scope[fld]; master[fld] = scope[fld];
} }
if (fld === 'variables') { if (fld === 'variables') {
// Parse extra_vars, converting to YAML. // Parse extra_vars, converting to YAML.
scope.variables = ParseVariableString(data.extra_vars); scope.variables = ParseVariableString(data.extra_vars);
master.variables = scope.variables; master.variables = scope.variables;
} }
if (form.fields[fld].type === 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) { if (form.fields[fld].type === 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) {
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
data.summary_fields[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] = master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField]; scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField];
} }
} }
scope.url = data.url; scope.url = data.url;
scope.ask_variables_on_launch = (data.ask_variables_on_launch) ? 'true' : 'false'; scope.ask_variables_on_launch = (data.ask_variables_on_launch) ? 'true' : 'false';
master.ask_variables_on_launch = scope.ask_variables_on_launch; master.ask_variables_on_launch = scope.ask_variables_on_launch;
relatedSets = form.relatedSets(data.related); relatedSets = form.relatedSets(data.related);
if (data.host_config_key) { if (data.host_config_key) {
scope.example_config_key = data.host_config_key; scope.example_config_key = data.host_config_key;
} }
scope.example_template_id = id; scope.example_template_id = id;
scope.setCallbackHelp(); scope.setCallbackHelp();
scope.callback_url = scope.callback_server_path + ((data.related.callback) ? data.related.callback : scope.callback_url = scope.callback_server_path + ((data.related.callback) ? data.related.callback :
GetBasePath('job_templates') + id + '/callback/'); GetBasePath('job_templates') + id + '/callback/');
master.callback_url = scope.callback_url; master.callback_url = scope.callback_url;
scope.can_edit = data.summary_fields.can_edit; scope.can_edit = data.summary_fields.can_edit;
LookUpInit({ LookUpInit({
scope: scope, scope: scope,
form: form, form: form,
current_item: data.inventory, current_item: data.inventory,
list: InventoryList, list: InventoryList,
field: 'inventory', field: 'inventory',
input_type: "radio" input_type: "radio"
}); });
LookUpInit({ LookUpInit({
url: GetBasePath('credentials') + '?kind=ssh', url: GetBasePath('credentials') + '?kind=ssh',
scope: scope, scope: scope,
form: form, form: form,
current_item: data.credential, current_item: data.credential,
list: CredentialList, list: CredentialList,
field: 'credential', field: 'credential',
hdr: 'Select Machine Credential', hdr: 'Select Machine Credential',
input_type: "radio" input_type: "radio"
}); });
LookUpInit({ LookUpInit({
scope: scope, scope: scope,
form: form, form: form,
current_item: data.project, current_item: data.project,
list: ProjectList, list: ProjectList,
field: 'project', field: 'project',
input_type: "radio" input_type: "radio"
}); });
RelatedSearchInit({ RelatedSearchInit({
scope: scope, scope: scope,
form: form, form: form,
relatedSets: relatedSets relatedSets: relatedSets
}); });
RelatedPaginateInit({ RelatedPaginateInit({
scope: scope, scope: scope,
relatedSets: relatedSets relatedSets: relatedSets
}); });
scope.$emit('jobTemplateLoaded', data.related.cloud_credential, master); scope.$emit('jobTemplateLoaded', data.related.cloud_credential, master);
}) })
.error(function (data, status) { .error(function (data, status) {
ProcessErrors(scope, data, status, form, { ProcessErrors(scope, data, status, form, {
hdr: 'Error!', hdr: 'Error!',
msg: 'Failed to retrieve job template: ' + $routeParams.template_id + '. GET status: ' + status msg: 'Failed to retrieve job template: ' + $routeParams.template_id + '. GET status: ' + status
}); });
}); });
}; };
}; };
}]); }]);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -14,8 +14,9 @@
/*jshint evil:true */ /*jshint evil:true */
'use strict';
export default
angular.module('LoadConfigHelper', ['Utilities']) angular.module('LoadConfigHelper', ['Utilities'])
.factory('LoadConfig', ['$log', '$rootScope', '$http', 'ProcessErrors', 'Store', function($log, $rootScope, $http, ProcessErrors, Store) { .factory('LoadConfig', ['$log', '$rootScope', '$http', 'ProcessErrors', 'Store', function($log, $rootScope, $http, ProcessErrors, Store) {

View File

@@ -9,374 +9,374 @@
* @name helpers.function:LogViewer * @name helpers.function:LogViewer
* @description logviewer * @description logviewer
*/ */
'use strict';
angular.module('LogViewerHelper', ['ModalDialog', 'Utilities', 'FormGenerator', 'VariablesHelper']) export default
angular.module('LogViewerHelper', ['ModalDialog', 'Utilities', 'FormGenerator', 'VariablesHelper'])
.factory('LogViewer', ['$location', '$compile', 'CreateDialog', 'GetJob', 'Wait', 'GenerateForm', 'LogViewerStatusForm', 'AddTable', 'AddTextarea', .factory('LogViewer', ['$location', '$compile', 'CreateDialog', 'GetJob', 'Wait', 'GenerateForm', 'LogViewerStatusForm', 'AddTable', 'AddTextarea',
'LogViewerOptionsForm', 'EnvTable', 'GetBasePath', 'LookUpName', 'Empty', 'AddPreFormattedText', 'ParseVariableString', 'GetChoices', 'LogViewerOptionsForm', 'EnvTable', 'GetBasePath', 'LookUpName', 'Empty', 'AddPreFormattedText', 'ParseVariableString', 'GetChoices',
function($location, $compile, CreateDialog, GetJob, Wait, GenerateForm, LogViewerStatusForm, AddTable, AddTextarea, LogViewerOptionsForm, EnvTable, function($location, $compile, CreateDialog, GetJob, Wait, GenerateForm, LogViewerStatusForm, AddTable, AddTextarea, LogViewerOptionsForm, EnvTable,
GetBasePath, LookUpName, Empty, AddPreFormattedText, ParseVariableString, GetChoices) { GetBasePath, LookUpName, Empty, AddPreFormattedText, ParseVariableString, GetChoices) {
return function(params) { return function(params) {
var parent_scope = params.scope, var parent_scope = params.scope,
url = params.url, url = params.url,
getIcon = params.getIcon, getIcon = params.getIcon,
scope = parent_scope.$new(true), scope = parent_scope.$new(true),
base = $location.path().replace(/^\//, '').split('/')[0], base = $location.path().replace(/^\//, '').split('/')[0],
pieces; pieces;
if (scope.removeModalReady) { if (scope.removeModalReady) {
scope.removeModalReady(); scope.removeModalReady();
}
scope.removeModalReady = scope.$on('ModalReady', function() {
Wait('stop');
$('#logviewer-modal-dialog').dialog('open');
});
if (scope.removeJobReady) {
scope.removeJobReady();
}
scope.removeJobReady = scope.$on('JobReady', function(e, data) {
var key, resizeText, elem;
$('#status-form-container').empty();
$('#options-form-container').empty();
$('#stdout-form-container').empty();
$('#traceback-form-container').empty();
$('#variables-container').empty();
$('#source-container').empty();
$('#logview-tabs li:eq(1)').hide();
$('#logview-tabs li:eq(2)').hide();
$('#logview-tabs li:eq(4)').hide();
$('#logview-tabs li:eq(5)').hide();
// Make sure subsequenct scope references don't bubble up to the parent
for (key in LogViewerStatusForm.fields) {
scope[key] = '';
}
for (key in LogViewerOptionsForm.fields) {
scope[key] = '';
} }
scope.removeModalReady = scope.$on('ModalReady', function() {
Wait('stop');
$('#logviewer-modal-dialog').dialog('open');
});
for (key in data) { if (scope.removeJobReady) {
scope[key] = data[key]; scope.removeJobReady();
} }
scope.created_by = ''; scope.removeJobReady = scope.$on('JobReady', function(e, data) {
scope.job_template = ''; var key, resizeText, elem;
$('#status-form-container').empty();
$('#options-form-container').empty();
$('#stdout-form-container').empty();
$('#traceback-form-container').empty();
$('#variables-container').empty();
$('#source-container').empty();
$('#logview-tabs li:eq(1)').hide();
$('#logview-tabs li:eq(2)').hide();
$('#logview-tabs li:eq(4)').hide();
$('#logview-tabs li:eq(5)').hide();
if (data.related.created_by) { // Make sure subsequenct scope references don't bubble up to the parent
pieces = data.related.created_by.replace(/^\//,'').replace(/\/$/,'').split('/'); for (key in LogViewerStatusForm.fields) {
scope.created_by = parseInt(pieces[pieces.length - 1],10); scope[key] = '';
LookUpName({
scope: scope,
scope_var: 'created_by',
url: GetBasePath('users') + scope.created_by + '/'
});
}
// For jobs link the name to the job parent
if (base === 'jobs') {
if (data.type === 'job') {
scope.name_link = "job_template";
scope.job_template = data.unified_job_template;
scope.job_template_name = (data.summary_fields.job_template) ? data.summary_fields.job_template.name : data.name;
scope.name_id = data.unified_job_template;
} }
if (data.type === 'project_update') { for (key in LogViewerOptionsForm.fields) {
scope.name_link = "project"; scope[key] = '';
scope.name_id = data.unified_job_template;
} }
if (data.type === 'inventory_update') {
scope.name_link = "inventory_source"; for (key in data) {
scope.name_id = scope.group; scope[key] = data[key];
} }
} scope.created_by = '';
scope.job_template = '';
AddTable({ scope: scope, form: LogViewerStatusForm, id: 'status-form-container', getIcon: getIcon }); if (data.related.created_by) {
AddTable({ scope: scope, form: LogViewerOptionsForm, id: 'options-form-container', getIcon: getIcon }); pieces = data.related.created_by.replace(/^\//,'').replace(/\/$/,'').split('/');
scope.created_by = parseInt(pieces[pieces.length - 1],10);
if (data.result_stdout) { LookUpName({
$('#logview-tabs li:eq(1)').show(); scope: scope,
AddPreFormattedText({ scope_var: 'created_by',
id: 'stdout-form-container', url: GetBasePath('users') + scope.created_by + '/'
val: data.result_stdout
});
}
if (data.result_traceback) {
$('#logview-tabs li:eq(2)').show();
AddPreFormattedText({
id: 'traceback-form-container',
val: data.result_traceback
});
}
/*if (data.job_env) {
EnvTable({
id: 'env-form-container',
vars: data.job_env
});
}*/
if (data.extra_vars) {
$('#logview-tabs li:eq(4)').show();
AddTextarea({
container_id: 'variables-container',
fld_id: 'variables',
val: ParseVariableString(data.extra_vars)
});
}
if (data.source_vars) {
$('#logview-tabs li:eq(5)').show();
AddTextarea({
container_id: 'source-container',
fld_id: 'source-variables',
val: ParseVariableString(data.source_vars)
});
}
if (!Empty(scope.source)) {
if (scope.removeChoicesReady) {
scope.removeChoicesReady();
}
scope.removeChoicesReady = scope.$on('ChoicesReady', function() {
scope.source_choices.every(function(e) {
if (e.value === scope.source) {
scope.source = e.label;
return false;
}
return true;
}); });
}); }
GetChoices({
scope: scope,
url: GetBasePath('inventory_sources'),
field: 'source',
variable: 'source_choices',
choice_name: 'choices',
callback: 'ChoicesReady'
});
}
if (!Empty(scope.credential)) { // For jobs link the name to the job parent
LookUpName({ if (base === 'jobs') {
scope: scope, if (data.type === 'job') {
scope_var: 'credential', scope.name_link = "job_template";
url: GetBasePath('credentials') + scope.credential + '/' scope.job_template = data.unified_job_template;
}); scope.job_template_name = (data.summary_fields.job_template) ? data.summary_fields.job_template.name : data.name;
} scope.name_id = data.unified_job_template;
}
if (data.type === 'project_update') {
scope.name_link = "project";
scope.name_id = data.unified_job_template;
}
if (data.type === 'inventory_update') {
scope.name_link = "inventory_source";
scope.name_id = scope.group;
}
}
if (!Empty(scope.inventory)) { AddTable({ scope: scope, form: LogViewerStatusForm, id: 'status-form-container', getIcon: getIcon });
LookUpName({ AddTable({ scope: scope, form: LogViewerOptionsForm, id: 'options-form-container', getIcon: getIcon });
scope: scope,
scope_var: 'inventory',
url: GetBasePath('inventory') + scope.inventory + '/'
});
}
if (!Empty(scope.project)) { if (data.result_stdout) {
LookUpName({ $('#logview-tabs li:eq(1)').show();
scope: scope, AddPreFormattedText({
scope_var: 'project', id: 'stdout-form-container',
url: GetBasePath('projects') + scope.project + '/' val: data.result_stdout
}); });
} }
if (!Empty(scope.cloud_credential)) { if (data.result_traceback) {
LookUpName({ $('#logview-tabs li:eq(2)').show();
scope: scope, AddPreFormattedText({
scope_var: 'cloud_credential', id: 'traceback-form-container',
url: GetBasePath('credentials') + scope.cloud_credential + '/' val: data.result_traceback
}); });
} }
if (!Empty(scope.inventory_source)) { /*if (data.job_env) {
LookUpName({ EnvTable({
scope: scope, id: 'env-form-container',
scope_var: 'inventory_source', vars: data.job_env
url: GetBasePath('inventory_sources') + scope.inventory_source + '/' });
}); }*/
}
resizeText = function() { if (data.extra_vars) {
var u = $('#logview-tabs').outerHeight() + 25, $('#logview-tabs li:eq(4)').show();
h = $('#logviewer-modal-dialog').innerHeight(), AddTextarea({
rows = Math.floor((h - u) / 20); container_id: 'variables-container',
rows -= 3; fld_id: 'variables',
rows = (rows < 6) ? 6 : rows; val: ParseVariableString(data.extra_vars)
$('#logviewer-modal-dialog #variables').attr({ rows: rows }); });
$('#logviewer-modal-dialog #source-variables').attr({ rows: rows }); }
if (data.source_vars) {
$('#logview-tabs li:eq(5)').show();
AddTextarea({
container_id: 'source-container',
fld_id: 'source-variables',
val: ParseVariableString(data.source_vars)
});
}
if (!Empty(scope.source)) {
if (scope.removeChoicesReady) {
scope.removeChoicesReady();
}
scope.removeChoicesReady = scope.$on('ChoicesReady', function() {
scope.source_choices.every(function(e) {
if (e.value === scope.source) {
scope.source = e.label;
return false;
}
return true;
});
});
GetChoices({
scope: scope,
url: GetBasePath('inventory_sources'),
field: 'source',
variable: 'source_choices',
choice_name: 'choices',
callback: 'ChoicesReady'
});
}
if (!Empty(scope.credential)) {
LookUpName({
scope: scope,
scope_var: 'credential',
url: GetBasePath('credentials') + scope.credential + '/'
});
}
if (!Empty(scope.inventory)) {
LookUpName({
scope: scope,
scope_var: 'inventory',
url: GetBasePath('inventory') + scope.inventory + '/'
});
}
if (!Empty(scope.project)) {
LookUpName({
scope: scope,
scope_var: 'project',
url: GetBasePath('projects') + scope.project + '/'
});
}
if (!Empty(scope.cloud_credential)) {
LookUpName({
scope: scope,
scope_var: 'cloud_credential',
url: GetBasePath('credentials') + scope.cloud_credential + '/'
});
}
if (!Empty(scope.inventory_source)) {
LookUpName({
scope: scope,
scope_var: 'inventory_source',
url: GetBasePath('inventory_sources') + scope.inventory_source + '/'
});
}
resizeText = function() {
var u = $('#logview-tabs').outerHeight() + 25,
h = $('#logviewer-modal-dialog').innerHeight(),
rows = Math.floor((h - u) / 20);
rows -= 3;
rows = (rows < 6) ? 6 : rows;
$('#logviewer-modal-dialog #variables').attr({ rows: rows });
$('#logviewer-modal-dialog #source-variables').attr({ rows: rows });
};
elem = angular.element(document.getElementById('logviewer-modal-dialog'));
$compile(elem)(scope);
CreateDialog({
scope: scope,
width: 600,
height: 550,
minWidth: 450,
callback: 'ModalReady',
id: 'logviewer-modal-dialog',
onResizeStop: resizeText,
title: 'Job Results',
onOpen: function() {
$('#logview-tabs a:first').tab('show');
$('#dialog-ok-button').focus();
resizeText();
}
});
});
GetJob({
url: url,
scope: scope
});
scope.modalOK = function() {
$('#logviewer-modal-dialog').dialog('close');
scope.$destroy();
}; };
elem = angular.element(document.getElementById('logviewer-modal-dialog'));
$compile(elem)(scope);
CreateDialog({
scope: scope,
width: 600,
height: 550,
minWidth: 450,
callback: 'ModalReady',
id: 'logviewer-modal-dialog',
onResizeStop: resizeText,
title: 'Job Results',
onOpen: function() {
$('#logview-tabs a:first').tab('show');
$('#dialog-ok-button').focus();
resizeText();
}
});
});
GetJob({
url: url,
scope: scope
});
scope.modalOK = function() {
$('#logviewer-modal-dialog').dialog('close');
scope.$destroy();
}; };
}; }])
}])
.factory('GetJob', ['Rest', 'ProcessErrors', function(Rest, ProcessErrors) { .factory('GetJob', ['Rest', 'ProcessErrors', function(Rest, ProcessErrors) {
return function(params) { return function(params) {
var url = params.url, var url = params.url,
scope = params.scope; scope = params.scope;
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success(function(data){ .success(function(data){
scope.$emit('JobReady', data); scope.$emit('JobReady', data);
}) })
.error(function(data, status) { .error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!', ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve ' + url + '. GET returned: ' + status }); msg: 'Failed to retrieve ' + url + '. GET returned: ' + status });
}); });
}; };
}]) }])
.factory('LookUpName', ['Rest', 'ProcessErrors', 'Empty', function(Rest, ProcessErrors, Empty) { .factory('LookUpName', ['Rest', 'ProcessErrors', 'Empty', function(Rest, ProcessErrors, Empty) {
return function(params) { return function(params) {
var url = params.url, var url = params.url,
scope_var = params.scope_var, scope_var = params.scope_var,
scope = params.scope; scope = params.scope;
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success(function(data) { .success(function(data) {
if (scope_var === 'inventory_source') { if (scope_var === 'inventory_source') {
scope[scope_var + '_name'] = data.summary_fields.group.name; scope[scope_var + '_name'] = data.summary_fields.group.name;
} }
else if (!Empty(data.name)) { else if (!Empty(data.name)) {
scope[scope_var + '_name'] = data.name; scope[scope_var + '_name'] = data.name;
} }
if (!Empty(data.group)) { if (!Empty(data.group)) {
// Used for inventory_source // Used for inventory_source
scope.group = data.group; scope.group = data.group;
} }
}) })
.error(function(data, status) { .error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!', ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve ' + url + '. GET returned: ' + status }); msg: 'Failed to retrieve ' + url + '. GET returned: ' + status });
}); });
}; };
}]) }])
.factory('AddTable', ['$compile', 'Empty', 'Find', function($compile, Empty, Find) { .factory('AddTable', ['$compile', 'Empty', 'Find', function($compile, Empty, Find) {
return function(params) { return function(params) {
var form = params.form, var form = params.form,
id = params.id, id = params.id,
scope = params.scope, scope = params.scope,
getIcon = params.getIcon, getIcon = params.getIcon,
fld, html, url, e, fld, html, url, e,
urls = [ urls = [
{ "variable": "credential", "url": "/#/credentials/" }, { "variable": "credential", "url": "/#/credentials/" },
{ "variable": "project", "url": "/#/projects/" }, { "variable": "project", "url": "/#/projects/" },
{ "variable": "inventory", "url": "/#/inventories/" }, { "variable": "inventory", "url": "/#/inventories/" },
{ "variable": "cloud_credential", "url": "/#/credentials/" }, { "variable": "cloud_credential", "url": "/#/credentials/" },
{ "variable": "inventory_source", "url": "/#/home/groups/?id={{ group }}" }, { "variable": "inventory_source", "url": "/#/home/groups/?id={{ group }}" },
{ "variable": "job_template", "url": "/#/job_templates/" }, { "variable": "job_template", "url": "/#/job_templates/" },
{ "variable": "created_by", "url": "/#/users/" } { "variable": "created_by", "url": "/#/users/" }
]; ];
html = "<table class=\"table logviewer-status\">\n"; html = "<table class=\"table logviewer-status\">\n";
for (fld in form.fields) { for (fld in form.fields) {
if (!Empty(scope[fld])) { if (!Empty(scope[fld])) {
html += "<tr><td class=\"fld-label col-md-3 col-sm-3 col-xs-3\">" + form.fields[fld].label + "</td>" + html += "<tr><td class=\"fld-label col-md-3 col-sm-3 col-xs-3\">" + form.fields[fld].label + "</td>" +
"<td>"; "<td>";
url = Find({ list: urls, key: "variable", val: fld }); url = Find({ list: urls, key: "variable", val: fld });
if (url) { if (url) {
html += "<a href=\"" + url.url; html += "<a href=\"" + url.url;
html += (fld === "inventory_source") ? "" : scope[fld]; html += (fld === "inventory_source") ? "" : scope[fld];
html += "\" ng-click=\"modalOK()\">{{ " + fld + '_name' + " }}</a>"; html += "\" ng-click=\"modalOK()\">{{ " + fld + '_name' + " }}</a>";
} }
else if (fld === 'name' && scope.name_link) { else if (fld === 'name' && scope.name_link) {
url = Find({ list: urls, key: "variable", val: scope.name_link }); url = Find({ list: urls, key: "variable", val: scope.name_link });
html += "<a href=\"" + url.url + ( (scope.name_link === 'inventory_source') ? '' : scope.name_id ) + "\" ng-click=\"modalOK()\">{{ " + html += "<a href=\"" + url.url + ( (scope.name_link === 'inventory_source') ? '' : scope.name_id ) + "\" ng-click=\"modalOK()\">{{ " +
( (scope.name_link === 'inventory_source') ? 'inventory_source_name' : fld ) + " }}</a>"; ( (scope.name_link === 'inventory_source') ? 'inventory_source_name' : fld ) + " }}</a>";
} }
else if (fld === 'elapsed') { else if (fld === 'elapsed') {
html += scope[fld] + " <span class=\"small-text\">seconds</span>"; html += scope[fld] + " <span class=\"small-text\">seconds</span>";
} }
else if (fld === 'status') { else if (fld === 'status') {
if (getIcon) { if (getIcon) {
html += "<i class=\"fa icon-job-" + getIcon(scope[fld]) + "\"></i> " + scope[fld]; html += "<i class=\"fa icon-job-" + getIcon(scope[fld]) + "\"></i> " + scope[fld];
}
else {
html += "<i class=\"fa icon-job-" + scope[fld] + "\"></i> " + scope[fld];
}
if (scope.job_explanation) {
html += "<p style=\"padding-top: 12px\">" + scope.job_explanation + "</p>";
}
} }
else { else {
html += "<i class=\"fa icon-job-" + scope[fld] + "\"></i> " + scope[fld]; html += "{{ " + fld ;
} html += (form.fields[fld].filter) ? " | " + form.fields[fld].filter : "" ;
if (scope.job_explanation) { html += " }}";
html += "<p style=\"padding-top: 12px\">" + scope.job_explanation + "</p>";
} }
html += "</td></tr>\n";
} }
else {
html += "{{ " + fld ;
html += (form.fields[fld].filter) ? " | " + form.fields[fld].filter : "" ;
html += " }}";
}
html += "</td></tr>\n";
} }
} html += "</table>\n";
html += "</table>\n"; e = angular.element(document.getElementById(id));
e = angular.element(document.getElementById(id)); e.empty().html(html);
e.empty().html(html); $compile(e)(scope);
$compile(e)(scope); };
}; }])
}])
.factory('AddTextarea', [ function() { .factory('AddTextarea', [ function() {
return function(params) { return function(params) {
var container_id = params.container_id, var container_id = params.container_id,
val = params.val, val = params.val,
fld_id = params.fld_id, fld_id = params.fld_id,
html; html;
html = "<div class=\"form-group\">\n" + html = "<div class=\"form-group\">\n" +
"<textarea id=\"" + fld_id + "\" ng-non-bindable class=\"form-control mono-space\" rows=\"12\" readonly>" + val + "</textarea>" + "<textarea id=\"" + fld_id + "\" ng-non-bindable class=\"form-control mono-space\" rows=\"12\" readonly>" + val + "</textarea>" +
"</div>\n"; "</div>\n";
$('#' + container_id).empty().html(html); $('#' + container_id).empty().html(html);
}; };
}]) }])
.factory('AddPreFormattedText', [function() { .factory('AddPreFormattedText', [function() {
return function(params) { return function(params) {
var id = params.id, var id = params.id,
val = params.val, val = params.val,
html; html;
html = "<pre ng-non-bindable>" + val + "</pre>\n"; html = "<pre ng-non-bindable>" + val + "</pre>\n";
$('#' + id).empty().html(html); $('#' + id).empty().html(html);
}; };
}]) }])
.factory('EnvTable', [ function() { .factory('EnvTable', [ function() {
return function(params) { return function(params) {
var id = params.id, var id = params.id,
vars = params.vars, vars = params.vars,
key, html; key, html;
html = "<table class=\"table logviewer-status\">\n"; html = "<table class=\"table logviewer-status\">\n";
for (key in vars) { for (key in vars) {
html += "<tr><td class=\"fld-label col-md-4 col-sm-3 col-xs-3 break\">" + key + "</td>" + html += "<tr><td class=\"fld-label col-md-4 col-sm-3 col-xs-3 break\">" + key + "</td>" +
"<td ng-non-bindable class=\"break\">" + vars[key] + "</td></tr>\n"; "<td ng-non-bindable class=\"break\">" + vars[key] + "</td></tr>\n";
} }
html += "</table>\n"; html += "</table>\n";
$('#' + id).empty().html(html); $('#' + id).empty().html(html);
}; };
}]); }]);

View File

@@ -22,229 +22,229 @@
* }) * })
*/ */
'use strict';
angular.module('LookUpHelper', ['RestServices', 'Utilities', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ApiLoader', 'ModalDialog']) export default
angular.module('LookUpHelper', ['RestServices', 'Utilities', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ApiLoader', 'ModalDialog'])
.factory('LookUpInit', ['Alert', 'Rest', 'GenerateList', 'SearchInit', 'PaginateInit', 'GetBasePath', 'FormatDate', 'Empty', 'CreateDialog', .factory('LookUpInit', ['Alert', 'Rest', 'GenerateList', 'SearchInit', 'PaginateInit', 'GetBasePath', 'FormatDate', 'Empty', 'CreateDialog',
function (Alert, Rest, GenerateList, SearchInit, PaginateInit, GetBasePath, FormatDate, Empty, CreateDialog) { function (Alert, Rest, GenerateList, SearchInit, PaginateInit, GetBasePath, FormatDate, Empty, CreateDialog) {
return function (params) { return function (params) {
var parent_scope = params.scope, var parent_scope = params.scope,
form = params.form, form = params.form,
list = params.list, list = params.list,
field = params.field, field = params.field,
instructions = params.instructions, instructions = params.instructions,
postAction = params.postAction, postAction = params.postAction,
callback = params.callback, callback = params.callback,
input_type = (params.input_type) ? params.input_type: "checkbox", input_type = (params.input_type) ? params.input_type: "checkbox",
defaultUrl, name, watchUrl; defaultUrl, name, watchUrl;
if (params.url) { if (params.url) {
// pass in a url value to override the default // pass in a url value to override the default
defaultUrl = params.url; defaultUrl = params.url;
} else { } else {
defaultUrl = (list.name === 'inventories') ? GetBasePath('inventory') : GetBasePath(list.name); defaultUrl = (list.name === 'inventories') ? GetBasePath('inventory') : GetBasePath(list.name);
} }
if ($('#htmlTemplate #lookup-modal-dialog').length > 0) { if ($('#htmlTemplate #lookup-modal-dialog').length > 0) {
$('#htmlTemplate #lookup-modal-dialog').empty(); $('#htmlTemplate #lookup-modal-dialog').empty();
} }
else { else {
$('#htmlTemplate').append("<div id=\"lookup-modal-dialog\"></div>"); $('#htmlTemplate').append("<div id=\"lookup-modal-dialog\"></div>");
} }
name = list.iterator.charAt(0).toUpperCase() + list.iterator.substring(1);
watchUrl = (/\/$/.test(defaultUrl)) ? defaultUrl + '?' : defaultUrl + '&';
watchUrl += form.fields[field].sourceField + '__' + 'iexact=:value';
$('input[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').attr('data-url', watchUrl);
$('input[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').attr('data-source', field);
parent_scope['lookUp' + name] = function () {
var master = {},
scope = parent_scope.$new(),
name, hdr, buttons;
// Generating the search list potentially kills the values held in scope for the field.
// We'll keep a copy in master{} that we can revert back to on cancel;
master[field] = scope[field];
master[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] =
scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField];
GenerateList.inject(list, {
mode: 'lookup',
id: 'lookup-modal-dialog',
scope: scope,
instructions: instructions,
input_type: input_type
});
name = list.iterator.charAt(0).toUpperCase() + list.iterator.substring(1); name = list.iterator.charAt(0).toUpperCase() + list.iterator.substring(1);
hdr = (params.hdr) ? params.hdr : 'Select ' + name;
// Show pop-up watchUrl = (/\/$/.test(defaultUrl)) ? defaultUrl + '?' : defaultUrl + '&';
buttons = [{ watchUrl += form.fields[field].sourceField + '__' + 'iexact=:value';
label: "Cancel",
icon: "fa-times", $('input[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').attr('data-url', watchUrl);
"class": "btn btn-default", $('input[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').attr('data-source', field);
"id": "lookup-cancel-button",
onClick: function() {
$('#lookup-modal-dialog').dialog('close'); parent_scope['lookUp' + name] = function () {
var master = {},
scope = parent_scope.$new(),
name, hdr, buttons;
// Generating the search list potentially kills the values held in scope for the field.
// We'll keep a copy in master{} that we can revert back to on cancel;
master[field] = scope[field];
master[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] =
scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField];
GenerateList.inject(list, {
mode: 'lookup',
id: 'lookup-modal-dialog',
scope: scope,
instructions: instructions,
input_type: input_type
});
name = list.iterator.charAt(0).toUpperCase() + list.iterator.substring(1);
hdr = (params.hdr) ? params.hdr : 'Select ' + name;
// Show pop-up
buttons = [{
label: "Cancel",
icon: "fa-times",
"class": "btn btn-default",
"id": "lookup-cancel-button",
onClick: function() {
$('#lookup-modal-dialog').dialog('close');
}
},{
label: "Select",
onClick: function() {
scope.selectAction();
},
icon: "fa-check",
"class": "btn btn-primary",
"id": "lookup-save-button"
}];
if (scope.removeModalReady) {
scope.removeModalReady();
} }
},{ scope.removeModalReady = scope.$on('ModalReady', function() {
label: "Select", $('#lookup-save-button').attr('disabled','disabled');
onClick: function() { $('#lookup-modal-dialog').dialog('open');
scope.selectAction(); });
},
icon: "fa-check",
"class": "btn btn-primary",
"id": "lookup-save-button"
}];
if (scope.removeModalReady) { CreateDialog({
scope.removeModalReady(); scope: scope,
} buttons: buttons,
scope.removeModalReady = scope.$on('ModalReady', function() { width: 600,
$('#lookup-save-button').attr('disabled','disabled'); height: (instructions) ? 625 : 500,
$('#lookup-modal-dialog').dialog('open'); minWidth: 500,
}); title: hdr,
id: 'lookup-modal-dialog',
onClose: function() {
setTimeout( function() {
scope.$apply( function() {
if (Empty(scope[field])) {
scope[field] = master[field];
scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] =
master[form.fields[field].sourceModel + '_' + form.fields[field].sourceField];
}
});
}, 300);
},
callback: 'ModalReady'
});
CreateDialog({ SearchInit({
scope: scope, scope: scope,
buttons: buttons, set: list.name,
width: 600, list: list,
height: (instructions) ? 625 : 500, url: defaultUrl
minWidth: 500, });
title: hdr,
id: 'lookup-modal-dialog', PaginateInit({
onClose: function() { scope: scope,
setTimeout( function() { list: list,
scope.$apply( function() { url: defaultUrl,
if (Empty(scope[field])) { mode: 'lookup'
scope[field] = master[field]; });
scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] =
master[form.fields[field].sourceModel + '_' + form.fields[field].sourceField]; if (scope.lookupPostRefreshRemove) {
scope.lookupPostRefreshRemove();
}
scope.lookupPostRefreshRemove = scope.$on('PostRefresh', function () {
var fld, i;
for (fld in list.fields) {
if (list.fields[fld].type && list.fields[fld].type === 'date') {
//convert dates to our standard format
for (i = 0; i < scope[list.name].length; i++) {
scope[list.name][i][fld] = FormatDate(new Date(scope[list.name][i][fld]));
}
}
}
// List generator creates the list, resetting it and losing the previously selected value.
// If the selected value is in the current set, find it and mark selected.
if (!Empty(parent_scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField])) {
scope[list.name].forEach(function(elem) {
if (elem[form.fields[field].sourceField] ===
parent_scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField]) {
scope[field] = elem.id;
} }
}); });
}, 300);
},
callback: 'ModalReady'
});
SearchInit({
scope: scope,
set: list.name,
list: list,
url: defaultUrl
});
PaginateInit({
scope: scope,
list: list,
url: defaultUrl,
mode: 'lookup'
});
if (scope.lookupPostRefreshRemove) {
scope.lookupPostRefreshRemove();
}
scope.lookupPostRefreshRemove = scope.$on('PostRefresh', function () {
var fld, i;
for (fld in list.fields) {
if (list.fields[fld].type && list.fields[fld].type === 'date') {
//convert dates to our standard format
for (i = 0; i < scope[list.name].length; i++) {
scope[list.name][i][fld] = FormatDate(new Date(scope[list.name][i][fld]));
}
} }
}
// List generator creates the list, resetting it and losing the previously selected value. if (!Empty(scope[field])) {
// If the selected value is in the current set, find it and mark selected. scope['toggle_' + list.iterator](scope[field]);
if (!Empty(parent_scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField])) { }
scope[list.name].forEach(function(elem) {
if (elem[form.fields[field].sourceField] ===
parent_scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField]) {
scope[field] = elem.id;
}
});
} });
if (!Empty(scope[field])) { scope.search(list.iterator);
scope['toggle_' + list.iterator](scope[field]);
}
}); scope.selectAction = function () {
var i, found = false;
scope.search(list.iterator); for (i = 0; i < scope[list.name].length; i++) {
if (scope[list.name][i].checked === '1' || scope[list.name][i].checked===1) {
scope.selectAction = function () { found = true;
var i, found = false; parent_scope[field] = scope[list.name][i].id;
for (i = 0; i < scope[list.name].length; i++) { if (parent_scope[form.name + '_form'] && form.fields[field] && form.fields[field].sourceModel) {
if (scope[list.name][i].checked === '1' || scope[list.name][i].checked===1) { parent_scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] =
found = true; scope[list.name][i][form.fields[field].sourceField];
parent_scope[field] = scope[list.name][i].id; if (parent_scope[form.name + '_form'][form.fields[field].sourceModel + '_' + form.fields[field].sourceField]) {
if (parent_scope[form.name + '_form'] && form.fields[field] && form.fields[field].sourceModel) { parent_scope[form.name + '_form'][form.fields[field].sourceModel + '_' + form.fields[field].sourceField]
parent_scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] = .$setValidity('awlookup', true);
scope[list.name][i][form.fields[field].sourceField]; }
if (parent_scope[form.name + '_form'][form.fields[field].sourceModel + '_' + form.fields[field].sourceField]) { }
parent_scope[form.name + '_form'][form.fields[field].sourceModel + '_' + form.fields[field].sourceField] if (parent_scope[form.name + '_form']) {
.$setValidity('awlookup', true); parent_scope[form.name + '_form'].$setDirty();
} }
} }
if (parent_scope[form.name + '_form']) { }
parent_scope[form.name + '_form'].$setDirty(); if (found) {
// Selection made
$('#lookup-modal-dialog').dialog('close');
if (postAction) {
postAction();
}
if (callback) {
parent_scope.$emit(callback);
} }
} }
} };
if (found) {
// Selection made
$('#lookup-modal-dialog').dialog('close');
if (postAction) {
postAction();
}
if (callback) {
parent_scope.$emit(callback);
}
}
};
scope['toggle_' + list.iterator] = function (id) { scope['toggle_' + list.iterator] = function (id) {
var count = 0; var count = 0;
scope[list.name].forEach( function(row, i) { scope[list.name].forEach( function(row, i) {
if (row.id === id) { if (row.id === id) {
if (row.checked === '0') { if (row.checked === '0') {
scope[list.name][i].checked = '1'; scope[list.name][i].checked = '1';
scope[list.name][i].success_class = 'success'; scope[list.name][i].success_class = 'success';
} }
else { else {
scope[list.name][i].checked = '0';
scope[list.name][i].success_class = '';
}
} else {
scope[list.name][i].checked = '0'; scope[list.name][i].checked = '0';
scope[list.name][i].success_class = ''; scope[list.name][i].success_class = '';
} }
} else { });
scope[list.name][i].checked = '0'; // Check if any rows are checked
scope[list.name][i].success_class = ''; scope[list.name].forEach(function(row) {
if (row.checked === '1') {
count++;
}
});
if (count === 0) {
$('#lookup-save-button').attr('disabled','disabled');
} }
}); else {
// Check if any rows are checked $('#lookup-save-button').removeAttr('disabled');
scope[list.name].forEach(function(row) {
if (row.checked === '1') {
count++;
} }
}); };
if (count === 0) {
$('#lookup-save-button').attr('disabled','disabled');
}
else {
$('#lookup-save-button').removeAttr('disabled');
}
}; };
}; };
}; }]);
}]);

View File

@@ -9,156 +9,156 @@
* @name helpers.function:PaginationHelpers * @name helpers.function:PaginationHelpers
* @description pagination * @description pagination
*/ */
'use strict';
angular.module('PaginationHelpers', ['Utilities', 'RefreshHelper', 'RefreshRelatedHelper']) export default
angular.module('PaginationHelpers', ['Utilities', 'RefreshHelper', 'RefreshRelatedHelper'])
.factory('PageRangeSetup', ['Empty', .factory('PageRangeSetup', ['Empty',
function (Empty) { function (Empty) {
return function (params) { return function (params) {
var scope = params.scope, var scope = params.scope,
count = params.count, count = params.count,
next = params.next, next = params.next,
previous = params.previous, previous = params.previous,
iterator = params.iterator, iterator = params.iterator,
i, first, last; i, first, last;
scope[iterator + '_page'] = 1;
scope[iterator + '_num_pages'] = Math.ceil((count / scope[iterator + '_page_size']));
scope[iterator + '_num_pages'] = (scope[iterator + '_num_pages'] <= 0) ? 1 : scope[iterator + '_num_pages'];
scope[iterator + '_total_rows'] = count;
// Which page are we on?
if (Empty(next) && previous) {
// no next page, but there is a previous page
scope[iterator + '_page'] = parseInt(previous.match(/page=\d+/)[0].replace(/page=/, '')) + 1;
} else if (next && Empty(previous)) {
// next page available, but no previous page
scope[iterator + '_page'] = 1;
} else if (next && previous) {
// we're in between next and previous
scope[iterator + '_page'] = parseInt(previous.match(/page=\d+/)[0].replace(/page=/, '')) + 1;
}
// Calc the range of up to 10 pages to show
scope[iterator + '_page_range'] = [];
first = (scope[iterator + '_page'] > 5) ? scope[iterator + '_page'] - 5 : 1;
if (scope[iterator + '_page'] < 6) {
last = (10 <= scope[iterator + '_num_pages']) ? 10 : scope[iterator + '_num_pages'];
} else {
last = (scope[iterator + '_page'] + 4 < scope[iterator + '_num_pages']) ?
scope[iterator + '_page'] + 4 : scope[iterator + '_num_pages'];
}
for (i = first; i <= last; i++) {
scope[iterator + '_page_range'].push(i);
}
};
}
])
.factory('RelatedPaginateInit', ['RefreshRelated', '$cookieStore', 'Wait',
function (RefreshRelated, $cookieStore, Wait) {
return function (params) {
var scope = params.scope,
relatedSets = params.relatedSets,
pageSize = (params.pageSize) ? params.pageSize : 10,
key;
for (key in relatedSets) {
scope[relatedSets[key].iterator + '_url'] = relatedSets[key].url;
scope[relatedSets[key].iterator + '_page'] = 0;
scope[relatedSets[key].iterator + '_page_size'] = pageSize;
}
scope.getPage = function (page, set, iterator) {
var new_url = scope[iterator + '_url'].replace(/.page\=\d+/, ''),
connect = (/\/$/.test(new_url)) ? '?' : '&';
new_url += connect + 'page=' + page;
new_url += (scope[iterator + 'SearchParams']) ? '&' + scope[iterator + 'SearchParams'] +
'&page_size=' + scope[iterator + '_page_size'] : 'page_size=' + scope[iterator + 'PageSize'];
Wait('start');
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: new_url });
};
scope.pageIsActive = function (page, iterator) {
return (page === scope[iterator + '_page']) ? 'active' : '';
};
scope.changePageSize = function (set, iterator) {
// Called when a new page size is selected
scope[iterator + '_page'] = 1; scope[iterator + '_page'] = 1;
var url = scope[iterator + '_url']; scope[iterator + '_num_pages'] = Math.ceil((count / scope[iterator + '_page_size']));
scope[iterator + '_num_pages'] = (scope[iterator + '_num_pages'] <= 0) ? 1 : scope[iterator + '_num_pages'];
scope[iterator + '_total_rows'] = count;
// Using the session cookie, keep track of user rows per page selection // Which page are we on?
$cookieStore.put(iterator + '_page_size', scope[iterator + '_page_size']); if (Empty(next) && previous) {
// no next page, but there is a previous page
url = url.replace(/\/\?.*$/, '/'); scope[iterator + '_page'] = parseInt(previous.match(/page=\d+/)[0].replace(/page=/, '')) + 1;
url += (scope[iterator + 'SearchParams']) ? '?' + scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + '_page_size'] : } else if (next && Empty(previous)) {
'?page_size=' + scope[iterator + '_page_size']; // next page available, but no previous page
scope[iterator + '_page'] = 1;
RefreshRelated({ } else if (next && previous) {
scope: scope, // we're in between next and previous
set: set, scope[iterator + '_page'] = parseInt(previous.match(/page=\d+/)[0].replace(/page=/, '')) + 1;
iterator: iterator, }
url: url
}); // Calc the range of up to 10 pages to show
}; scope[iterator + '_page_range'] = [];
}; first = (scope[iterator + '_page'] > 5) ? scope[iterator + '_page'] - 5 : 1;
} if (scope[iterator + '_page'] < 6) {
]) last = (10 <= scope[iterator + '_num_pages']) ? 10 : scope[iterator + '_num_pages'];
} else {
last = (scope[iterator + '_page'] + 4 < scope[iterator + '_num_pages']) ?
.factory('PaginateInit', ['Refresh', '$cookieStore', 'Wait', scope[iterator + '_page'] + 4 : scope[iterator + '_num_pages'];
function (Refresh, $cookieStore, Wait) { }
return function (params) { for (i = first; i <= last; i++) {
scope[iterator + '_page_range'].push(i);
var scope = params.scope,
list = params.list,
iterator = (params.iterator) ? params.iterator : list.iterator,
pageSize = params.pageSize,
mode = (params.mode) ? params.mode : null;
scope[iterator + '_page'] = (params.page) ? params.page : 1;
scope[iterator + '_url'] = params.url;
scope[iterator + '_mode'] = mode;
if (pageSize) {
scope[iterator + '_page_size'] = params.pageSize;
} else if (mode === 'lookup') {
scope[iterator + '_page_size'] = 5;
} else {
scope[iterator + '_page_size'] = 20;
}
scope.getPage = function (page, set, iterator) {
var new_url = scope[iterator + '_url'].replace(/.page\=\d+/, ''),
connect = (/\/$/.test(new_url)) ? '?' : '&';
new_url += connect + 'page=' + page;
new_url += (scope[iterator + 'SearchParams']) ? '&' + scope[iterator + 'SearchParams'] +
'&page_size=' + scope[iterator + '_page_size'] : '&page_size=' + scope[iterator + 'PageSize'];
Wait('start');
Refresh({ scope: scope, set: set, iterator: iterator, url: new_url });
};
scope.pageIsActive = function (page, iterator) {
return (page === scope[iterator + '_page']) ? 'active' : '';
};
scope.changePageSize = function (set, iterator, spinner) {
// Called whenever a new page size is selected
scope[iterator + '_page'] = 1;
var new_url = scope[iterator + '_url'].replace(/\?page_size\=\d+/, ''),
connect = (/\/$/.test(new_url)) ? '?' : '&';
new_url += (scope[iterator + 'SearchParams']) ? connect + scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + '_page_size'] :
connect + 'page_size=' + scope[iterator + '_page_size'];
if (spinner === undefined || spinner === true) {
Wait('start');
} }
Refresh({ scope: scope, set: set, iterator: iterator, url: new_url });
}; };
}; }
} ])
]);
.factory('RelatedPaginateInit', ['RefreshRelated', '$cookieStore', 'Wait',
function (RefreshRelated, $cookieStore, Wait) {
return function (params) {
var scope = params.scope,
relatedSets = params.relatedSets,
pageSize = (params.pageSize) ? params.pageSize : 10,
key;
for (key in relatedSets) {
scope[relatedSets[key].iterator + '_url'] = relatedSets[key].url;
scope[relatedSets[key].iterator + '_page'] = 0;
scope[relatedSets[key].iterator + '_page_size'] = pageSize;
}
scope.getPage = function (page, set, iterator) {
var new_url = scope[iterator + '_url'].replace(/.page\=\d+/, ''),
connect = (/\/$/.test(new_url)) ? '?' : '&';
new_url += connect + 'page=' + page;
new_url += (scope[iterator + 'SearchParams']) ? '&' + scope[iterator + 'SearchParams'] +
'&page_size=' + scope[iterator + '_page_size'] : 'page_size=' + scope[iterator + 'PageSize'];
Wait('start');
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: new_url });
};
scope.pageIsActive = function (page, iterator) {
return (page === scope[iterator + '_page']) ? 'active' : '';
};
scope.changePageSize = function (set, iterator) {
// Called when a new page size is selected
scope[iterator + '_page'] = 1;
var url = scope[iterator + '_url'];
// Using the session cookie, keep track of user rows per page selection
$cookieStore.put(iterator + '_page_size', scope[iterator + '_page_size']);
url = url.replace(/\/\?.*$/, '/');
url += (scope[iterator + 'SearchParams']) ? '?' + scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + '_page_size'] :
'?page_size=' + scope[iterator + '_page_size'];
RefreshRelated({
scope: scope,
set: set,
iterator: iterator,
url: url
});
};
};
}
])
.factory('PaginateInit', ['Refresh', '$cookieStore', 'Wait',
function (Refresh, $cookieStore, Wait) {
return function (params) {
var scope = params.scope,
list = params.list,
iterator = (params.iterator) ? params.iterator : list.iterator,
pageSize = params.pageSize,
mode = (params.mode) ? params.mode : null;
scope[iterator + '_page'] = (params.page) ? params.page : 1;
scope[iterator + '_url'] = params.url;
scope[iterator + '_mode'] = mode;
if (pageSize) {
scope[iterator + '_page_size'] = params.pageSize;
} else if (mode === 'lookup') {
scope[iterator + '_page_size'] = 5;
} else {
scope[iterator + '_page_size'] = 20;
}
scope.getPage = function (page, set, iterator) {
var new_url = scope[iterator + '_url'].replace(/.page\=\d+/, ''),
connect = (/\/$/.test(new_url)) ? '?' : '&';
new_url += connect + 'page=' + page;
new_url += (scope[iterator + 'SearchParams']) ? '&' + scope[iterator + 'SearchParams'] +
'&page_size=' + scope[iterator + '_page_size'] : '&page_size=' + scope[iterator + 'PageSize'];
Wait('start');
Refresh({ scope: scope, set: set, iterator: iterator, url: new_url });
};
scope.pageIsActive = function (page, iterator) {
return (page === scope[iterator + '_page']) ? 'active' : '';
};
scope.changePageSize = function (set, iterator, spinner) {
// Called whenever a new page size is selected
scope[iterator + '_page'] = 1;
var new_url = scope[iterator + '_url'].replace(/\?page_size\=\d+/, ''),
connect = (/\/$/.test(new_url)) ? '?' : '&';
new_url += (scope[iterator + 'SearchParams']) ? connect + scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + '_page_size'] :
connect + 'page_size=' + scope[iterator + '_page_size'];
if (spinner === undefined || spinner === true) {
Wait('start');
}
Refresh({ scope: scope, set: set, iterator: iterator, url: new_url });
};
};
}
]);

View File

@@ -12,87 +12,87 @@
* *
*/ */
'use strict';
angular.module('ParseHelper', ['Utilities', 'AngularCodeMirrorModule']) export default
.factory('ParseTypeChange', ['Alert', 'AngularCodeMirror', function (Alert, AngularCodeMirror) { angular.module('ParseHelper', ['Utilities', 'AngularCodeMirrorModule'])
return function (params) { .factory('ParseTypeChange', ['Alert', 'AngularCodeMirror', function (Alert, AngularCodeMirror) {
return function (params) {
var scope = params.scope, var scope = params.scope,
field_id = params.field_id, field_id = params.field_id,
fld = (params.variable) ? params.variable : 'variables', fld = (params.variable) ? params.variable : 'variables',
pfld = (params.parse_variable) ? params.parse_variable : 'parseType', pfld = (params.parse_variable) ? params.parse_variable : 'parseType',
onReady = params.onReady, onReady = params.onReady,
onChange = params.onChange; onChange = params.onChange;
function removeField() { function removeField() {
//set our model to the last change in CodeMirror and then destroy CodeMirror //set our model to the last change in CodeMirror and then destroy CodeMirror
scope[fld] = scope.codeMirror.getValue(); scope[fld] = scope.codeMirror.getValue();
// codeMirror.destroy looks for anything with a CodeMirror class and destroys it, so if there are multiple codeMirror editor instances, it will delete them all, // codeMirror.destroy looks for anything with a CodeMirror class and destroys it, so if there are multiple codeMirror editor instances, it will delete them all,
// // which was the case if launching a job from the job template form. I had to add a check to see if there were multiple instances and only remove the second one found on the modal. // // which was the case if launching a job from the job template form. I had to add a check to see if there were multiple instances and only remove the second one found on the modal.
// if( $(".CodeMirror").length >1) { // if( $(".CodeMirror").length >1) {
// var self = scope.codeMirror; // var self = scope.codeMirror;
// $('.CodeMirror:eq(1)').empty().remove(); // $('.CodeMirror:eq(1)').empty().remove();
// if (self.element) { // if (self.element) {
// self.element.show(); // self.element.show();
// } // }
// } // }
// else // else
scope.codeMirror.destroy(); scope.codeMirror.destroy();
}
function createField(onChange, onReady) {
//hide the textarea and show a fresh CodeMirror with the current mode (json or yaml)
scope.codeMirror = AngularCodeMirror();
scope.codeMirror.addModes($AnsibleConfig.variable_edit_modes);
scope.codeMirror.showTextArea({ scope: scope, model: fld, element: field_id, mode: scope[pfld], onReady: onReady, onChange: onChange });
}
// Hide the textarea and show a CodeMirror editor
createField(onChange, onReady);
// Toggle displayed variable string between JSON and YAML
scope.parseTypeChange = function() {
var json_obj;
if (scope[pfld] === 'json') {
// converting yaml to json
try {
removeField();
json_obj = jsyaml.load(scope[fld]);
if ($.isEmptyObject(json_obj)) {
scope[fld] = "{}";
}
else {
scope[fld] = JSON.stringify(json_obj, null, " ");
}
createField();
}
catch (e) {
Alert('Parse Error', 'Failed to parse valid YAML. ' + e.message);
setTimeout( function() { scope.$apply( function() { scope[pfld] = 'yaml'; createField(); }); }, 500);
}
} }
else {
// convert json to yaml function createField(onChange, onReady) {
try { //hide the textarea and show a fresh CodeMirror with the current mode (json or yaml)
removeField(); scope.codeMirror = AngularCodeMirror();
json_obj = JSON.parse(scope[fld]); scope.codeMirror.addModes($AnsibleConfig.variable_edit_modes);
if ($.isEmptyObject(json_obj)) { scope.codeMirror.showTextArea({ scope: scope, model: fld, element: field_id, mode: scope[pfld], onReady: onReady, onChange: onChange });
scope[fld] = '---';
}
else {
scope[fld] = jsyaml.safeDump(json_obj);
}
createField();
}
catch (e) {
Alert('Parse Error', 'Failed to parse valid JSON. ' + e.message);
setTimeout( function() { scope.$apply( function() { scope[pfld] = 'json'; createField(); }); }, 500 );
}
} }
// Hide the textarea and show a CodeMirror editor
createField(onChange, onReady);
// Toggle displayed variable string between JSON and YAML
scope.parseTypeChange = function() {
var json_obj;
if (scope[pfld] === 'json') {
// converting yaml to json
try {
removeField();
json_obj = jsyaml.load(scope[fld]);
if ($.isEmptyObject(json_obj)) {
scope[fld] = "{}";
}
else {
scope[fld] = JSON.stringify(json_obj, null, " ");
}
createField();
}
catch (e) {
Alert('Parse Error', 'Failed to parse valid YAML. ' + e.message);
setTimeout( function() { scope.$apply( function() { scope[pfld] = 'yaml'; createField(); }); }, 500);
}
}
else {
// convert json to yaml
try {
removeField();
json_obj = JSON.parse(scope[fld]);
if ($.isEmptyObject(json_obj)) {
scope[fld] = '---';
}
else {
scope[fld] = jsyaml.safeDump(json_obj);
}
createField();
}
catch (e) {
Alert('Parse Error', 'Failed to parse valid JSON. ' + e.message);
setTimeout( function() { scope.$apply( function() { scope[pfld] = 'json'; createField(); }); }, 500 );
}
}
};
}; };
}; }
} ]);
]);

View File

@@ -10,45 +10,47 @@
* Functions shared amongst Permission related controllers * Functions shared amongst Permission related controllers
* *
*/ */
angular.module('PermissionsHelper', [])
// Handle category change event export default
.factory('PermissionCategoryChange', ['$sce', angular.module('PermissionsHelper', [])
function ($sce) {
return function (params) {
var scope = params.scope,
reset = params.reset,
html;
if (scope.category === 'Inventory') { // Handle category change event
scope.projectrequired = false; .factory('PermissionCategoryChange', ['$sce',
html = "<dl>\n" + function ($sce) {
"<dt>Read</dt>\n" + return function (params) {
"<dd>Only allow the user or team to view the inventory.</dd>\n" + var scope = params.scope,
"<dt>Write</dt>\n" + reset = params.reset,
"<dd>Allow the user or team to modify hosts and groups contained in the inventory, add new hosts and groups, and perform inventory sync operations.\n" + html;
"<dt>Admin</dt>\n" +
"<dd>Allow the user or team full access to the inventory. This includes reading, writing, deletion of the inventory and inventory sync operations.</dd>\n" +
"</dl>\n";
scope.permissionTypeHelp = $sce.trustAsHtml(html);
} else {
scope.projectrequired = true;
html = "<dl>\n" +
"<dt>Create</dt>\n" +
"<dd>Allow the user or team to create job templates. This implies that they have the Run and Check permissions.</dd>\n" +
"<dt>Run</dt>\n" +
"<dd>Allow the user or team to run a job template from the project against the inventory. In Run mode modules will " +
"be executed, and changes to the inventory will occur.</dd>\n" +
"<dt>Check</dt>\n" +
"<dd>Only allow the user or team to run the project against the inventory as a dry-run operation. In Check mode, module operations " +
"will only be simulated. No changes will occur.</dd>\n" +
"</dl>\n";
scope.permissionTypeHelp = $sce.trustAsHtml(html);
}
if (reset) { if (scope.category === 'Inventory') {
scope.permission_type = (scope.category === 'Inventory') ? 'read' : 'run'; //default to the first option scope.projectrequired = false;
} html = "<dl>\n" +
}; "<dt>Read</dt>\n" +
} "<dd>Only allow the user or team to view the inventory.</dd>\n" +
]); "<dt>Write</dt>\n" +
"<dd>Allow the user or team to modify hosts and groups contained in the inventory, add new hosts and groups, and perform inventory sync operations.\n" +
"<dt>Admin</dt>\n" +
"<dd>Allow the user or team full access to the inventory. This includes reading, writing, deletion of the inventory and inventory sync operations.</dd>\n" +
"</dl>\n";
scope.permissionTypeHelp = $sce.trustAsHtml(html);
} else {
scope.projectrequired = true;
html = "<dl>\n" +
"<dt>Create</dt>\n" +
"<dd>Allow the user or team to create job templates. This implies that they have the Run and Check permissions.</dd>\n" +
"<dt>Run</dt>\n" +
"<dd>Allow the user or team to run a job template from the project against the inventory. In Run mode modules will " +
"be executed, and changes to the inventory will occur.</dd>\n" +
"<dt>Check</dt>\n" +
"<dd>Only allow the user or team to run the project against the inventory as a dry-run operation. In Check mode, module operations " +
"will only be simulated. No changes will occur.</dd>\n" +
"</dl>\n";
scope.permissionTypeHelp = $sce.trustAsHtml(html);
}
if (reset) {
scope.permission_type = (scope.category === 'Inventory') ? 'read' : 'run'; //default to the first option
}
};
}
]);

View File

@@ -12,74 +12,76 @@
* scope.base_dir (readonly field). * scope.base_dir (readonly field).
* *
*/ */
angular.module('ProjectPathHelper', ['RestServices', 'Utilities'])
.factory('GetProjectPath', ['Alert', 'Rest', 'GetBasePath', 'ProcessErrors',
function (Alert, Rest, GetBasePath, ProcessErrors) {
return function (params) {
var scope = params.scope, export default
master = params.master; angular.module('ProjectPathHelper', ['RestServices', 'Utilities'])
.factory('GetProjectPath', ['Alert', 'Rest', 'GetBasePath', 'ProcessErrors',
function (Alert, Rest, GetBasePath, ProcessErrors) {
return function (params) {
function arraySort(data) { var scope = params.scope,
//Sort nodes by name master = params.master;
var i, j, names = [],
newData = []; function arraySort(data) {
for (i = 0; i < data.length; i++) { //Sort nodes by name
names.push(data[i].value); var i, j, names = [],
} newData = [];
names.sort();
for (j = 0; j < names.length; j++) {
for (i = 0; i < data.length; i++) { for (i = 0; i < data.length; i++) {
if (data[i].value === names[j]) { names.push(data[i].value);
newData.push(data[i]);
}
} }
} names.sort();
return newData; for (j = 0; j < names.length; j++) {
} for (i = 0; i < data.length; i++) {
if (data[i].value === names[j]) {
scope.showMissingPlaybooksAlert = false; newData.push(data[i]);
Rest.setUrl(GetBasePath('config'));
Rest.get()
.success(function (data) {
var opts = [], i;
for (i = 0; i < data.project_local_paths.length; i++) {
opts.push({
label: data.project_local_paths[i],
value: data.project_local_paths[i]
});
}
if (scope.local_path) {
// List only includes paths not assigned to projects, so add the
// path assigned to the current project.
opts.push({
label: scope.local_path,
value: scope.local_path
});
}
scope.project_local_paths = arraySort(opts);
if (scope.local_path) {
for (i = 0; scope.project_local_paths.length; i++) {
if (scope.project_local_paths[i].value === scope.local_path) {
scope.local_path = scope.project_local_paths[i];
break;
} }
} }
} }
scope.base_dir = data.project_base_dir; return newData;
master.local_path = scope.local_path; }
master.base_dir = scope.base_dir; // Keep in master object so that it doesn't get
// wiped out on form reset. scope.showMissingPlaybooksAlert = false;
if (opts.length === 0) {
// trigger display of alert block when scm_type == manual Rest.setUrl(GetBasePath('config'));
scope.showMissingPlaybooksAlert = true; Rest.get()
} .success(function (data) {
}) var opts = [], i;
.error(function (data, status) { for (i = 0; i < data.project_local_paths.length; i++) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!', opts.push({
msg: 'Failed to access API config. GET status: ' + status }); label: data.project_local_paths[i],
}); value: data.project_local_paths[i]
}; });
} }
]); if (scope.local_path) {
// List only includes paths not assigned to projects, so add the
// path assigned to the current project.
opts.push({
label: scope.local_path,
value: scope.local_path
});
}
scope.project_local_paths = arraySort(opts);
if (scope.local_path) {
for (i = 0; scope.project_local_paths.length; i++) {
if (scope.project_local_paths[i].value === scope.local_path) {
scope.local_path = scope.project_local_paths[i];
break;
}
}
}
scope.base_dir = data.project_base_dir;
master.local_path = scope.local_path;
master.base_dir = scope.base_dir; // Keep in master object so that it doesn't get
// wiped out on form reset.
if (opts.length === 0) {
// trigger display of alert block when scm_type == manual
scope.showMissingPlaybooksAlert = true;
}
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to access API config. GET status: ' + status });
});
};
}
]);

View File

@@ -13,64 +13,64 @@
* *
*/ */
'use strict';
angular.module('ProjectsHelper', ['RestServices', 'Utilities', 'ProjectStatusDefinition', 'ProjectFormDefinition']) export default
angular.module('ProjectsHelper', ['RestServices', 'Utilities', 'ProjectStatusDefinition', 'ProjectFormDefinition'])
.factory('GetProjectIcon', [ function() { .factory('GetProjectIcon', [ function() {
return function(status) { return function(status) {
var result = ''; var result = '';
switch (status) { switch (status) {
case 'n/a': case 'n/a':
case 'ok': case 'ok':
case 'never updated': case 'never updated':
result = 'none'; result = 'none';
break; break;
case 'pending': case 'pending':
case 'waiting': case 'waiting':
case 'new': case 'new':
result = 'none'; result = 'none';
break; break;
case 'updating': case 'updating':
case 'running': case 'running':
result = 'running'; result = 'running';
break; break;
case 'successful': case 'successful':
result = 'success'; result = 'success';
break; break;
case 'failed': case 'failed':
case 'missing': case 'missing':
result = 'error'; result = 'error';
} }
return result; return result;
}; };
}]) }])
.factory('GetProjectToolTip', [ function() { .factory('GetProjectToolTip', [ function() {
return function(status) { return function(status) {
var result = ''; var result = '';
switch (status) { switch (status) {
case 'n/a': case 'n/a':
case 'ok': case 'ok':
case 'never updated': case 'never updated':
result = 'No SCM updates have run for this project'; result = 'No SCM updates have run for this project';
break; break;
case 'pending': case 'pending':
case 'waiting': case 'waiting':
case 'new': case 'new':
result = 'Queued. Click for details'; result = 'Queued. Click for details';
break; break;
case 'updating': case 'updating':
case 'running': case 'running':
result = 'Running! Click for details'; result = 'Running! Click for details';
break; break;
case 'successful': case 'successful':
result = 'Success! Click for details'; result = 'Success! Click for details';
break; break;
case 'failed': case 'failed':
case 'missing': case 'missing':
result = 'Failed. Click for details'; result = 'Failed. Click for details';
} }
return result; return result;
}; };
}]); }]);

File diff suppressed because it is too large Load Diff

View File

@@ -14,164 +14,164 @@
* }) * })
*/ */
'use strict';
angular.module('SelectionHelper', ['Utilities', 'RestServices']) export default
angular.module('SelectionHelper', ['Utilities', 'RestServices'])
.factory('SelectionInit', ['Rest', 'Alert', 'ProcessErrors', 'ReturnToCaller', 'Wait', .factory('SelectionInit', ['Rest', 'Alert', 'ProcessErrors', 'ReturnToCaller', 'Wait',
function (Rest, Alert, ProcessErrors, ReturnToCaller, Wait) { function (Rest, Alert, ProcessErrors, ReturnToCaller, Wait) {
return function (params) { return function (params) {
var scope = params.scope, var scope = params.scope,
list = params.list, list = params.list,
target_url = params.url, target_url = params.url,
returnToCaller = params.returnToCaller, returnToCaller = params.returnToCaller,
selected; selected;
if (params.selected !== undefined) { if (params.selected !== undefined) {
selected = params.selected; selected = params.selected;
} else {
selected = []; //array of selected row IDs
}
scope.formModalActionDisabled = true;
scope.disableSelectBtn = true;
// toggle row selection
scope['toggle_' + list.iterator] = function (id, ischeckbox) {
var i, j, found;
for (i = 0; i < scope[list.name].length; i++) {
if (scope[list.name][i].id === id) {
if ((scope[list.name][i].checked === "0" && !ischeckbox) || (scope[list.name][i].checked === "0" && ischeckbox)) {
// select the row
scope[list.name][i].checked = '1';
scope[list.name][i].success_class = 'success';
// add selected object to the array
found = false;
for (j = 0; j < selected.length; j++) {
if (selected[j].id === id) {
found = true;
break;
}
}
if (!found) {
selected.push(scope[list.name][i]);
}
} else {
// unselect the row
scope[list.name][i].checked = '0';
scope[list.name][i].success_class = '';
// remove selected object from the array
for (j = 0; j < selected.length; j++) {
if (selected[j].id === id) {
selected.splice(j, 1);
break;
}
}
}
}
}
if (selected.length > 0) {
scope.formModalActionDisabled = false;
scope.disableSelectBtn = false;
} else { } else {
scope.formModalActionDisabled = true; selected = []; //array of selected row IDs
scope.disableSelectBtn = true;
} }
};
// Add the selections
scope.finishSelection = function () {
Rest.setUrl(target_url);
var queue = [], j;
scope.formModalActionDisabled = true; scope.formModalActionDisabled = true;
scope.disableSelectBtn = true; scope.disableSelectBtn = true;
Wait('start'); // toggle row selection
scope['toggle_' + list.iterator] = function (id, ischeckbox) {
var i, j, found;
for (i = 0; i < scope[list.name].length; i++) {
if (scope[list.name][i].id === id) {
if ((scope[list.name][i].checked === "0" && !ischeckbox) || (scope[list.name][i].checked === "0" && ischeckbox)) {
// select the row
scope[list.name][i].checked = '1';
scope[list.name][i].success_class = 'success';
// add selected object to the array
found = false;
for (j = 0; j < selected.length; j++) {
if (selected[j].id === id) {
found = true;
break;
}
}
if (!found) {
selected.push(scope[list.name][i]);
}
} else {
// unselect the row
scope[list.name][i].checked = '0';
scope[list.name][i].success_class = '';
function finished() { // remove selected object from the array
selected = []; for (j = 0; j < selected.length; j++) {
if (returnToCaller !== undefined) { if (selected[j].id === id) {
ReturnToCaller(returnToCaller); selected.splice(j, 1);
} else { break;
$('#form-modal').modal('hide'); }
scope.$emit('modalClosed'); }
}
}
function postIt(data) {
Rest.post(data)
.success(function (data, status) {
queue.push({ result: 'success', data: data, status: status });
scope.$emit('callFinished');
})
.error(function (data, status, headers) {
queue.push({ result: 'error', data: data, status: status, headers: headers });
scope.$emit('callFinished');
});
}
if (scope.callFinishedRemove) {
scope.callFinishedRemove();
}
scope.callFinishedRemove = scope.$on('callFinished', function () {
// We call the API for each selected item. We need to hang out until all the api
// calls are finished.
var i, errors=0;
if (queue.length === selected.length) {
Wait('stop');
for (i = 0; i < queue.length; i++) {
if (queue[i].result === 'error') {
ProcessErrors(scope, queue[i].data, queue[i].status, null, { hdr: 'POST Failure',
msg: 'Failed to add ' + list.iterator + '. POST returned status: ' + queue[i].status });
errors++;
} }
} }
if (errors === 0) { }
finished(); if (selected.length > 0) {
scope.formModalActionDisabled = false;
scope.disableSelectBtn = false;
} else {
scope.formModalActionDisabled = true;
scope.disableSelectBtn = true;
}
};
// Add the selections
scope.finishSelection = function () {
Rest.setUrl(target_url);
var queue = [], j;
scope.formModalActionDisabled = true;
scope.disableSelectBtn = true;
Wait('start');
function finished() {
selected = [];
if (returnToCaller !== undefined) {
ReturnToCaller(returnToCaller);
} else {
$('#form-modal').modal('hide');
scope.$emit('modalClosed');
}
}
function postIt(data) {
Rest.post(data)
.success(function (data, status) {
queue.push({ result: 'success', data: data, status: status });
scope.$emit('callFinished');
})
.error(function (data, status, headers) {
queue.push({ result: 'error', data: data, status: status, headers: headers });
scope.$emit('callFinished');
});
}
if (scope.callFinishedRemove) {
scope.callFinishedRemove();
}
scope.callFinishedRemove = scope.$on('callFinished', function () {
// We call the API for each selected item. We need to hang out until all the api
// calls are finished.
var i, errors=0;
if (queue.length === selected.length) {
Wait('stop');
for (i = 0; i < queue.length; i++) {
if (queue[i].result === 'error') {
ProcessErrors(scope, queue[i].data, queue[i].status, null, { hdr: 'POST Failure',
msg: 'Failed to add ' + list.iterator + '. POST returned status: ' + queue[i].status });
errors++;
}
}
if (errors === 0) {
finished();
}
}
});
if (selected.length > 0) {
for (j = 0; j < selected.length; j++) {
postIt(selected[j]);
}
} else {
finished();
}
};
scope.formModalAction = scope.finishSelection;
// Initialize our data set after a refresh (page change or search)
if (scope.SelectPostRefreshRemove) {
scope.SelectPostRefreshRemove();
}
scope.SelectPostRefreshRemove = scope.$on('PostRefresh', function () {
var i, j, found;
if (scope[list.name]) {
for (i = 0; i < scope[list.name].length; i++) {
found = false;
for (j = 0; j < selected.length; j++) {
if (selected[j].id === scope[list.name][i].id) {
found = true;
break;
}
}
if (found) {
scope[list.name][i].checked = '1';
scope[list.name][i].success_class = 'success';
} else {
scope[list.name][i].checked = '0';
scope[list.name][i].success_class = '';
}
} }
} }
}); });
if (selected.length > 0) {
for (j = 0; j < selected.length; j++) {
postIt(selected[j]);
}
} else {
finished();
}
}; };
}
scope.formModalAction = scope.finishSelection; ]);
// Initialize our data set after a refresh (page change or search)
if (scope.SelectPostRefreshRemove) {
scope.SelectPostRefreshRemove();
}
scope.SelectPostRefreshRemove = scope.$on('PostRefresh', function () {
var i, j, found;
if (scope[list.name]) {
for (i = 0; i < scope[list.name].length; i++) {
found = false;
for (j = 0; j < selected.length; j++) {
if (selected[j].id === scope[list.name][i].id) {
found = true;
break;
}
}
if (found) {
scope[list.name][i].checked = '1';
scope[list.name][i].success_class = 'success';
} else {
scope[list.name][i].checked = '0';
scope[list.name][i].success_class = '';
}
}
}
});
};
}
]);

View File

@@ -11,35 +11,35 @@
* *
*/ */
'use strict';
angular.module('SocketHelper', ['Utilities', 'FFSocketHelpDefinition', 'SafariSocketHelpDefinition' , 'ChromeSocketHelpDefinition']) export default
angular.module('SocketHelper', ['Utilities', 'FFSocketHelpDefinition', 'SafariSocketHelpDefinition' , 'ChromeSocketHelpDefinition'])
.factory('ShowSocketHelp', ['$location', '$rootScope', 'FFSocketHelp', 'SafariSocketHelp', 'ChromeSocketHelp', 'HelpDialog', .factory('ShowSocketHelp', ['$location', '$rootScope', 'FFSocketHelp', 'SafariSocketHelp', 'ChromeSocketHelp', 'HelpDialog',
function($location, $rootScope, FFSocketHelp, SafariSocketHelp, ChromeSocketHelp, HelpDialog) { function($location, $rootScope, FFSocketHelp, SafariSocketHelp, ChromeSocketHelp, HelpDialog) {
return function() { return function() {
var scope = $rootScope.$new(); var scope = $rootScope.$new();
scope.socketPort = $AnsibleConfig.websocket_port; scope.socketPort = $AnsibleConfig.websocket_port;
scope.socketURL = 'https://' + $location.host() + ':' + scope.socketPort + '/'; scope.socketURL = 'https://' + $location.host() + ':' + scope.socketPort + '/';
if ($rootScope.browser === "FF") { if ($rootScope.browser === "FF") {
scope.browserName = "Firefox"; scope.browserName = "Firefox";
HelpDialog({ defn: FFSocketHelp, scope: scope }); HelpDialog({ defn: FFSocketHelp, scope: scope });
}
else if ($rootScope.browser === "SAFARI") {
scope.browserName = "Safari";
HelpDialog({ defn: SafariSocketHelp, scope: scope });
}
else {
if ($rootScope.browser === "MSIE") {
scope.browserName = "Internet Explorer";
} }
else if ($rootScope.browser === "CHROME") { else if ($rootScope.browser === "SAFARI") {
scope.browserName = "Chrome"; scope.browserName = "Safari";
HelpDialog({ defn: SafariSocketHelp, scope: scope });
} }
else if ($rootScope.browser === "OPERA") { else {
scope.browserName = "Opera"; if ($rootScope.browser === "MSIE") {
scope.browserName = "Internet Explorer";
}
else if ($rootScope.browser === "CHROME") {
scope.browserName = "Chrome";
}
else if ($rootScope.browser === "OPERA") {
scope.browserName = "Opera";
}
HelpDialog({ defn: ChromeSocketHelp, scope: scope });
} }
HelpDialog({ defn: ChromeSocketHelp, scope: scope }); };
} }]);
};
}]);

View File

@@ -11,8 +11,7 @@
* *
*/ */
'use strict'; export default
angular.module('SurveyHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ModalDialog' , angular.module('SurveyHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ModalDialog' ,
'GeneratorHelpers']) 'GeneratorHelpers'])
@@ -877,4 +876,3 @@ angular.module('SurveyHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper',
}; };
}]); }]);

View File

@@ -10,34 +10,34 @@
* *
*/ */
'use strict';
angular.module('UserHelper', ['UserFormDefinition']) export default
.factory('ResetForm', ['UserForm', angular.module('UserHelper', ['UserFormDefinition'])
function (UserForm) { .factory('ResetForm', ['UserForm',
return function () { function (UserForm) {
// Restore form to default conditions. Run before applying LDAP configuration. return function () {
// LDAP may manage some or all of these fields in which case the user cannot // Restore form to default conditions. Run before applying LDAP configuration.
// make changes to their values in AWX. // LDAP may manage some or all of these fields in which case the user cannot
// make changes to their values in AWX.
UserForm.fields.first_name.readonly = false; UserForm.fields.first_name.readonly = false;
UserForm.fields.first_name.editRequired = true; UserForm.fields.first_name.editRequired = true;
UserForm.fields.last_name.readonly = false; UserForm.fields.last_name.readonly = false;
UserForm.fields.last_name.editRequired = true; UserForm.fields.last_name.editRequired = true;
UserForm.fields.email.readonly = false; UserForm.fields.email.readonly = false;
UserForm.fields.email.editRequired = true; UserForm.fields.email.editRequired = true;
UserForm.fields.organization.awRequiredWhen = { UserForm.fields.organization.awRequiredWhen = {
variable: "orgrequired", variable: "orgrequired",
init: true init: true
};
UserForm.fields.organization.readonly = false;
UserForm.fields.username.awRequiredWhen = {
variable: "not_ldap_user",
init: true
};
UserForm.fields.username.readonly = false;
UserForm.fields.password.editRequired = false;
UserForm.fields.password.addRrequired = true;
}; };
UserForm.fields.organization.readonly = false; }
UserForm.fields.username.awRequiredWhen = { ]);
variable: "not_ldap_user",
init: true
};
UserForm.fields.username.readonly = false;
UserForm.fields.password.editRequired = false;
UserForm.fields.password.addRrequired = true;
};
}
]);

View File

@@ -10,8 +10,7 @@
* *
*/ */
'use strict'; export default
angular.module('VariablesHelper', ['Utilities']) angular.module('VariablesHelper', ['Utilities'])
/** /**

View File

@@ -10,86 +10,86 @@
* @name helpers.function:api-defaults * @name helpers.function:api-defaults
* @description this could use more discussion * @description this could use more discussion
*/ */
'use strict';
angular.module('APIDefaults', ['RestServices', 'Utilities']) export default
.factory('GetAPIDefaults', ['Alert', 'Rest', '$rootScope', angular.module('APIDefaults', ['RestServices', 'Utilities'])
function (Alert, Rest, $rootScope) { .factory('GetAPIDefaults', ['Alert', 'Rest', '$rootScope',
return function (key) { function (Alert, Rest, $rootScope) {
return function (key) {
//Reload a related collection on pagination or search change //Reload a related collection on pagination or search change
var result = {}, cnt = 0, url; var result = {}, cnt = 0, url;
function lookup(key) { function lookup(key) {
var id, result = {}; var id, result = {};
for (id in $rootScope.apiDefaults) { for (id in $rootScope.apiDefaults) {
if (id === key || id.iterator === key) { if (id === key || id.iterator === key) {
result[id] = $rootScope.apiDefaults[id]; result[id] = $rootScope.apiDefaults[id];
break; break;
}
}
return result;
}
function wait() {
if ($.isEmptyObject(result) && cnt < 5) {
cnt++;
setTimeout(1000, wait());
} else if (result.status === 'success') {
return lookup(key);
} }
} }
return result;
}
function wait() { if ($rootScope.apiDefaults === null || $rootScope.apiDefaults === undefined) {
if ($.isEmptyObject(result) && cnt < 5) { url = '/api/v1/';
cnt++; Rest.setUrl(url);
setTimeout(1000, wait()); Rest.get()
} else if (result.status === 'success') { .success(function (data) {
var id, defaults = data;
for (id in defaults) {
switch (id) {
case 'organizations':
defaults[id].iterator = 'organization';
break;
case 'jobs':
defaults[id].iterator = 'job';
break;
case 'users':
defaults[id].iterator = 'user';
break;
case 'teams':
defaults[id].iterator = 'team';
break;
case 'hosts':
defaults[id].iterator = 'host';
break;
case 'groups':
defaults[id].iterator = 'group';
break;
case 'projects':
defaults[id].iterator = 'project';
break;
case 'inventories':
defaults[id].iterator = 'inventory';
break;
}
}
$rootScope.apiDefaults = defaults;
result = {
status: 'success'
};
})
.error(function (data, status) {
result = {
status: 'error',
msg: 'Call to ' + url + ' failed. GET returned status: ' + status
};
});
return wait();
} else {
return lookup(key); return lookup(key);
} }
} };
}
if ($rootScope.apiDefaults === null || $rootScope.apiDefaults === undefined) { ]);
url = '/api/v1/';
Rest.setUrl(url);
Rest.get()
.success(function (data) {
var id, defaults = data;
for (id in defaults) {
switch (id) {
case 'organizations':
defaults[id].iterator = 'organization';
break;
case 'jobs':
defaults[id].iterator = 'job';
break;
case 'users':
defaults[id].iterator = 'user';
break;
case 'teams':
defaults[id].iterator = 'team';
break;
case 'hosts':
defaults[id].iterator = 'host';
break;
case 'groups':
defaults[id].iterator = 'group';
break;
case 'projects':
defaults[id].iterator = 'project';
break;
case 'inventories':
defaults[id].iterator = 'inventory';
break;
}
}
$rootScope.apiDefaults = defaults;
result = {
status: 'success'
};
})
.error(function (data, status) {
result = {
status: 'error',
msg: 'Call to ' + url + ' failed. GET returned status: ' + status
};
});
return wait();
} else {
return lookup(key);
}
};
}
]);

View File

@@ -10,388 +10,388 @@
* for the menu piece. The routine for building the menu is in InventoriesEdit controller * for the menu piece. The routine for building the menu is in InventoriesEdit controller
* (controllers/Inventories.js) * (controllers/Inventories.js)
*/ */
'use strict';
angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationListDefinition', 'ListGenerator', 'AuthService', export default
'InventoryHelper', 'InventoryFormDefinition', 'ParseHelper', 'SearchHelper', 'VariablesHelper', angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationListDefinition', 'ListGenerator', 'AuthService',
]) 'InventoryHelper', 'InventoryFormDefinition', 'ParseHelper', 'SearchHelper', 'VariablesHelper',
])
.factory('GetGroupContainerHeight', [ function() { .factory('GetGroupContainerHeight', [ function() {
return function() { return function() {
/*console.log('window height: ' + $(window).height()); /*console.log('window height: ' + $(window).height());
console.log('main-menu: ' + $('.main-menu').outerHeight()); console.log('main-menu: ' + $('.main-menu').outerHeight());
console.log('main_tabs: ' + $('#main_tabs').outerHeight()); console.log('main_tabs: ' + $('#main_tabs').outerHeight());
console.log('breadcrumbs: ' + $('#breadcrumbs').outerHeight()); console.log('breadcrumbs: ' + $('#breadcrumbs').outerHeight());
console.log('footer: ' + $('.site-footer').outerHeight()); console.log('footer: ' + $('.site-footer').outerHeight());
console.log('group-breadcrumbs: ' + $('.group-breadcrumbs').outerHeight()); console.log('group-breadcrumbs: ' + $('.group-breadcrumbs').outerHeight());
console.log('searchwidget: ' + $('#groups-container #search-widget-container').outerHeight()); console.log('searchwidget: ' + $('#groups-container #search-widget-container').outerHeight());
console.log('group table head: ' + $('#groups_table thead').height()); console.log('group table head: ' + $('#groups_table thead').height());
console.log('subtotal: ' + ( $(window).height() - $('.main-menu').outerHeight() - $('#main_tabs').outerHeight() - $('#breadcrumbs').outerHeight() - console.log('subtotal: ' + ( $(window).height() - $('.main-menu').outerHeight() - $('#main_tabs').outerHeight() - $('#breadcrumbs').outerHeight() -
$('.site-footer').outerHeight() - $('.group-breadcrumbs').outerHeight() - $('#groups-container #search-widget-container').outerHeight() - $('.site-footer').outerHeight() - $('.group-breadcrumbs').outerHeight() - $('#groups-container #search-widget-container').outerHeight() -
$('#groups_table thead').height() )); $('#groups_table thead').height() ));
*/ */
var height = $(window).height() - $('#main-menu-container .navbar').outerHeight() - $('#breadcrumbs').outerHeight() - var height = $(window).height() - $('#main-menu-container .navbar').outerHeight() - $('#breadcrumbs').outerHeight() -
$('.site-footer').outerHeight() - $('.group-breadcrumbs').outerHeight() - $('#groups-container #search-widget-container').outerHeight() - $('.site-footer').outerHeight() - $('.group-breadcrumbs').outerHeight() - $('#groups-container #search-widget-container').outerHeight() -
$('#groups_table thead').height() - 90; $('#groups_table thead').height() - 90;
height = (height < 600) ? 600 : height; height = (height < 600) ? 600 : height;
return height; return height;
};
}])
.factory('GetHostContainerRows', [ function() {
return function() {
var height, rows;
height = $('#hosts-container .list-well').height() - $('#hosts-constainer .list-well .row').height() - $('#hosts_table thead').height();
rows = Math.floor(height / 30) - 2;
rows = (rows < 20) ? 20 : rows;
return rows;
};
}])
.factory('GetGroupContainerRows', [ function() {
return function() {
var height, rows;
height = $('#groups-container .list-table-container').height();
rows = Math.floor(height / 31) - 2;
rows = (rows < 20) ? 20 : rows;
return rows;
};
}])
.factory('SetContainerHeights', [ 'GetGroupContainerHeight', 'GetHostContainerRows', function(GetGroupContainerHeight, GetHostContainerRows) {
return function(params) {
var group_scope = params.group_scope,
host_scope = params.host_scope,
reloadHosts = (params.reloadHosts) ? true : false,
height, rows;
$('#groups-container .list-table-container').height('auto');
$('#hosts-container .list-well').height('auto');
$('#hosts-container .list-table-container').height('auto');
setTimeout(function() {
if ($(window).width() > 1210) {
height = GetGroupContainerHeight();
$('#groups-container .list-table-container').height(height);
$('#hosts-container .list-table-container').height(height);
setTimeout(function() { $('#hosts-container .list-well').height( $('#groups-container .list-well').outerHeight()); }, 500);
}
if (reloadHosts) {
// we need ro recalc the the page size
if ($(window).width() > 1210) {
rows = GetHostContainerRows();
host_scope.host_page_size = rows;
group_scope.group_page_size = rows;
}
else {
// on small screens we go back to the default
host_scope.host_page_size = 20;
group_scope.group_page_size = 20;
}
host_scope.changePageSize('hosts', 'host');
group_scope.changePageSize('groups', 'group');
}
}, 100);
};
}])
.factory('WatchInventoryWindowResize', ['ApplyEllipsis', 'SetContainerHeights',
function (ApplyEllipsis, SetContainerHeights) {
return function (params) {
// Call to set or restore window resize
var group_scope = params.group_scope,
host_scope = params.host_scope;
$(window).off("resize");
$(window).resize(_.debounce(function() {
ApplyEllipsis('#groups_table .group-name a');
ApplyEllipsis('#hosts_table .host-name a');
SetContainerHeights({
group_scope: group_scope,
host_scope: host_scope,
reloadHosts: true
});
}, 500));
}; };
} }])
])
.factory('SaveInventory', ['InventoryForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList', .factory('GetHostContainerRows', [ function() {
'GetBasePath', 'ParseTypeChange', 'Wait', 'ToJSON', return function() {
function (InventoryForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, Wait, var height, rows;
ToJSON) { height = $('#hosts-container .list-well').height() - $('#hosts-constainer .list-well .row').height() - $('#hosts_table thead').height();
return function (params) { rows = Math.floor(height / 30) - 2;
rows = (rows < 20) ? 20 : rows;
return rows;
};
}])
// Save inventory property modifications .factory('GetGroupContainerRows', [ function() {
return function() {
var height, rows;
height = $('#groups-container .list-table-container').height();
rows = Math.floor(height / 31) - 2;
rows = (rows < 20) ? 20 : rows;
return rows;
};
}])
var scope = params.scope, .factory('SetContainerHeights', [ 'GetGroupContainerHeight', 'GetHostContainerRows', function(GetGroupContainerHeight, GetHostContainerRows) {
form = InventoryForm, return function(params) {
defaultUrl = GetBasePath('inventory'), var group_scope = params.group_scope,
fld, json_data, data; host_scope = params.host_scope,
reloadHosts = (params.reloadHosts) ? true : false,
height, rows;
Wait('start'); $('#groups-container .list-table-container').height('auto');
$('#hosts-container .list-well').height('auto');
$('#hosts-container .list-table-container').height('auto');
// Make sure we have valid variable data setTimeout(function() {
json_data = ToJSON(scope.parseType, scope.variables); if ($(window).width() > 1210) {
height = GetGroupContainerHeight();
$('#groups-container .list-table-container').height(height);
$('#hosts-container .list-table-container').height(height);
setTimeout(function() { $('#hosts-container .list-well').height( $('#groups-container .list-well').outerHeight()); }, 500);
}
data = {}; if (reloadHosts) {
for (fld in form.fields) { // we need ro recalc the the page size
if (fld !== 'variables') { if ($(window).width() > 1210) {
if (form.fields[fld].realName) { rows = GetHostContainerRows();
data[form.fields[fld].realName] = scope[fld]; host_scope.host_page_size = rows;
} else { group_scope.group_page_size = rows;
data[fld] = scope[fld]; }
else {
// on small screens we go back to the default
host_scope.host_page_size = 20;
group_scope.group_page_size = 20;
}
host_scope.changePageSize('hosts', 'host');
group_scope.changePageSize('groups', 'group');
}
}, 100);
};
}])
.factory('WatchInventoryWindowResize', ['ApplyEllipsis', 'SetContainerHeights',
function (ApplyEllipsis, SetContainerHeights) {
return function (params) {
// Call to set or restore window resize
var group_scope = params.group_scope,
host_scope = params.host_scope;
$(window).off("resize");
$(window).resize(_.debounce(function() {
ApplyEllipsis('#groups_table .group-name a');
ApplyEllipsis('#hosts_table .host-name a');
SetContainerHeights({
group_scope: group_scope,
host_scope: host_scope,
reloadHosts: true
});
}, 500));
};
}
])
.factory('SaveInventory', ['InventoryForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList',
'GetBasePath', 'ParseTypeChange', 'Wait', 'ToJSON',
function (InventoryForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, Wait,
ToJSON) {
return function (params) {
// Save inventory property modifications
var scope = params.scope,
form = InventoryForm,
defaultUrl = GetBasePath('inventory'),
fld, json_data, data;
Wait('start');
// Make sure we have valid variable data
json_data = ToJSON(scope.parseType, scope.variables);
data = {};
for (fld in form.fields) {
if (fld !== 'variables') {
if (form.fields[fld].realName) {
data[form.fields[fld].realName] = scope[fld];
} else {
data[fld] = scope[fld];
}
} }
} }
}
if (scope.removeUpdateInventoryVariables) { if (scope.removeUpdateInventoryVariables) {
scope.removeUpdateInventoryVariables(); scope.removeUpdateInventoryVariables();
} }
scope.removeUpdateInventoryVariables = scope.$on('UpdateInventoryVariables', function(e, data) { scope.removeUpdateInventoryVariables = scope.$on('UpdateInventoryVariables', function(e, data) {
Rest.setUrl(data.related.variable_data); Rest.setUrl(data.related.variable_data);
Rest.put(json_data) Rest.put(json_data)
.success(function () { .success(function () {
Wait('stop'); Wait('stop');
scope.$emit('InventorySaved'); scope.$emit('InventorySaved');
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to update inventory varaibles. PUT returned status: ' + status
});
});
});
Rest.setUrl(defaultUrl + scope.inventory_id + '/');
Rest.put(data)
.success(function (data) {
if (scope.variables) {
scope.$emit('UpdateInventoryVariables', data);
} else {
scope.$emit('InventorySaved');
}
}) })
.error(function (data, status) { .error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!', ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to update inventory varaibles. PUT returned status: ' + status msg: 'Failed to update inventory. PUT returned status: ' + status });
});
}); });
}); };
}
])
Rest.setUrl(defaultUrl + scope.inventory_id + '/');
Rest.put(data) .factory('EditInventoryProperties', ['InventoryForm', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList',
.success(function (data) { 'GetBasePath', 'ParseTypeChange', 'SaveInventory', 'Wait', 'Store', 'SearchInit', 'ParseVariableString', 'CreateDialog', 'TextareaResize',
if (scope.variables) { function (InventoryForm, GenerateForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, SaveInventory,
scope.$emit('UpdateInventoryVariables', data); Wait, Store, SearchInit, ParseVariableString, CreateDialog, TextareaResize) {
} else { return function (params) {
scope.$emit('InventorySaved');
} var parent_scope = params.scope,
}) inventory_id = params.inventory_id,
.error(function (data, status) { generator = GenerateForm,
ProcessErrors(scope, data, status, form, { hdr: 'Error!', form = InventoryForm,
msg: 'Failed to update inventory. PUT returned status: ' + status }); master = {},
//PreviousSearchParams = Store('CurrentSearchParams'),
buttons,
scope = parent_scope.$new();
form.well = false;
generator.inject(form, {
mode: 'edit',
showButtons: false,
showActions: false,
id: 'inventory-edit-modal-dialog',
breadCrumbs: false,
related: false,
scope: scope
}); });
};
}
])
/* Reset form properties. Otherwise it screws up future requests of the Inventories detail page */
form.well = true;
.factory('EditInventoryProperties', ['InventoryForm', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList', buttons = [{
'GetBasePath', 'ParseTypeChange', 'SaveInventory', 'Wait', 'Store', 'SearchInit', 'ParseVariableString', 'CreateDialog', 'TextareaResize', label: "Cancel",
function (InventoryForm, GenerateForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, SaveInventory, onClick: function() {
Wait, Store, SearchInit, ParseVariableString, CreateDialog, TextareaResize) { scope.cancelModal();
return function (params) { },
icon: "fa-times",
"class": "btn btn-default",
"id": "inventory-edit-cancel-button"
},{
label: "Save",
onClick: function() {
scope.saveModal();
},
icon: "fa-check",
"class": "btn btn-primary",
"id": "inventory-edit-save-button"
}];
var parent_scope = params.scope, CreateDialog({
inventory_id = params.inventory_id, scope: scope,
generator = GenerateForm, buttons: buttons,
form = InventoryForm, width: 675,
master = {}, height: 750,
//PreviousSearchParams = Store('CurrentSearchParams'), minWidth: 400,
buttons, title: 'Inventory Properties',
scope = parent_scope.$new(); id: 'inventory-edit-modal-dialog',
clonseOnEscape: false,
form.well = false; onClose: function() {
Wait('stop');
generator.inject(form, {
mode: 'edit',
showButtons: false,
showActions: false,
id: 'inventory-edit-modal-dialog',
breadCrumbs: false,
related: false,
scope: scope
});
/* Reset form properties. Otherwise it screws up future requests of the Inventories detail page */
form.well = true;
buttons = [{
label: "Cancel",
onClick: function() {
scope.cancelModal();
},
icon: "fa-times",
"class": "btn btn-default",
"id": "inventory-edit-cancel-button"
},{
label: "Save",
onClick: function() {
scope.saveModal();
},
icon: "fa-check",
"class": "btn btn-primary",
"id": "inventory-edit-save-button"
}];
CreateDialog({
scope: scope,
buttons: buttons,
width: 675,
height: 750,
minWidth: 400,
title: 'Inventory Properties',
id: 'inventory-edit-modal-dialog',
clonseOnEscape: false,
onClose: function() {
Wait('stop');
scope.codeMirror.destroy();
$('#inventory-edit-modal-dialog').empty();
},
onResizeStop: function() {
TextareaResize({
scope: scope,
textareaId: 'inventory_variables',
modalId: 'inventory-edit-modal-dialog',
formId: 'inventory_form'
});
},
beforeDestroy: function() {
if (scope.codeMirror) {
scope.codeMirror.destroy(); scope.codeMirror.destroy();
} $('#inventory-edit-modal-dialog').empty();
$('#inventory-edit-modal-dialog').empty(); },
}, onResizeStop: function() {
onOpen: function() {
$('#inventory_name').focus();
setTimeout(function() {
TextareaResize({ TextareaResize({
scope: scope, scope: scope,
textareaId: 'inventory_variables', textareaId: 'inventory_variables',
modalId: 'inventory-edit-modal-dialog', modalId: 'inventory-edit-modal-dialog',
formId: 'inventory_form', formId: 'inventory_form'
parse: true
}); });
}, 300); },
}, beforeDestroy: function() {
callback: 'InventoryEditDialogReady' if (scope.codeMirror) {
}); scope.codeMirror.destroy();
scope.parseType = 'yaml';
if (scope.removeInventoryPropertiesLoaded) {
scope.removeInventoryPropertiesLoaded();
}
scope.removeInventoryPropertiesLoaded = scope.$on('inventoryPropertiesLoaded', function() {
Wait('stop');
$('#inventory-edit-modal-dialog').dialog('open');
});
scope.formModalActionLabel = 'Save';
scope.formModalCancelShow = true;
scope.formModalInfo = false;
scope.formModalHeader = 'Inventory Properties';
Wait('start');
Rest.setUrl(GetBasePath('inventory') + inventory_id + '/');
Rest.get()
.success(function (data) {
var fld;
for (fld in form.fields) {
if (fld === 'variables') {
scope.variables = ParseVariableString(data.variables);
master.variables = scope.variables;
} else if (fld === 'inventory_name') {
scope[fld] = data.name;
master[fld] = scope[fld];
} else if (fld === 'inventory_description') {
scope[fld] = data.description;
master[fld] = scope[fld];
} else if (data[fld]) {
scope[fld] = data[fld];
master[fld] = scope[fld];
} }
if (form.fields[fld].sourceModel && data.summary_fields && $('#inventory-edit-modal-dialog').empty();
data.summary_fields[form.fields[fld].sourceModel]) { },
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = onOpen: function() {
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; $('#inventory_name').focus();
master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = setTimeout(function() {
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; TextareaResize({
} scope: scope,
} textareaId: 'inventory_variables',
modalId: 'inventory-edit-modal-dialog',
LookUpInit({ formId: 'inventory_form',
scope: scope, parse: true
form: form, });
current_item: scope.organization, }, 300);
list: OrganizationList, },
field: 'organization', callback: 'InventoryEditDialogReady'
input_type: 'radio'
});
scope.$emit('inventoryPropertiesLoaded');
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status });
}); });
if (scope.removeInventorySaved) { scope.parseType = 'yaml';
scope.removeInventorySaved();
}
scope.removeInventorySaved = scope.$on('InventorySaved', function () {
//$('#form-modal').modal('hide');
// Restore prior search state
//if (scope.searchCleanp) {
// scope.searchCleanup();
//}
//SearchInit({
// scope: parent_scope,
// set: PreviousSearchParams.set,
// list: PreviousSearchParams.list,
// url: PreviousSearchParams.defaultUrl,
// iterator: PreviousSearchParams.iterator,
// sort_order: PreviousSearchParams.sort_order,
// setWidgets: false
//});
//parent_scope.$emit('RefreshInventories');
try {
$('#inventory-edit-modal-dialog').dialog('close');
}
catch(err) {
// ignore
}
parent_scope.$emit('RefreshInventories');
scope.$destroy();
});
scope.cancelModal = function () { if (scope.removeInventoryPropertiesLoaded) {
// Restore prior search state scope.removeInventoryPropertiesLoaded();
/*if (scope.searchCleanp) {
scope.searchCleanup();
} }
SearchInit({ scope.removeInventoryPropertiesLoaded = scope.$on('inventoryPropertiesLoaded', function() {
scope: parent_scope, Wait('stop');
set: PreviousSearchParams.set, $('#inventory-edit-modal-dialog').dialog('open');
list: PreviousSearchParams.list, });
url: PreviousSearchParams.defaultUrl,
iterator: PreviousSearchParams.iterator, scope.formModalActionLabel = 'Save';
sort_order: PreviousSearchParams.sort_order, scope.formModalCancelShow = true;
setWidgets: false scope.formModalInfo = false;
});*/ scope.formModalHeader = 'Inventory Properties';
try {
$('#inventory-edit-modal-dialog').dialog('close'); Wait('start');
Rest.setUrl(GetBasePath('inventory') + inventory_id + '/');
Rest.get()
.success(function (data) {
var fld;
for (fld in form.fields) {
if (fld === 'variables') {
scope.variables = ParseVariableString(data.variables);
master.variables = scope.variables;
} else if (fld === 'inventory_name') {
scope[fld] = data.name;
master[fld] = scope[fld];
} else if (fld === 'inventory_description') {
scope[fld] = data.description;
master[fld] = scope[fld];
} 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];
}
}
LookUpInit({
scope: scope,
form: form,
current_item: scope.organization,
list: OrganizationList,
field: 'organization',
input_type: 'radio'
});
scope.$emit('inventoryPropertiesLoaded');
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status });
});
if (scope.removeInventorySaved) {
scope.removeInventorySaved();
} }
catch(err) { scope.removeInventorySaved = scope.$on('InventorySaved', function () {
// ignore //$('#form-modal').modal('hide');
} // Restore prior search state
scope.$destroy(); //if (scope.searchCleanp) {
// scope.searchCleanup();
//}
//SearchInit({
// scope: parent_scope,
// set: PreviousSearchParams.set,
// list: PreviousSearchParams.list,
// url: PreviousSearchParams.defaultUrl,
// iterator: PreviousSearchParams.iterator,
// sort_order: PreviousSearchParams.sort_order,
// setWidgets: false
//});
//parent_scope.$emit('RefreshInventories');
try {
$('#inventory-edit-modal-dialog').dialog('close');
}
catch(err) {
// ignore
}
parent_scope.$emit('RefreshInventories');
scope.$destroy();
});
scope.cancelModal = function () {
// Restore prior search state
/*if (scope.searchCleanp) {
scope.searchCleanup();
}
SearchInit({
scope: parent_scope,
set: PreviousSearchParams.set,
list: PreviousSearchParams.list,
url: PreviousSearchParams.defaultUrl,
iterator: PreviousSearchParams.iterator,
sort_order: PreviousSearchParams.sort_order,
setWidgets: false
});*/
try {
$('#inventory-edit-modal-dialog').dialog('close');
}
catch(err) {
// ignore
}
scope.$destroy();
};
scope.saveModal = function () {
scope.inventory_id = inventory_id;
SaveInventory({ scope: scope, parent_scope: parent_scope });
};
}; };
}
scope.saveModal = function () { ]);
scope.inventory_id = inventory_id;
SaveInventory({ scope: scope, parent_scope: parent_scope });
};
};
}
]);

View File

@@ -13,34 +13,34 @@
* discussion * discussion
*/ */
'use strict';
angular.module('md5Helper', ['RestServices', 'Utilities', 'angular-md5']) export default
.factory('md5Setup', ['md5', function (md5) { angular.module('md5Helper', ['RestServices', 'Utilities', 'angular-md5'])
return function (params) { .factory('md5Setup', ['md5', function (md5) {
return function (params) {
var scope = params.scope, var scope = params.scope,
master = params.master, master = params.master,
check_field = params.check_field, check_field = params.check_field,
default_val = params.default_val; default_val = params.default_val;
scope[check_field] = default_val; scope[check_field] = default_val;
master[check_field] = default_val; master[check_field] = default_val;
scope.genMD5 = function (fld) { scope.genMD5 = function (fld) {
var now = new Date(); var now = new Date();
scope[fld] = md5.createHash('AnsibleWorks' + now.getTime()); scope[fld] = md5.createHash('AnsibleWorks' + now.getTime());
scope.$emit('NewMD5Generated'); scope.$emit('NewMD5Generated');
};
scope.toggleCallback = function (fld) {
if (scope.allow_callbacks === 'false') {
scope[fld] = '';
}
};
scope.selectAll = function (fld) {
$('input[name="' + fld + '"]').focus().select();
};
}; };
}]);
scope.toggleCallback = function (fld) {
if (scope.allow_callbacks === 'false') {
scope[fld] = '';
}
};
scope.selectAll = function (fld) {
$('input[name="' + fld + '"]').focus().select();
};
};
}]);

View File

@@ -19,38 +19,38 @@
* *
*/ */
'use strict';
angular.module('RefreshRelatedHelper', ['RestServices', 'Utilities', 'PaginationHelpers']) export default
.factory('RefreshRelated', ['ProcessErrors', 'Rest', 'Wait', 'PageRangeSetup', angular.module('RefreshRelatedHelper', ['RestServices', 'Utilities', 'PaginationHelpers'])
function (ProcessErrors, Rest, Wait, PageRangeSetup) { .factory('RefreshRelated', ['ProcessErrors', 'Rest', 'Wait', 'PageRangeSetup',
return function (params) { function (ProcessErrors, Rest, Wait, PageRangeSetup) {
return function (params) {
var scope = params.scope, var scope = params.scope,
set = params.set, set = params.set,
iterator = params.iterator, iterator = params.iterator,
url = params.url; url = params.url;
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success(function (data) { .success(function (data) {
PageRangeSetup({ PageRangeSetup({
scope: scope, scope: scope,
count: data.count, count: data.count,
next: data.next, next: data.next,
previous: data.previous, previous: data.previous,
iterator: iterator iterator: iterator
});
scope[set] = data.results;
scope[iterator + 'Loading'] = false;
scope[iterator + 'HoldInput'] = false;
Wait('stop');
scope.$emit('related' + set);
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve ' + set + '. GET returned status: ' + status });
}); });
scope[set] = data.results; };
scope[iterator + 'Loading'] = false; }
scope[iterator + 'HoldInput'] = false; ]);
Wait('stop');
scope.$emit('related' + set);
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve ' + set + '. GET returned status: ' + status });
});
};
}
]);

View File

@@ -18,50 +18,50 @@
* *
*/ */
'use strict';
angular.module('RefreshHelper', ['RestServices', 'Utilities', 'PaginationHelpers']) export default
.factory('Refresh', ['ProcessErrors', 'Rest', 'Wait', 'Empty', 'PageRangeSetup', angular.module('RefreshHelper', ['RestServices', 'Utilities', 'PaginationHelpers'])
function (ProcessErrors, Rest, Wait, Empty, PageRangeSetup) { .factory('Refresh', ['ProcessErrors', 'Rest', 'Wait', 'Empty', 'PageRangeSetup',
return function (params) { function (ProcessErrors, Rest, Wait, Empty, PageRangeSetup) {
return function (params) {
var scope = params.scope, var scope = params.scope,
set = params.set, set = params.set,
iterator = params.iterator, iterator = params.iterator,
url = params.url, url = params.url,
deferWaitStop = params.deferWaitStop; deferWaitStop = params.deferWaitStop;
scope.current_url = url; scope.current_url = url;
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success(function (data) { .success(function (data) {
var i, modifier; var i, modifier;
PageRangeSetup({ PageRangeSetup({
scope: scope, scope: scope,
count: data.count, count: data.count,
next: data.next, next: data.next,
previous: data.previous, previous: data.previous,
iterator: iterator iterator: iterator
});
for (i = 1; i <= 3; i++) {
modifier = (i === 1) ? '' : i;
scope[iterator + 'HoldInput' + modifier] = false;
}
scope[set] = data.results;
scope[iterator + 'Loading'] = false;
scope[iterator + 'HidePaginator'] = false;
if (!deferWaitStop) {
Wait('stop');
}
scope.$emit('PostRefresh', set);
})
.error(function (data, status) {
scope[iterator + 'HoldInput'] = false;
ProcessErrors(scope, data, status, null, {
hdr: 'Error!',
msg: 'Failed to retrieve ' + set + '. GET returned status: ' + status
});
}); });
for (i = 1; i <= 3; i++) { };
modifier = (i === 1) ? '' : i; }
scope[iterator + 'HoldInput' + modifier] = false; ]);
}
scope[set] = data.results;
scope[iterator + 'Loading'] = false;
scope[iterator + 'HidePaginator'] = false;
if (!deferWaitStop) {
Wait('stop');
}
scope.$emit('PostRefresh', set);
})
.error(function (data, status) {
scope[iterator + 'HoldInput'] = false;
ProcessErrors(scope, data, status, null, {
hdr: 'Error!',
msg: 'Failed to retrieve ' + set + '. GET returned status: ' + status
});
});
};
}
]);

View File

@@ -19,260 +19,260 @@
* *
*/ */
'use strict';
angular.module('RelatedSearchHelper', ['RestServices', 'Utilities', 'RefreshRelatedHelper']) export default
.factory('RelatedSearchInit', ['$timeout', 'Alert', 'Rest', 'RefreshRelated', 'Wait', 'Empty', angular.module('RelatedSearchHelper', ['RestServices', 'Utilities', 'RefreshRelatedHelper'])
function ($timeout, Alert, Rest, RefreshRelated, Wait, Empty) { .factory('RelatedSearchInit', ['$timeout', 'Alert', 'Rest', 'RefreshRelated', 'Wait', 'Empty',
return function (params) { function ($timeout, Alert, Rest, RefreshRelated, Wait, Empty) {
return function (params) {
var scope = params.scope, var scope = params.scope,
relatedSets = params.relatedSets, relatedSets = params.relatedSets,
form = params.form, f; form = params.form, f;
// add 'selected' class to the selected li element // add 'selected' class to the selected li element
function setSelectedItem(iterator, label) { function setSelectedItem(iterator, label) {
$('#' + iterator + 'SearchDropdown' + ' li').each(function() { $('#' + iterator + 'SearchDropdown' + ' li').each(function() {
$(this).removeClass('selected'); $(this).removeClass('selected');
var link = $(this).find('a'); var link = $(this).find('a');
if (label === link.text()) { if (label === link.text()) {
$(this).addClass('selected'); $(this).addClass('selected');
}
});
}
// Set default values
function setDefaults(inIterator) {
var iterator, f, fld, set;
for (set in form.related) {
if (form.related[set].type !== 'tree' && (inIterator === undefined || inIterator === form.related[set].iterator)) {
iterator = form.related[set].iterator;
for (fld in form.related[set].fields) {
if (form.related[set].fields[fld].key) {
if (form.related[set].fields[fld].searchable === undefined || form.related[set].fields[fld].searchable === true) {
scope[iterator + 'SearchField'] = fld;
scope[iterator + 'SearchFieldLabel'] = form.related[set].fields[fld].label;
}
break;
}
} }
});
}
if (Empty(scope[iterator + 'SearchField'])) { // Set default values
// A field marked as key may not be 'searchable'. Find the first searchable field. function setDefaults(inIterator) {
var iterator, f, fld, set;
for (set in form.related) {
if (form.related[set].type !== 'tree' && (inIterator === undefined || inIterator === form.related[set].iterator)) {
iterator = form.related[set].iterator;
for (fld in form.related[set].fields) { for (fld in form.related[set].fields) {
if (form.related[set].fields[fld].searchable === undefined || form.related[set].fields[fld].searchable === true) { if (form.related[set].fields[fld].key) {
scope[iterator + 'SearchField'] = fld; if (form.related[set].fields[fld].searchable === undefined || form.related[set].fields[fld].searchable === true) {
scope[iterator + 'SearchFieldLabel'] = form.related[set].fields[fld].label; scope[iterator + 'SearchField'] = fld;
scope[iterator + 'SearchFieldLabel'] = form.related[set].fields[fld].label;
}
break; break;
} }
} }
}
scope[iterator + 'SortOrder'] = null; if (Empty(scope[iterator + 'SearchField'])) {
scope[iterator + 'SearchType'] = 'icontains'; // A field marked as key may not be 'searchable'. Find the first searchable field.
scope[iterator + 'SearchTypeLabel'] = 'Contains'; for (fld in form.related[set].fields) {
scope[iterator + 'SearchValue'] = null; if (form.related[set].fields[fld].searchable === undefined || form.related[set].fields[fld].searchable === true) {
scope[iterator + 'SelectShow'] = false; scope[iterator + 'SearchField'] = fld;
//scope[iterator + 'HideSearchType'] = false; scope[iterator + 'SearchFieldLabel'] = form.related[set].fields[fld].label;
scope[iterator + 'ShowStartBtn'] = true; break;
scope[iterator + 'HideAllStartBtn'] = false; }
f = scope[iterator + 'SearchField'];
if (form.related[set].fields[f].searchType &&
(form.related[set].fields[f].searchType === 'boolean' || form.related[set].fields[f].searchType === 'select')) {
scope[iterator + 'SelectShow'] = true;
scope[iterator + 'SearchSelectOpts'] = form.fields[f].searchOptions;
}
if (form.related[set].fields[f].searchType && form.related[set].fields[f].searchType === 'gtzero') {
scope[iterator + "InputHide"] = true;
}
setSelectedItem(iterator, scope[iterator + 'SearchFieldLabel']);
}
}
}
setDefaults();
scope.resetSearch = function (iterator) {
setDefaults(iterator);
scope.search(iterator);
};
// Functions to handle search widget changes
scope.setSearchField = function (iterator, fld, label) {
var f, related;
for (related in form.related) {
if (form.related[related].iterator === iterator) {
f = form.related[related].fields[fld];
}
}
scope[iterator + 'SearchFieldLabel'] = label;
scope[iterator + 'SearchField'] = fld;
scope[iterator + 'SearchValue'] = '';
scope[iterator + 'SelectShow'] = false;
//scope[iterator + 'HideSearchType'] = false;
scope[iterator + 'InputHide'] = false;
scope[iterator + 'ShowStartBtn'] = true;
if (f.searchType !== undefined && f.searchType === 'gtzero') {
scope[iterator + "InputHide"] = true;
scope[iterator + 'ShowStartBtn'] = false;
}
if (f.searchType !== undefined && (f.searchType === 'boolean' || f.searchType === 'select')) {
scope[iterator + 'SelectShow'] = true;
scope[iterator + 'SearchSelectOpts'] = f.searchOptions;
}
if (f.searchType !== undefined && f.searchType === 'int') {
//scope[iterator + 'HideSearchType'] = true;
scope[iterator + 'SearchType'] = 'int';
}
setSelectedItem(iterator, label);
scope.search(iterator);
};
scope.setSearchType = function (model, type, label) {
scope[model + 'SearchTypeLabel'] = label;
scope[model + 'SearchType'] = type;
scope.search(model);
};
scope.startSearch = function (e, iterator) {
// If use clicks enter while on input field, start the search
if (e.keyCode === 13) {
scope.search(iterator);
}
};
scope.search = function (iterator) {
//scope[iterator + 'SearchSpin'] = true;
Wait('start');
scope[iterator + 'Loading'] = false;
scope[iterator + 'HoldInput'] = true;
if (scope[iterator + 'SearchValue']) {
// User typed a value in input field
scope[iterator + 'ShowStartBtn'] = false;
}
if (iterator === 'host') {
if (scope.hostSearchField === 'has_active_failures') {
if (scope.hostSearchSelectValue && scope.hostSearchSelectValue.value === 1) {
scope.hostFailureFilter = true;
} else {
scope.hostFailureFilter = false;
}
}
}
var fld, key, set, url, sort_order;
for (key in relatedSets) {
if (relatedSets[key].iterator === iterator) {
set = key;
url = relatedSets[key].url;
for (fld in form.related[key].fields) {
if (form.related[key].fields[fld].key) {
if (form.related[key].fields[fld].desc) {
sort_order = '-' + fld;
} else {
sort_order = fld;
} }
} }
scope[iterator + 'SortOrder'] = null;
scope[iterator + 'SearchType'] = 'icontains';
scope[iterator + 'SearchTypeLabel'] = 'Contains';
scope[iterator + 'SearchValue'] = null;
scope[iterator + 'SelectShow'] = false;
//scope[iterator + 'HideSearchType'] = false;
scope[iterator + 'ShowStartBtn'] = true;
scope[iterator + 'HideAllStartBtn'] = false;
f = scope[iterator + 'SearchField'];
if (form.related[set].fields[f].searchType &&
(form.related[set].fields[f].searchType === 'boolean' || form.related[set].fields[f].searchType === 'select')) {
scope[iterator + 'SelectShow'] = true;
scope[iterator + 'SearchSelectOpts'] = form.fields[f].searchOptions;
}
if (form.related[set].fields[f].searchType && form.related[set].fields[f].searchType === 'gtzero') {
scope[iterator + "InputHide"] = true;
}
setSelectedItem(iterator, scope[iterator + 'SearchFieldLabel']);
} }
break;
} }
} }
sort_order = (scope[iterator + 'SortOrder'] === null) ? sort_order : scope[iterator + 'SortOrder']; setDefaults();
f = form.related[set].fields[scope[iterator + 'SearchField']];
if ((scope[iterator + 'SelectShow'] === false && !Empty(scope[iterator + 'SearchValue'])) || scope.resetSearch = function (iterator) {
(scope[iterator + 'SelectShow'] && scope[iterator + 'SearchSelectValue']) || setDefaults(iterator);
(f.searchType && f.searchType === 'gtzero')) { scope.search(iterator);
if (f.sourceModel) { };
// handle fields whose source is a related model e.g. inventories.organization
scope[iterator + 'SearchParams'] = f.sourceModel + '__' + f.sourceField + '__'; // Functions to handle search widget changes
} else if (f.searchField) { scope.setSearchField = function (iterator, fld, label) {
scope[iterator + 'SearchParams'] = f.searchField + '__';
} else { var f, related;
scope[iterator + 'SearchParams'] = scope[iterator + 'SearchField'] + '__';
for (related in form.related) {
if (form.related[related].iterator === iterator) {
f = form.related[related].fields[fld];
}
} }
if (f.searchType && (f.searchType === 'int' || f.searchType === 'boolean')) { scope[iterator + 'SearchFieldLabel'] = label;
scope[iterator + 'SearchParams'] += 'int='; scope[iterator + 'SearchField'] = fld;
} else if (f.searchType && f.searchType === 'gtzero') { scope[iterator + 'SearchValue'] = '';
scope[iterator + 'SearchParams'] += 'gt=0'; scope[iterator + 'SelectShow'] = false;
} else { //scope[iterator + 'HideSearchType'] = false;
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchType'] + '='; scope[iterator + 'InputHide'] = false;
scope[iterator + 'ShowStartBtn'] = true;
if (f.searchType !== undefined && f.searchType === 'gtzero') {
scope[iterator + "InputHide"] = true;
scope[iterator + 'ShowStartBtn'] = false;
}
if (f.searchType !== undefined && (f.searchType === 'boolean' || f.searchType === 'select')) {
scope[iterator + 'SelectShow'] = true;
scope[iterator + 'SearchSelectOpts'] = f.searchOptions;
} }
if (f.searchType && (f.searchType === 'boolean' || f.searchType === 'select')) { if (f.searchType !== undefined && f.searchType === 'int') {
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchSelectValue'].value; //scope[iterator + 'HideSearchType'] = true;
} else if (f.searchType === undefined || f.searchType === 'gtzero') { scope[iterator + 'SearchType'] = 'int';
scope[iterator + 'SearchParams'] += encodeURI(scope[iterator + 'SearchValue']);
} }
scope[iterator + 'SearchParams'] += (sort_order) ? '&order_by=' + encodeURI(sort_order) : '';
} else {
scope[iterator + 'SearchParams'] = (sort_order) ? 'order_by=' + encodeURI(sort_order) : '';
}
scope[iterator + '_page'] = 1;
url += (url.match(/\/$/)) ? '?' : '&';
url += scope[iterator + 'SearchParams'];
url += (scope[iterator + '_page_size']) ? '&page_size=' + scope[iterator + '_page_size'] : "";
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: url });
};
setSelectedItem(iterator, label);
scope.sort = function (iterator, fld) { scope.search(iterator);
var sort_order, icon, direction, set;
// reset sort icons back to 'icon-sort' on all columns };
// except the one clicked
$('.' + iterator + ' .list-header').each(function () { scope.setSearchType = function (model, type, label) {
if ($(this).attr('id') !== iterator + '-' + fld + '-header') { scope[model + 'SearchTypeLabel'] = label;
var icon = $(this).find('i'); scope[model + 'SearchType'] = type;
icon.attr('class', 'fa fa-sort'); scope.search(model);
};
scope.startSearch = function (e, iterator) {
// If use clicks enter while on input field, start the search
if (e.keyCode === 13) {
scope.search(iterator);
} }
}); };
// Toggle the icon for the clicked column scope.search = function (iterator) {
// and set the sort direction //scope[iterator + 'SearchSpin'] = true;
icon = $('#' + iterator + '-' + fld + '-header i'); Wait('start');
direction = ''; scope[iterator + 'Loading'] = false;
if (icon.hasClass('fa-sort')) { scope[iterator + 'HoldInput'] = true;
icon.removeClass('fa-sort');
icon.addClass('fa-sort-up');
} else if (icon.hasClass('fa-sort-up')) {
icon.removeClass('fa-sort-up');
icon.addClass('fa-sort-down');
direction = '-';
} else if (icon.hasClass('fa-sort-down')) {
icon.removeClass('fa-sort-down');
icon.addClass('fa-sort-up');
}
// Set the sorder order value and call the API to refresh the list with the new order if (scope[iterator + 'SearchValue']) {
for (set in form.related) { // User typed a value in input field
if (form.related[set].iterator === iterator) { scope[iterator + 'ShowStartBtn'] = false;
if (form.related[set].fields[fld].sourceModel) { }
sort_order = direction + form.related[set].fields[fld].sourceModel + '__' +
form.related[set].fields[fld].sourceField; if (iterator === 'host') {
if (scope.hostSearchField === 'has_active_failures') {
if (scope.hostSearchSelectValue && scope.hostSearchSelectValue.value === 1) {
scope.hostFailureFilter = true;
} else {
scope.hostFailureFilter = false;
}
}
}
var fld, key, set, url, sort_order;
for (key in relatedSets) {
if (relatedSets[key].iterator === iterator) {
set = key;
url = relatedSets[key].url;
for (fld in form.related[key].fields) {
if (form.related[key].fields[fld].key) {
if (form.related[key].fields[fld].desc) {
sort_order = '-' + fld;
} else {
sort_order = fld;
}
}
}
break;
}
}
sort_order = (scope[iterator + 'SortOrder'] === null) ? sort_order : scope[iterator + 'SortOrder'];
f = form.related[set].fields[scope[iterator + 'SearchField']];
if ((scope[iterator + 'SelectShow'] === false && !Empty(scope[iterator + 'SearchValue'])) ||
(scope[iterator + 'SelectShow'] && scope[iterator + 'SearchSelectValue']) ||
(f.searchType && f.searchType === 'gtzero')) {
if (f.sourceModel) {
// handle fields whose source is a related model e.g. inventories.organization
scope[iterator + 'SearchParams'] = f.sourceModel + '__' + f.sourceField + '__';
} else if (f.searchField) {
scope[iterator + 'SearchParams'] = f.searchField + '__';
} else { } else {
sort_order = direction + fld; scope[iterator + 'SearchParams'] = scope[iterator + 'SearchField'] + '__';
}
if (f.searchType && (f.searchType === 'int' || f.searchType === 'boolean')) {
scope[iterator + 'SearchParams'] += 'int=';
} else if (f.searchType && f.searchType === 'gtzero') {
scope[iterator + 'SearchParams'] += 'gt=0';
} else {
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchType'] + '=';
}
if (f.searchType && (f.searchType === 'boolean' || f.searchType === 'select')) {
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchSelectValue'].value;
} else if (f.searchType === undefined || f.searchType === 'gtzero') {
scope[iterator + 'SearchParams'] += encodeURI(scope[iterator + 'SearchValue']);
}
scope[iterator + 'SearchParams'] += (sort_order) ? '&order_by=' + encodeURI(sort_order) : '';
} else {
scope[iterator + 'SearchParams'] = (sort_order) ? 'order_by=' + encodeURI(sort_order) : '';
}
scope[iterator + '_page'] = 1;
url += (url.match(/\/$/)) ? '?' : '&';
url += scope[iterator + 'SearchParams'];
url += (scope[iterator + '_page_size']) ? '&page_size=' + scope[iterator + '_page_size'] : "";
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: url });
};
scope.sort = function (iterator, fld) {
var sort_order, icon, direction, set;
// reset sort icons back to 'icon-sort' on all columns
// except the one clicked
$('.' + iterator + ' .list-header').each(function () {
if ($(this).attr('id') !== iterator + '-' + fld + '-header') {
var icon = $(this).find('i');
icon.attr('class', 'fa fa-sort');
}
});
// Toggle the icon for the clicked column
// and set the sort direction
icon = $('#' + iterator + '-' + fld + '-header i');
direction = '';
if (icon.hasClass('fa-sort')) {
icon.removeClass('fa-sort');
icon.addClass('fa-sort-up');
} else if (icon.hasClass('fa-sort-up')) {
icon.removeClass('fa-sort-up');
icon.addClass('fa-sort-down');
direction = '-';
} else if (icon.hasClass('fa-sort-down')) {
icon.removeClass('fa-sort-down');
icon.addClass('fa-sort-up');
}
// Set the sorder order value and call the API to refresh the list with the new order
for (set in form.related) {
if (form.related[set].iterator === iterator) {
if (form.related[set].fields[fld].sourceModel) {
sort_order = direction + form.related[set].fields[fld].sourceModel + '__' +
form.related[set].fields[fld].sourceField;
} else {
sort_order = direction + fld;
}
} }
} }
} scope[iterator + 'SortOrder'] = sort_order;
scope[iterator + 'SortOrder'] = sort_order; scope.search(iterator);
scope.search(iterator); };
}; };
}; }
} ]);
]);

Some files were not shown because too many files have changed in this diff Show More