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
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
+1
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,
+3 -2
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
+11 -5
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
+93 -62
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;
+2 -2
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,
@@ -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,
+4 -4
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) {
+6 -4
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
+4 -4
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,
+2 -2
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) {
+3 -3
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();
+2 -2
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) {
+2 -2
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();
+4 -4
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,
+2 -2
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();
@@ -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();
+4 -4
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) {
+2 -2
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');
+4 -4
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) {
+2 -2
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();
+2 -2
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();
@@ -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,
+4 -4
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) {
+4 -4
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) {
@@ -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);
@@ -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')
}; };
}]); }
@@ -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').
} }
} }
}]); }
@@ -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')
} }
} }
}]); }
@@ -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
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
};
+28 -26
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
+425 -423
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: {}
});
+59 -57
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
+71 -69
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'
}
} }
} });
});
+49 -47
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: { }
}); });
+39 -37
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
+83 -81
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: {}
});
+77 -75
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: { });
}
});
+46 -45
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
+17 -15
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
+38 -37
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 != ""'
}
} }
} });
});
+362 -362
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;
};
}]);
+21 -21
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: { }
}); });
+101 -99
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: { }
}
}
});
+65 -64
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'
}
} }
} });
});
+38 -36
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
+88 -86
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
}
} }
} });
});
+45 -43
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
}
} }
}
}); });
+136 -134
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
+120 -118
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
+36 -34
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
+2
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', {
+239 -237
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: { }
});
+52 -50
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
// }
// }
}); });
+254 -252
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'
}
}
}); });
+234 -232
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
+258 -256
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
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
};
+1 -1
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', {
+1 -1
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', {
+1 -1
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', {
+1 -1
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', {
+82
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
};
+65 -64
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%');
}
});
}); });
});
}; };
} }
]); ]);
+46 -46
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); };
}]); }]);
+86 -86
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);
};
}
]);
+433 -433
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');
}
};
}]);
+251 -227
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
}); });
}); });
} }
} }
}; };
} }
]); ]);
+311 -311
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
+195 -195
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
+256 -256
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
+157 -158
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
+2 -1
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) {
+340 -340
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);
}; };
}]); }]);
+194 -194
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');
}
}; };
}; };
}; }]);
}]);
+145 -145
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 });
};
};
}
]);
+77 -77
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 );
}
}
};
}; };
}; }
} ]);
]);
+41 -39
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
}
};
}
]);
+66 -64
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 });
});
};
}
]);
+58 -58
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
+144 -144
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 = '';
}
}
}
});
};
}
]);
+27 -27
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 }); };
} }]);
};
}]);
+1 -3
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',
}; };
}]); }]);
+28 -28
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;
};
}
]);
+1 -2
View File
@@ -10,8 +10,7 @@
* *
*/ */
'use strict'; export default
angular.module('VariablesHelper', ['Utilities']) angular.module('VariablesHelper', ['Utilities'])
/** /**
+74 -74
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);
}
};
}
]);
+349 -349
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 });
};
};
}
]);
+26 -26
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();
};
};
}]);
+31 -31
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 });
});
};
}
]);
+43 -43
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
});
});
};
}
]);
+224 -224
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