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
commit 8c3ea4f8da
359 changed files with 17851 additions and 417985 deletions

7
.gitignore vendored
View File

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

View File

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

View File

@ -3,7 +3,7 @@ recursive-include awx/static *.ico
recursive-include awx/templates *.html
recursive-include awx/api/templates *.md
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/lib *
recursive-include awx/playbooks *.yml
@ -16,7 +16,8 @@ recursive-exclude awx/api/tests *
recursive-exclude awx/main/tests *
recursive-exclude awx/ui/static/lib/ansible *
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 tools/scripts/request_tower_configuration.sh
include tools/scripts/ansible-tower

View File

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

View File

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

View File

@ -17,9 +17,9 @@
* 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) {
var list = AdminList,

View File

@ -57,9 +57,9 @@
* @Usage
* 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) {
var setLoginFocus, lastPath, sessionExpired, loginAgain,

View File

@ -11,9 +11,9 @@
* @name controllers.function:Credentials
* @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,
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,
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,
KindChange, UserList, TeamList, LookUpInit, Empty, OwnerChange, LoginMethodChange, FormSave, Stream, Wait) {

View File

@ -14,7 +14,7 @@
* @name controllers.function:Home
* @description This controller's for the dashboard
*/
'use strict';
/**
* @ngdoc method
@ -25,7 +25,8 @@
* 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('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
*
*/
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,
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'
*
*/
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) {
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior

View File

@ -12,9 +12,9 @@
* @name controllers.function:Inventories
* @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,
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,
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,
GroupsCancelUpdate, ViewUpdateStatus, GroupsDelete, Store, HostsEdit, HostsDelete, EditInventoryProperties, ToggleHostEnabled, Stream, ShowJobSummary,
InventoryGroupsHelp, HelpDialog, ViewJob, WatchInventoryWindowResize, GetHostContainerRows, GetGroupContainerRows, GetGroupContainerHeight,

View File

@ -9,9 +9,9 @@
* @name controllers.function:JobDetail
* @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,
UpdateDOM, EventViewer, DeleteJob, PlaybookRun, HostEventsViewer, LoadPlays, LoadTasks, LoadHosts, HostsEdit, ParseVariableString) {

View File

@ -12,9 +12,9 @@
* @name controllers.function:JobEvent
* @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,
FormatDate, EventView, Refresh, Wait) {
@ -260,7 +260,7 @@ JobEventsList.$inject = ['$sce', '$filter', '$scope', '$rootScope', '$location',
'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) {
ClearScope();

View File

@ -12,9 +12,9 @@
* @name controllers.function:JobHosts
* @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,
JobStatusToolTip) {

View File

@ -9,9 +9,9 @@
* @name controllers.function:JobStdout
* @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();

View File

@ -12,9 +12,9 @@
* @name controllers.function:JobTemplate
* @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,
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'
];
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,
InventoryList, CredentialList, ProjectList, LookUpInit, md5Setup, ParseTypeChange, Wait, Empty, ToJSON,
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,
CredentialList, ProjectList, LookUpInit, GetBasePath, md5Setup, ParseTypeChange, JobStatusToolTip, FormatDate,
Wait, Stream, Empty, Prompt, ParseVariableString, ToJSON, SchedulesControllerInit, JobsControllerInit, JobsListUpdate,

View File

@ -12,9 +12,9 @@
* @name controllers.function:Jobs
* @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) {
ClearScope();

View File

@ -12,9 +12,9 @@
* @name controllers.function:Organizations
* @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) {
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,
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) {
ClearScope();

View File

@ -12,9 +12,9 @@
* @name controllers.function: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,
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,
GetBasePath, ReturnToCaller, InventoryList, ProjectList, LookUpInit, CheckAccess,
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,
InventoryList, ProjectList, LookUpInit, CheckAccess, Wait, PermissionCategoryChange) {

View File

@ -14,7 +14,7 @@
* @name controllers.function:Portal
* @description This controller's for portal mode
*/
'use strict';
/**
* @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){
ClearScope('portal');

View File

@ -12,9 +12,9 @@
* @name controllers.function:Projects
* @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,
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,
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,
ClearScope, GetBasePath, ReturnToCaller, GetProjectPath, Authorization, CredentialList, LookUpInit, GetChoices,
Empty, DebugForm, Wait, Stream, SchedulesControllerInit, SchedulesListInit, SchedulesList, ProjectUpdate) {

View File

@ -12,9 +12,9 @@
* @name controllers.function: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) {
ClearScope();

View File

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

View File

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

View File

@ -12,9 +12,9 @@
* @name controllers.function: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,
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,
OrganizationList, SearchInit, PaginateInit, GetBasePath, LookUpInit, Wait) {
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,
OrganizationList, Wait, Stream) {

View File

@ -11,9 +11,9 @@
* @name controllers.function:Users
* @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) {
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) {
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,
Prompt, CheckAccess, ResetForm, Wait, Stream) {

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

@ -10,438 +10,440 @@
* @name forms.function:Credentials
* @description This form is for adding/editing a Credential
*/
angular.module('CredentialFormDefinition', [])
.value('CredentialForm', {
addTitle: 'Create Credential', //Legend in add mode
editTitle: '{{ name }}', //Legend in edit mode
name: 'credential',
well: true,
forceListeners: true,
export default
angular.module('CredentialFormDefinition', [])
.value('CredentialForm', {
actions: {
stream: {
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
mode: 'edit'
}
},
addTitle: 'Create Credential', //Legend in add mode
editTitle: '{{ name }}', //Legend in edit mode
name: 'credential',
well: true,
forceListeners: true,
fields: {
name: {
label: 'Name',
type: 'text',
addRequired: true,
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"
actions: {
stream: {
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
mode: 'edit'
}
},
team: {
label: 'Team that owns this credential',
type: 'lookup',
sourceModel: 'team',
sourceField: 'name',
ngClick: 'lookUpTeam()',
ngShow: "owner == 'team'",
awRequiredWhen: {
variable: "team_required",
init: "false"
fields: {
name: {
label: 'Name',
type: 'text',
addRequired: true,
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',
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',
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
buttons: {
save: {
label: 'Save',
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
},
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
reset: {
ngClick: 'formReset()',
ngDisabled: true //Disabled when $pristine
}
},
"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
},
related: {}
"vault_password": {
label: "Vault Password",
type: 'password',
ngShow: "kind.value == 'ssh'",
addRequired: false,
editRequired: false,
ngChange: "clearPWConfirm('vault_password_confirm')",
ask: true,
clear: true,
associated: 'vault_password_confirm',
autocomplete: false
},
"vault_password_confirm": {
label: "Confirm Vault Password",
type: 'password',
ngShow: "kind.value == 'ssh'",
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'vault_password',
autocomplete: false
}
},
buttons: {
save: {
label: 'Save',
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
},
reset: {
ngClick: 'formReset()',
ngDisabled: true //Disabled when $pristine
}
},
related: {}
});
});

View File

@ -11,68 +11,70 @@
* @name forms.function:Organizations
* @description This form is for adding/editing an organization
*/
angular.module('CustomInventoryFormDefinition', [])
.value('CustomInventoryForm', {
addTitle: 'Create Custom Inventory', //Title in add mode
editTitle: '{{ name }}', //Title in edit mode
name: 'custom_inventory', //entity or model name in singular form
well: false,
showActions: false,
export default
angular.module('CustomInventoryFormDefinition', [])
.value('CustomInventoryForm', {
fields: {
name: {
label: 'Name',
type: 'text',
addRequired: true,
editRequired: true,
capitalize: false
},
description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
},
organization: {
label: 'Organization',
type: 'lookup',
awRequiredWhen: {
variable: "orgrequired",
init: true
addTitle: 'Create Custom Inventory', //Title in add mode
editTitle: '{{ name }}', //Title in edit mode
name: 'custom_inventory', //entity or model name in singular form
well: false,
showActions: false,
fields: {
name: {
label: 'Name',
type: 'text',
addRequired: true,
editRequired: true,
capitalize: false
},
description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false
},
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',
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"
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
}
},
},
buttons: { //for now always generates <button> tags
save: {
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
},
reset: {
ngClick: 'formReset()',
ngDisabled: true //Disabled when $pristine
}
},
}); //OrganizationForm
}); //OrganizationForm

View File

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

View File

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

View File

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

View File

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

View File

@ -11,87 +11,89 @@
* @name forms.function:Inventories
* @description This form is for adding/editing an inventory
*/
angular.module('InventoryFormDefinition', [])
.value('InventoryForm', {
addTitle: 'Create Inventory',
editTitle: '{{ inventory_name }}',
name: 'inventory',
well: true,
export default
angular.module('InventoryFormDefinition', [])
.value('InventoryForm', {
actions: {
stream: {
'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
dataPlacement: "top",
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
}
},
addTitle: 'Create Inventory',
editTitle: '{{ inventory_name }}',
name: 'inventory',
well: true,
fields: {
inventory_name: {
realName: 'name',
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"
actions: {
stream: {
'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
dataPlacement: "top",
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
}
},
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: {
save: {
ngClick: 'formSave()',
ngDisabled: true
fields: {
inventory_name: {
realName: 'name',
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()',
ngDisabled: true
buttons: {
save: {
ngClick: 'formSave()',
ngDisabled: true
},
reset: {
ngClick: 'formReset()',
ngDisabled: true
}
},
related: {
}
},
related: {
}
});
});

View File

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

View File

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

View File

@ -12,43 +12,44 @@
* @description Display job status info in a dialog
*/
angular.module('JobSummaryDefinition', [])
.value('JobSummary', {
export default
angular.module('JobSummaryDefinition', [])
.value('JobSummary', {
editTitle: '{{ id }} - {{ name }}',
name: 'jobs',
well: false,
editTitle: '{{ id }} - {{ name }}',
name: 'jobs',
well: false,
fields: {
status: {
//label: 'Job Status',
type: 'custom',
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>',
readonly: true
},
created: {
label: 'Created On',
type: 'text',
readonly: true
},
result_stdout: {
label: 'Standard Out',
type: 'textarea',
readonly: true,
xtraWide: true,
rows: '{{ stdout_rows }}',
'class': 'nowrap mono-space resizable',
ngShow: 'result_stdout != ""'
},
result_traceback: {
label: 'Traceback',
type: 'textarea',
xtraWide: true,
readonly: true,
rows: '{{ traceback_rows }}',
'class': 'nowrap mono-space resizable',
ngShow: 'result_traceback != ""'
fields: {
status: {
//label: 'Job Status',
type: 'custom',
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>',
readonly: true
},
created: {
label: 'Created On',
type: 'text',
readonly: true
},
result_stdout: {
label: 'Standard Out',
type: 'textarea',
readonly: true,
xtraWide: true,
rows: '{{ stdout_rows }}',
'class': 'nowrap mono-space resizable',
ngShow: 'result_stdout != ""'
},
result_traceback: {
label: 'Traceback',
type: 'textarea',
xtraWide: true,
readonly: true,
rows: '{{ traceback_rows }}',
'class': 'nowrap mono-space resizable',
ngShow: 'result_traceback != ""'
}
}
}
});
});

View File

@ -12,376 +12,376 @@
* @name forms.function:JobTemplate
* @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',
editTitle: '{{ name }}',
name: 'job_templates',
twoColumns: true,
well: true,
base: 'job_templates',
collapse: true,
collapseTitle: "Properties",
collapseMode: 'edit',
collapseOpenFirst: true, //Always open first panel
addTitle: 'Create Job Templates',
editTitle: '{{ name }}',
name: 'job_templates',
twoColumns: true,
well: true,
base: 'job_templates',
collapse: true,
collapseTitle: "Properties",
collapseMode: 'edit',
collapseOpenFirst: true, //Always open first panel
actions: {
// submit: {
// ngClick: 'launch()',
// awToolTip: 'Start a job using this template',
// dataPlacement: 'top',
// mode: 'edit'
// },
stream: {
'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
dataPlacement: "top",
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
}
},
actions: {
// submit: {
// ngClick: 'launch()',
// awToolTip: 'Start a job using this template',
// dataPlacement: 'top',
// mode: 'edit'
// },
stream: {
'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
dataPlacement: "top",
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
}
},
fields: {
name: {
label: 'Name',
type: 'text',
addRequired: true,
editRequired: true,
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'
fields: {
name: {
label: 'Name',
type: 'text',
addRequired: true,
editRequired: true,
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: {
iterator: 'schedule',
url: urls.schedules
include: "SchedulesList"
},
"completed_jobs": {
include: "CompletedJobsList"
}
};
}
})
},
.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;
}
relatedSets: function(urls) {
return {
completed_jobs: {
iterator: 'completed_job',
url: urls.jobs + '?or__status=successful&or__status=failed&or__status=error&or__status=canceled'
},
schedules: {
iterator: 'schedule',
url: urls.schedules
}
};
}
})
return JobTemplateFormObject;
};
}]);
.factory('JobTemplateForm', ['JobTemplateFormObject', 'SchedulesList', 'CompletedJobsList',
function(JobTemplateFormObject, SchedulesList, CompletedJobsList) {
return function() {
var itm;
for (itm in JobTemplateFormObject.related) {
if (JobTemplateFormObject.related[itm].include === "SchedulesList") {
JobTemplateFormObject.related[itm] = SchedulesList;
JobTemplateFormObject.related[itm].generateList = true; // tell form generator to call list generator and inject a list
}
if (JobTemplateFormObject.related[itm].include === "CompletedJobsList") {
JobTemplateFormObject.related[itm] = CompletedJobsList;
JobTemplateFormObject.related[itm].generateList = true;
}
}
return JobTemplateFormObject;
};
}]);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,248 +11,250 @@
* @name forms.function:Source
* @description This form is for group model
*/
angular.module('SourceFormDefinition', [])
.value('SourceForm', {
addTitle: 'Create Source',
editTitle: 'Edit Source',
showTitle: false,
cancelButton: false,
name: 'source',
well: false,
export default
angular.module('SourceFormDefinition', [])
.value('SourceForm', {
fields: {
source: {
label: 'Source',
type: 'select',
ngOptions: 'source.label for source in source_type_options track by source.value',
ngChange: 'sourceChange()',
addRequired: false,
editRequired: false
},
source_path: {
label: 'Script Path',
ngShow: "source && source.value == 'file'",
type: 'text',
awRequiredWhen: {
variable: "sourcePathRequired",
init: "false"
addTitle: 'Create Source',
editTitle: 'Edit Source',
showTitle: false,
cancelButton: false,
name: 'source',
well: false,
fields: {
source: {
label: 'Source',
type: 'select',
ngOptions: 'source.label for source in source_type_options track by source.value',
ngChange: 'sourceChange()',
addRequired: false,
editRequired: 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: [{
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'
}]
buttons: {
},
update_cache_timeout: {
label: "Cache Timeout <span class=\"small-text\"> (seconds)</span>",
id: 'source-cache-timeout',
type: 'number',
integer: true,
min: 0,
ngShow: "source && source.value !== 'manual' && update_on_launch",
spinner: true,
"default": 0,
addRequired: false,
editRequired: false,
awPopOver: '<p>Time in seconds to consider an inventory sync to be current. During job runs and callbacks the task system will ' +
'evaluate the timestamp of the latest sync. If it is older than Cache Timeout, it is not considered current, ' +
'and a new inventory sync will be performed.</p>',
dataTitle: 'Cache Timeout',
dataPlacement: 'right',
dataContainer: "body"
}
},
buttons: {
related: { }
},
related: { }
});
});

View File

@ -11,60 +11,62 @@
* @name forms.function:SurveyMaker
* @description This form is for adding/editing a survey
*/
angular.module('SurveyMakerFormDefinition', [])
.value('SurveyMakerForm', {
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,
export default
angular.module('SurveyMakerFormDefinition', [])
.value('SurveyMakerForm', {
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: {
survey_name: {
type: 'custom',
control: '<div class="row">'+
// '<div class="col-sm-6">
// <div class="form-group">'+
// '<label for="survey_name"><span class="label-text prepend-asterisk">Survey Name</span></label>
// <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>'+
// '<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></div></div>'+
// '<div class="col-sm-6"><div class="form-group">'+
// '<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">'+
// '<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 class="col-sm-12">'+
'<label for="survey"><span class="label-text prepend-asterisk">Questions</span></label>'+
'<div id="survey_maker_question_area"></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>'+
'<div id="new_question"></div>'+
'</div>'+
'</div>'//</div>'
// label: 'Survey Name',
// type: 'text',
// addRequired: true,
// editRequired: true,
// capitalize: false,
// // column: 1
fields: {
survey_name: {
type: 'custom',
control: '<div class="row">'+
// '<div class="col-sm-6">
// <div class="form-group">'+
// '<label for="survey_name"><span class="label-text prepend-asterisk">Survey Name</span></label>
// <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>'+
// '<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></div></div>'+
// '<div class="col-sm-6"><div class="form-group">'+
// '<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">'+
// '<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 class="col-sm-12">'+
'<label for="survey"><span class="label-text prepend-asterisk">Questions</span></label>'+
'<div id="survey_maker_question_area"></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>'+
'<div id="new_question"></div>'+
'</div>'+
'</div>'//</div>'
// label: 'Survey Name',
// type: 'text',
// addRequired: true,
// editRequired: true,
// capitalize: false,
// // column: 1
},
},
},
// 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
// 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
// }
// }
// reset: {
// ngClick: 'formReset()',
// ngDisabled: true //Disabled when $pristine
// }
// }
});
});

View File

@ -11,261 +11,263 @@
* @name forms.function:Questions
* @description This form is for adding a question
*/
angular.module('SurveyQuestionFormDefinition', [])
.value('SurveyQuestionForm', {
addTitle: 'Add Question',
editTitle: 'Edit Question',
base: 'survey_question',
name: 'survey_question',
well: true,
twoColumns: true,
breadcrumbs: false,
export default
angular.module('SurveyQuestionFormDefinition', [])
.value('SurveyQuestionForm', {
fields: {
question_name: {
realName: 'question_text',
label: 'Name',
type: 'text',
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>'+
addTitle: 'Add Question',
editTitle: 'Edit Question',
base: 'survey_question',
name: 'survey_question',
well: true,
twoColumns: true,
breadcrumbs: false,
'</div>'+
'</div>',
ngShow: 'type.type==="float" ',
addRequired: true,
editRequired: true,
column: 2
fields: {
question_name: {
realName: 'question_text',
label: 'Name',
type: 'text',
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: {
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
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'
}
}
},
buttons: {
question_cancel : {
label: 'Cancel',
'class' : 'btn btn-default',
ngClick: 'cancelQuestion($event)'
},
submit_question: {
ngClick: 'submitQuestion($event)',
ngDisabled: true, //'survey_question.$valid', //"!question_name || !variable || !type || ((type.type==='multiplechoice' || type.type === 'multiselect' ) && !choices)", //|| type.type===multiselect ',//'!question_name || !variable || !type' ,
'class': 'btn btn-sm btn-primary',
label: 'Add Question'
}
}
});
});

View File

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

View File

@ -11,288 +11,290 @@
* @name forms.function:Users
* @description This form is for adding/editing users
*/
angular.module('UserFormDefinition', [])
.value('UserForm', {
addTitle: 'Create User',
editTitle: '{{ username }}',
name: 'user',
well: true,
forceListeners: true,
collapse: true,
collapseTitle: "Properties",
collapseMode: 'edit',
collapseOpen: true,
export default
angular.module('UserFormDefinition', [])
.value('UserForm', {
actions: {
stream: {
'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
dataPlacement: "top",
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
}
},
addTitle: 'Create User',
editTitle: '{{ username }}',
name: 'user',
well: true,
forceListeners: true,
collapse: true,
collapseTitle: "Properties",
collapseMode: 'edit',
collapseOpen: true,
fields: {
first_name: {
label: 'First Name',
type: 'text',
addRequired: true,
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
}
},
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'
}
actions: {
stream: {
'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
dataPlacement: "top",
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
}
},
permissions: {
type: 'collection',
title: 'Permissions',
iterator: 'permission',
open: false,
index: false,
fields: {
first_name: {
label: 'First Name',
type: 'text',
addRequired: true,
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: {
add: {
ngClick: "add('permissions')",
icon: 'icon-plus',
label: 'Add',
awToolTip: 'Add a permission for this user',
ngShow: 'PermissionAddAllowed'
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'
}
}
},
fields: {
name: {
key: true,
label: 'Name',
ngClick: "edit('permissions', permission.id, permission.name)"
permissions: {
type: 'collection',
title: 'Permissions',
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'
}
},
inventory: {
label: 'Inventory',
sourceModel: 'inventory',
sourceField: 'name',
ngBind: 'permission.summary_fields.inventory.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'
}
},
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'
}
}
},
fieldActions: {
edit: {
label: 'Edit',
ngClick: "edit('permissions', permission.id, permission.name)",
icon: 'icon-edit',
awToolTip: 'Edit the permission',
'class': 'btn btn-default'
},
admin_of_organizations: { // Assumes a plural name (e.g. things)
type: 'collection',
title: 'Admin of Organizations',
iterator: 'adminof', // Singular form of name (e.g. thing)
open: false, // Open accordion on load?
index: false,
base: '/organizations',
"delete": {
label: 'Delete',
ngClick: "delete('permissions', permission.id, permission.name, 'permissions')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Delete the permission',
ngShow: 'PermissionAddAllowed'
actions: {},
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
}
}
}
},
},
organizations: {
type: 'collection',
title: 'Organizations',
iterator: 'organization',
index: false,
open: false,
admin_of_organizations: { // Assumes a plural name (e.g. things)
type: 'collection',
title: 'Admin of Organizations',
iterator: 'adminof', // Singular form of name (e.g. thing)
open: false, // Open accordion on load?
index: false,
base: '/organizations',
actions: {},
actions: {},
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
}
}
}
},
},
organizations: {
type: 'collection',
title: 'Organizations',
iterator: 'organization',
index: false,
open: false,
teams: {
type: 'collection',
title: 'Teams',
iterator: 'team',
open: false,
index: false,
actions: {},
actions: {},
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
}
}
},
teams: {
type: 'collection',
title: 'Teams',
iterator: 'team',
open: false,
index: false,
actions: {},
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
fields: {
name: {
key: true,
label: 'Name'
},
description: {
label: 'Description'
}
}
}
}
}
}); //UserForm
}); //UserForm

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

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

View File

@ -18,7 +18,7 @@
* @name help.function:ChromeSocketHelp
* @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', [])
.value('ChromeSocketHelp', {

View File

@ -11,7 +11,7 @@
* @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.
*/
'use strict';
angular.module('FFSocketHelpDefinition', [])
.value('FFSocketHelp', {

View File

@ -12,7 +12,7 @@
* @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.
*/
'use strict';
angular.module('InventoryGroupsHelpDefinition', [])
.value('InventoryGroupsHelp', {

View File

@ -11,7 +11,7 @@
* @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.
*/
'use strict';
angular.module('SafariSocketHelpDefinition', [])
.value('SafariSocketHelp', {

View File

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

View File

@ -16,76 +16,77 @@
* @name helpers.function:AboutAnsible
* @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(),
url;
export default
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');
Rest.setUrl(url);
Rest.get()
.success(function (data){
scope.$emit('BuildAboutDialog', data);
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to get: ' + url + ' GET returned: ' + status });
var scope= $rootScope.$new(),
url;
url = GetBasePath('config');
Rest.setUrl(url);
Rest.get()
.success(function (data){
scope.$emit('BuildAboutDialog', data);
})
.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.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) {
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 +" ";
if (scope.removeBuildAboutDialog) {
scope.removeBuildAboutDialog();
}
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%');
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;
for( j = paddedStr.length; j<16; j++){
paddedStr = paddedStr + " ";
}
$('#about-modal-version').html(paddedStr);
scope.modalOK = function(){
$('#about-modal-dialog').dialog('close');
};
CreateDialog({
id: 'about-modal-dialog',
scope: scope,
// buttons: [],
width: 710,
height: 380,
minWidth: 300,
resizable: false,
// title: , //'<img src="static/img/tower_login_logo.png">' ,//'About Ansible',
callback: 'DialogReady',
onOpen: function(){
$('#dialog-ok-button').focus();
$('#about-modal-dialog').scrollTop(0);
$('#about-modal-dialog').css('overflow-x', 'hidden');
$('.ui-widget-overlay').css('width', '100%');
}
});
});
});
};
}
]);
};
}
]);

View File

@ -12,57 +12,57 @@
* @description routines checking user access
*/
'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) {
return function (params) {
// set PermissionAddAllowed to true or false based on user access. admins and org admins are granted
// accesss.
var scope = params.scope,
callback = params.callback || undefined,
me;
.factory('CheckAccess', ['$rootScope', 'Alert', 'Rest', 'GetBasePath', 'ProcessErrors', '$cookieStore', function ($rootScope, Alert, Rest, GetBasePath, ProcessErrors, $cookieStore) {
return function (params) {
// set PermissionAddAllowed to true or false based on user access. admins and org admins are granted
// accesss.
var scope = params.scope,
callback = params.callback || undefined,
me;
// 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');
// 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');
if (me.is_superuser) {
scope.PermissionAddAllowed = true;
if(callback){
scope.$emit(callback);
}
} else {
if (me.related.admin_of_organizations) {
Rest.setUrl(me.related.admin_of_organizations);
Rest.get()
.success(function (data) {
if (data.results.length > 0) {
scope.PermissionAddAllowed = true;
} else {
scope.PermissionAddAllowed = false;
}
if(callback){
scope.$emit(callback);
}
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, {
hdr: 'Error!',
msg: 'Call to ' + me.related.admin_of_organizations +
' failed. DELETE returned status: ' + status
if (me.is_superuser) {
scope.PermissionAddAllowed = true;
if(callback){
scope.$emit(callback);
}
} else {
if (me.related.admin_of_organizations) {
Rest.setUrl(me.related.admin_of_organizations);
Rest.get()
.success(function (data) {
if (data.results.length > 0) {
scope.PermissionAddAllowed = true;
} else {
scope.PermissionAddAllowed = false;
}
if(callback){
scope.$emit(callback);
}
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, {
hdr: 'Error!',
msg: 'Call to ' + me.related.admin_of_organizations +
' failed. DELETE returned status: ' + status
});
});
});
}
}
}
//if (!access) {
// Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
//}
//return access;
};
}])
//if (!access) {
// Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
//}
//return access;
};
}])
.factory('IsAdmin', ['$rootScope', function($rootScope) {
return function() { return ($rootScope.current_user && $rootScope.current_user.is_superuser); };
}]);
.factory('IsAdmin', ['$rootScope', function($rootScope) {
return function() { return ($rootScope.current_user && $rootScope.current_user.is_superuser); };
}]);

View File

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

View File

@ -11,459 +11,459 @@
*
*/
'use strict';
angular.module('ConfigureTowerHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ModalDialog',
'GeneratorHelpers'])
export default
angular.module('ConfigureTowerHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ModalDialog',
'GeneratorHelpers'])
.factory('ConfigureTower', ['Wait', '$location' , '$compile', 'CreateDialog', 'ConfigureTowerJobsList', 'GenerateList', 'GetBasePath' , 'SearchInit' , 'PaginateInit', 'PlaybookRun', 'LoadSchedulesScope',
'SchedulesList', 'SchedulesControllerInit' , 'ConfigureTowerSchedule', 'Rest' , 'ProcessErrors',
function(Wait, $location, $compile, CreateDialog, ConfigureTowerJobsList, GenerateList, GetBasePath, SearchInit, PaginateInit, PlaybookRun, LoadSchedulesScope,
SchedulesList, SchedulesControllerInit, ConfigureTowerSchedule, Rest, ProcessErrors) {
return function(params) {
// Set modal dimensions based on viewport width
.factory('ConfigureTower', ['Wait', '$location' , '$compile', 'CreateDialog', 'ConfigureTowerJobsList', 'GenerateList', 'GetBasePath' , 'SearchInit' , 'PaginateInit', 'PlaybookRun', 'LoadSchedulesScope',
'SchedulesList', 'SchedulesControllerInit' , 'ConfigureTowerSchedule', 'Rest' , 'ProcessErrors',
function(Wait, $location, $compile, CreateDialog, ConfigureTowerJobsList, GenerateList, GetBasePath, SearchInit, PaginateInit, PlaybookRun, LoadSchedulesScope,
SchedulesList, SchedulesControllerInit, ConfigureTowerSchedule, Rest, ProcessErrors) {
return function(params) {
// Set modal dimensions based on viewport width
var scope = params.scope.$new(),
parent_scope = params.scope,
callback = 'OpenConfig',
defaultUrl = GetBasePath('system_job_templates'),
list = ConfigureTowerJobsList,
view = GenerateList, e,
scheduleUrl = GetBasePath('system_job_templates'),
buttons = [
{
"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",
var scope = params.scope.$new(),
parent_scope = params.scope,
callback = 'OpenConfig',
defaultUrl = GetBasePath('system_job_templates'),
list = ConfigureTowerJobsList,
view = GenerateList, e,
scheduleUrl = GetBasePath('system_job_templates'),
buttons = [
{
"label": "Close",
"onClick": function() {
$(this).dialog('close');
// $(this).dialog('close');
scope.cancelConfigure();
},
"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);
"id": "configure-close-button"
}
];
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"
}]
});
scope.cleanupJob = true;
if (scope.removePromptForDays) {
scope.removePromptForDays();
if(scope.removeOpenConfig) {
scope.removeOpenConfig();
}
scope.removePromptForDays = scope.$on('PromptForDays', function() {
// $('#configure-tower-dialog').dialog('close');
$('#prompt-for-days').show();
$('#prompt-for-days').dialog('open');
Wait('stop');
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() {
$(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) {
Rest.setUrl(scheduleUrl+id+'/schedules/');
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 {
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()
.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
});
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) {
.error(function(data,status){
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 {
detail.hide();
target.show();
scope.formShowing = true;
scope.$emit('ScheduleReady');
}
};
if (scope.removeScheduleSaved) {
scope.removeScheduleSaved();
}
scope.removeScheduleSaved = scope.$on('ScheduleSaved', function() {
Wait('stop');
$("#configure-save-button").remove();
container.hide('slide', { direction: 'left' }, 500, restoreList);
scope.$destroy();
});
scope.saveScheduleForm = function() {
var extra_vars;
if (scheduler.isValid()) {
scope.schedulerIsValid = true;
url = (mode==="edit") ? GetBasePath('schedules')+id+'/' : url;
extra_vars = {
"days" : scope.scheduler_form.schedulerPurgeDays.$viewValue
};
schedule.extra_data = JSON.stringify(extra_vars);
SchedulePost({
scope: scope,
url: url,
scheduler: scheduler,
callback: 'ScheduleSaved',
mode: mode,
schedule: schedule
});
}
else {
scope.schedulerIsValid = false;
}
};
scope.deleteSystemSchedule = function(){
var hdr = 'Delete Schedule',
action = function () {
Wait('start');
Rest.setUrl(schedule.url);
Rest.destroy()
.success(function () {
$('#prompt-modal').modal('hide');
Wait('stop');
// scope.$emit(callback, id);
scope.cancelScheduleForm();
})
.error(function (data, status) {
try {
$('#prompt-modal').modal('hide');
}
catch(e) {
// ignore
}
ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url +
' failed. DELETE returned: ' + status });
});
};
Prompt({
hdr: hdr,
body: "<div class=\"alert alert-info\">Are you sure you want to delete the <em>" + scope.schedulerName + "</em> schedule?</div>",
action: action,
backdrop: false
});
// }
// } else {
// //a schedule doesn't exist
// $("#prompt_action_btn").text('OK');
// $('#prompt_cancel_btn').hide();
// var action2 = function(){
// $('#prompt-modal').modal('hide');
// $("#prompt_action_btn").text('Yes');
// $('#prompt_cancel_btn').show();
// };
// Prompt({
// hdr: "Delete",
// body: "<div class=\"alert alert-info\">No schedule exists for that job. </div>",
// action: action2,
// backdrop: false
// });
// }
// })
// .error(function(data, status) {
// ProcessErrors(scope, data, status, null, { hdr: 'Error!',
// msg: 'Failed updating job ' + scope.job_template_id + ' with variables. PUT returned: ' + status });
// });
};
scope.cancelScheduleForm = function() {
container.hide('slide', { direction: 'right' }, 500, restoreList);
$("#configure-save-button").remove();
scope.$destroy();
};
if (mode === 'edit') {
// Get the existing record
Rest.setUrl(url); //GetBasePath('schedules')+id+'/');
Rest.get()
.success(function(data) {
schedule = data.results[0];
id = schedule.id;
if (!/DTSTART/.test(schedule.rrule)) {
schedule.rrule += ";DTSTART=" + schedule.dtstart.replace(/\.\d+Z$/,'Z');
}
schedule.rrule = schedule.rrule.replace(/ RRULE:/,';');
schedule.rrule = schedule.rrule.replace(/DTSTART:/,'DTSTART=');
scope.$emit('ScheduleReady');
})
.error(function(data,status){
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to get: ' + url + ' GET returned: ' + status });
});
}
else {
scope.$emit('ScheduleReady');
}
};
}]);
}]);

View File

@ -5,263 +5,287 @@
*
*
*/
/**
/**
* @ngdoc function
* @name helpers.function:Credentials
* @description Functions shared amongst Credential related controllers
*/
'use strict';
*/
export default
angular.module('CredentialsHelper', ['Utilities'])
.factory('KindChange', ['Empty',
function (Empty) {
return function (params) {
function (Empty) {
return function (params) {
var scope = params.scope,
reset = params.reset,
collapse, id;
var scope = params.scope,
reset = params.reset,
collapse, id;
$('.popover').each(function() {
// remove lingering popover <div>. Seems to be a bug in TB3 RC1
$(this).remove();
});
$('.tooltip').each( function() {
// close any lingering tool tipss
$(this).hide();
});
// Put things in a default state
scope.usernameLabel = 'Username';
scope.aws_required = false;
scope.email_required = false;
scope.rackspace_required = false;
scope.sshKeyDataLabel = 'SSH Private Key';
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.project_required = false;
scope.subscription_required = false;
scope.key_description = "Paste the contents of the SSH private key file.";
scope.key_hint= "drag and drop an SSH private key file on the field below";
scope.host_required = false;
scope.password_required = false;
scope.hostLabel = '';
$('.popover').each(function() {
// remove lingering popover <div>. Seems to be a bug in TB3 RC1
$(this).remove();
});
$('.tooltip').each( function() {
// close any lingering tool tipss
$(this).hide();
});
// Put things in a default state
scope.usernameLabel = 'Username';
scope.aws_required = false;
scope.email_required = false;
scope.rackspace_required = false;
scope.sshKeyDataLabel = 'SSH Private Key';
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.project_required = false;
scope.subscription_required = false;
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.host_required = false;
scope.password_required = false;
scope.hostLabel = '';
if (!Empty(scope.kind)) {
// Apply kind specific settings
switch (scope.kind.value) {
case 'aws':
scope.aws_required = true;
break;
case 'rax':
scope.rackspace_required = true;
scope.username_required = true;
break;
case 'ssh':
scope.usernameLabel = 'Username'; //formally 'SSH Username'
break;
case 'scm':
scope.sshKeyDataLabel = 'SCM Private Key';
break;
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;
}
}
$('.popover').each(function() {
// remove lingering popover <div>. Seems to be a bug in TB3 RC1
$(this).remove();
});
$('.tooltip').each( function() {
// close any lingering tool tipss
$(this).hide();
});
// Put things in a default state
scope.usernameLabel = 'Username';
scope.aws_required = false;
scope.email_required = false;
scope.rackspace_required = false;
scope.sshKeyDataLabel = 'SSH Private Key';
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.project_required = false;
scope.subscription_required = false;
scope.key_description = "Paste the contents of the SSH private key file.";
scope.key_hint= "drag and drop an SSH private key file on the field below";
scope.host_required = false;
scope.password_required = false;
scope.hostLabel = '';
// Reset all the field values related to Kind.
if (reset) {
scope.access_key = null;
scope.secret_key = null;
scope.api_key = null;
scope.username = null;
scope.password = null;
scope.password_confirm = null;
scope.ssh_key_data = null;
scope.ssh_key_unlock = null;
scope.ssh_key_unlock_confirm = null;
scope.sudo_username = null;
scope.sudo_password = null;
scope.sudo_password_confirm = null;
scope.su_username = null;
scope.su_password = null;
scope.su_password_confirm = null;
}
if (!Empty(scope.kind)) {
// Apply kind specific settings
switch (scope.kind.value) {
case 'aws':
scope.aws_required = true;
break;
case 'rax':
scope.rackspace_required = true;
scope.username_required = true;
break;
case 'ssh':
scope.usernameLabel = 'Username'; //formally 'SSH Username'
break;
case 'scm':
scope.sshKeyDataLabel = 'SCM Private Key';
break;
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
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);
}
}
// Reset all the field values related to Kind.
if (reset) {
scope.access_key = null;
scope.secret_key = null;
scope.api_key = null;
scope.username = null;
scope.password = null;
scope.password_confirm = null;
scope.ssh_key_data = null;
scope.ssh_key_unlock = null;
scope.ssh_key_unlock_confirm = null;
scope.sudo_username = null;
scope.sudo_password = null;
scope.sudo_password_confirm = null;
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', [
function () {
return function (params) {
var scope = params.scope,
owner = scope.owner;
if (owner === 'team') {
scope.team_required = true;
scope.user_required = false;
scope.user = null;
scope.user_username = null;
} else {
scope.team_required = false;
scope.user_required = true;
scope.team = null;
scope.team_name = null;
}
};
}
return function (params) {
var scope = params.scope,
owner = scope.owner;
if (owner === 'team') {
scope.team_required = true;
scope.user_required = false;
scope.user = null;
scope.user_username = null;
} else {
scope.team_required = false;
scope.user_required = true;
scope.team = null;
scope.team_name = null;
}
};
}
])
.factory('LoginMethodChange', [
function () {
return function (params) {
var scope = params.scope,
login_method = scope.login_method;
if (login_method !== 'sudo') {
scope.sudo_username = null;
scope.sudo_password = null;
}
if (login_method !== 'su') {
scope.su_username = null;
scope.su_password = null;
}
};
}
return function (params) {
var scope = params.scope,
login_method = scope.login_method;
if (login_method !== 'sudo') {
scope.sudo_username = null;
scope.sudo_password = null;
}
if (login_method !== 'su') {
scope.su_username = null;
scope.su_password = null;
}
};
}
])
.factory('FormSave', ['$location', 'Alert', 'Rest', 'ProcessErrors', 'Empty', 'GetBasePath', 'CredentialForm', 'ReturnToCaller', 'Wait',
function ($location, Alert, Rest, ProcessErrors, Empty, GetBasePath, CredentialForm, ReturnToCaller, Wait) {
return function (params) {
var scope = params.scope,
mode = params.mode,
form = CredentialForm,
data = {}, fld, url;
function ($location, Alert, Rest, ProcessErrors, Empty, GetBasePath, CredentialForm, ReturnToCaller, Wait) {
return function (params) {
var scope = params.scope,
mode = params.mode,
form = CredentialForm,
data = {}, fld, url;
for (fld in form.fields) {
if (fld !== 'access_key' && fld !== 'secret_key' && fld !== 'ssh_username' &&
fld !== 'ssh_password') {
if (scope[fld] === null) {
data[fld] = "";
} else {
data[fld] = scope[fld];
}
}
}
for (fld in form.fields) {
if (fld !== 'access_key' && fld !== 'secret_key' && fld !== 'ssh_username' &&
fld !== 'ssh_password') {
if (scope[fld] === null) {
data[fld] = "";
} else {
data[fld] = scope[fld];
}
}
}
if (!Empty(scope.team)) {
data.team = scope.team;
data.user = "";
} else {
data.user = scope.user;
data.team = "";
}
if (!Empty(scope.team)) {
data.team = scope.team;
data.user = "";
} else {
data.user = scope.user;
data.team = "";
}
data.kind = scope.kind.value;
data.kind = scope.kind.value;
switch (data.kind) {
case 'ssh':
data.password = scope.ssh_password;
break;
case 'aws':
data.username = scope.access_key;
data.password = scope.secret_key;
break;
case 'rax':
data.password = scope.api_key;
break;
case 'gce':
data.username = scope.email_address;
data.project = scope.project;
break;
case 'azure':
data.username = scope.subscription_id;
}
switch (data.kind) {
case 'ssh':
data.password = scope.ssh_password;
break;
case 'aws':
data.username = scope.access_key;
data.password = scope.secret_key;
break;
case 'rax':
data.password = scope.api_key;
break;
case 'gce':
data.username = scope.email_address;
data.project = scope.project;
break;
case 'azure':
data.username = scope.subscription_id;
}
if (Empty(data.team) && Empty(data.user)) {
Alert('Missing User or Team', 'You must provide either a User or a Team. If this credential will only be accessed by a specific ' +
'user, select a User. To allow a team of users to access this credential, select a Team.', 'alert-danger');
} else {
Wait('start');
if (mode === 'add') {
url = (!Empty(data.team)) ? GetBasePath('teams') + data.team + '/credentials/' :
GetBasePath('users') + data.user + '/credentials/';
Rest.setUrl(url);
Rest.post(data)
.success(function () {
Wait('stop');
var base = $location.path().replace(/^\//, '').split('/')[0];
if (base === 'credentials') {
ReturnToCaller();
}
else {
ReturnToCaller(1);
}
})
.error(function (data, status) {
Wait('stop');
ProcessErrors(scope, data, status, form, {
hdr: 'Error!',
msg: 'Failed to create new Credential. POST status: ' + status
});
});
} else {
url = GetBasePath('credentials') + scope.id + '/';
Rest.setUrl(url);
Rest.put(data)
.success(function () {
Wait('stop');
var base = $location.path().replace(/^\//, '').split('/')[0];
if (base === 'credentials') {
ReturnToCaller();
}
else {
ReturnToCaller(1);
}
})
.error(function (data, status) {
Wait('stop');
ProcessErrors(scope, data, status, form, {
hdr: 'Error!',
msg: 'Failed to update Credential. PUT status: ' + status
});
});
}
}
};
}
if (Empty(data.team) && Empty(data.user)) {
Alert('Missing User or Team', 'You must provide either a User or a Team. If this credential will only be accessed by a specific ' +
'user, select a User. To allow a team of users to access this credential, select a Team.', 'alert-danger');
} else {
Wait('start');
if (mode === 'add') {
url = (!Empty(data.team)) ? GetBasePath('teams') + data.team + '/credentials/' :
GetBasePath('users') + data.user + '/credentials/';
Rest.setUrl(url);
Rest.post(data)
.success(function () {
Wait('stop');
var base = $location.path().replace(/^\//, '').split('/')[0];
if (base === 'credentials') {
ReturnToCaller();
}
else {
ReturnToCaller(1);
}
})
.error(function (data, status) {
Wait('stop');
ProcessErrors(scope, data, status, form, {
hdr: 'Error!',
msg: 'Failed to create new Credential. POST status: ' + status
});
});
} else {
url = GetBasePath('credentials') + scope.id + '/';
Rest.setUrl(url);
Rest.put(data)
.success(function () {
Wait('stop');
var base = $location.path().replace(/^\//, '').split('/')[0];
if (base === 'credentials') {
ReturnToCaller();
}
else {
ReturnToCaller(1);
}
})
.error(function (data, status) {
Wait('stop');
ProcessErrors(scope, data, status, form, {
hdr: 'Error!',
msg: 'Failed to update Credential. PUT status: ' + status
});
});
}
}
};
}
]);

View File

@ -11,347 +11,347 @@
*
*/
'use strict';
angular.module('CreateCustomInventoryHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ModalDialog',
'GeneratorHelpers', 'CustomInventoryFormDefinition'])
export default
angular.module('CreateCustomInventoryHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ModalDialog',
'GeneratorHelpers', 'CustomInventoryFormDefinition'])
.factory('CreateCustomInventory', ['Wait', 'CreateDialog', 'CustomInventoryList', 'GenerateList', 'GetBasePath' , 'SearchInit' , 'PaginateInit', 'PlaybookRun', 'CustomInventoryAdd',
'SchedulesList', 'CustomInventoryEdit', 'Rest' , 'ProcessErrors', 'CustomInventoryForm', 'GenerateForm', 'Prompt',
function(Wait, CreateDialog, CustomInventoryList, GenerateList, GetBasePath, SearchInit, PaginateInit, PlaybookRun, CustomInventoryAdd,
SchedulesList, CustomInventoryEdit, Rest, ProcessErrors, CustomInventoryForm, GenerateForm, Prompt) {
return function(params) {
// Set modal dimensions based on viewport width
.factory('CreateCustomInventory', ['Wait', 'CreateDialog', 'CustomInventoryList', 'GenerateList', 'GetBasePath' , 'SearchInit' , 'PaginateInit', 'PlaybookRun', 'CustomInventoryAdd',
'SchedulesList', 'CustomInventoryEdit', 'Rest' , 'ProcessErrors', 'CustomInventoryForm', 'GenerateForm', 'Prompt',
function(Wait, CreateDialog, CustomInventoryList, GenerateList, GetBasePath, SearchInit, PaginateInit, PlaybookRun, CustomInventoryAdd,
SchedulesList, CustomInventoryEdit, Rest, ProcessErrors, CustomInventoryForm, GenerateForm, Prompt) {
return function(params) {
// Set modal dimensions based on viewport width
var scope = params.parent_scope.$new(),
callback = 'OpenConfig',
defaultUrl = GetBasePath('inventory_scripts'),
list = CustomInventoryList,
view = GenerateList,
buttons = [
{
"label": "Close",
"onClick": function() {
// $(this).dialog('close');
var scope = params.parent_scope.$new(),
callback = 'OpenConfig',
defaultUrl = GetBasePath('inventory_scripts'),
list = CustomInventoryList,
view = GenerateList,
buttons = [
{
"label": "Close",
"onClick": function() {
// $(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();
},
"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');
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 });
});
// 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');
}
};
Prompt({
hdr: 'Delete',
body: "<div class\"alert alert-info\">Are you sure you want to delete " + name + "?</div>",
action: action
scope.editCustomInv = function(id){
CustomInventoryEdit({
scope: scope,
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(){
CustomInventoryAdd({
scope: scope
});
// Cancel
scope.formReset = function () {
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',
'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: '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'
});
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();
// Retrieve detail record and prepopulate the form
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
});
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];
}
SearchInit({
scope: scope,
set: 'source_scripts', //'custom_inventories',
list: list,
url: url
});
PaginateInit({
scope: scope,
list: list,
url: url
});
scope.search(list.iterator);
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];
}
}
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 });
msg: 'Failed to retrieve inventory script: ' + $routeParams.id + '. GET status: ' + status });
});
};
// Cancel
scope.formReset = function () {
generator.reset();
};
};
}])
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
});
.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');
SearchInit({
scope: scope,
set: 'source_scripts', //'custom_inventories',
list: list,
url: url
});
PaginateInit({
scope: scope,
list: list,
url: url
});
generator.inject(form, {
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'
});
scope.search(list.iterator);
// Retrieve detail record and prepopulate the form
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];
}
Wait('stop');
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];
}
})
.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];
}
Wait('stop');
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to retrieve inventory script: ' + $routeParams.id + '. GET status: ' + status });
});
scope.organization_name = master.organization_name;
scope.formSave = function () {
generator.clearApiErrors();
Wait('start');
Rest.setUrl(url+ id+'/');
Rest.put({ name: scope.name, description: scope.description, organization: scope.organization, script: scope.script })
.success(function () {
view.inject( list, {
id : 'custom-script-dialog',
mode: 'edit',
scope: scope,
breadCrumbs: false,
activityStream: false,
showSearch: true
});
SearchInit({
scope: scope,
set: 'source_scripts', //'custom_inventories',
list: list,
url: url
});
PaginateInit({
scope: scope,
list: list,
url: url
});
scope.search(list.iterator);
Wait('stop');
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to add new inventory script. PUT returned status: ' + status });
});
};
};
scope.formReset = function () {
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
}
scope.organization_name = master.organization_name;
};
};
}]);
}]);

File diff suppressed because it is too large Load Diff

View File

@ -11,30 +11,54 @@
* @name helpers.function:Events
* @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',
'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'JobEventDataForm', 'Empty', 'JobEventsForm',
function ($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath,
FormatDate, JobEventDataForm, Empty, JobEventsForm) {
return function (params) {
.factory('EventView', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'JobEventDataForm', 'Empty', 'JobEventsForm',
function ($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath,
FormatDate, JobEventDataForm, Empty, JobEventsForm) {
return function (params) {
var event_id = params.event_id,
generator = GenerateForm,
form = angular.copy(JobEventsForm),
scope,
defaultUrl = GetBasePath('base') + 'job_events/' + event_id + '/';
var event_id = params.event_id,
generator = GenerateForm,
form = angular.copy(JobEventsForm),
scope,
defaultUrl = GetBasePath('base') + 'job_events/' + event_id + '/';
// Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl);
Rest.get()
.success(function (data) {
var i, n, fld, rows, txt, cDate;
// Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl);
Rest.get()
.success(function (data) {
var i, n, fld, rows, txt, cDate;
// If event_data is not available, remove fields that depend on it
if ($.isEmptyObject(data.event_data) || !data.event_data.res || typeof data.event_data.res === 'string') {
// If event_data is not available, remove fields that depend on it
if ($.isEmptyObject(data.event_data) || !data.event_data.res || typeof data.event_data.res === 'string') {
for (fld in form.fields) {
switch (fld) {
case 'start':
case 'end':
case 'delta':
case 'msg':
case 'stdout':
case 'stderr':
case 'msg':
case 'results':
case 'module_name':
case 'module_args':
case 'rc':
delete form.fields[fld];
break;
}
}
}
if ($.isEmptyObject(data.event_data) || !data.event_data.res || typeof data.event_data.res !== 'string') {
delete form.fields.traceback;
}
// Remove remaining form fields that do not have a corresponding data value
for (fld in form.fields) {
switch (fld) {
case 'start':
@ -44,196 +68,172 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
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':
case 'rc':
delete form.fields[fld];
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;
}
}
}
if ($.isEmptyObject(data.event_data) || !data.event_data.res || typeof data.event_data.res !== 'string') {
delete form.fields.traceback;
}
// Remove remaining form fields that do not have a corresponding data value
for (fld in form.fields) {
switch (fld) {
case 'start':
case 'end':
case 'delta':
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, {
// load the form
scope = generator.inject(form, {
mode: 'edit',
modal: true,
related: false,
modal_selector: '#form-modal2',
modal_body_id: 'form-modal2-body',
modal_title_id: 'formModal2Header'
related: false
});
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");
scope.formModalAction = function () {
$('#form-modal').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') {
scope.traceback = data.event_data.res;
}
// Respond to View JSON button
scope.formModalInfoAction = function () {
var generator = GenerateForm,
scope = generator.inject(JobEventDataForm, {
mode: 'edit',
modal: true,
related: false,
modal_selector: '#form-modal2',
modal_body_id: 'form-modal2-body',
modal_title_id: 'formModal2Header'
});
generator.reset();
scope.formModal2Header = data.event_display.replace(/^\u00a0*/g, '');
scope.event_data = JSON.stringify(data.event_data, null, '\t');
scope.formModal2ActionLabel = 'OK';
scope.formModal2CancelShow = false;
scope.formModal2Info = false;
scope.formModalInfo = 'View JSON';
scope.formModal2Action = function () {
$('#form-modal2').modal("hide");
};
$('#form-modal2 .btn-success').removeClass('btn-success').addClass('btn-none');
};
for (fld in form.fields) {
switch (fld) {
case 'status':
if (data.failed) {
scope.status = 'error';
} else if (data.changed) {
scope.status = 'changed';
} else {
scope.status = 'success';
}
break;
case '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 (typeof data.event_data.res === 'string') {
scope.traceback = data.event_data.res;
}
}
if (!scope.$$phase) {
scope.$digest();
}
for (fld in form.fields) {
switch (fld) {
case 'status':
if (data.failed) {
scope.status = 'error';
} else if (data.changed) {
scope.status = 'changed';
} else {
scope.status = 'success';
}
break;
case '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];
}
})
.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 });
});
};
}
]);
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) {
scope.$digest();
}
})
.error(function (data, status) {
$('#form-modal').modal("hide");
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to retrieve event: ' + event_id + '. GET status: ' + status });
});
};
}
]);

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -6,13 +6,13 @@
* Routines shared by job related controllers
*
*/
/**
/**
* @ngdoc function
* @name helpers.function:JobTemplatesHelper
* @description Routines shared by job related controllers
*/
'use strict';
*/
export default
angular.module('JobTemplatesHelper', ['Utilities'])
/*
@ -21,181 +21,180 @@ angular.module('JobTemplatesHelper', ['Utilities'])
*/
.factory('CallbackHelpInit', ['$location', 'GetBasePath', 'Rest', 'JobTemplateForm', 'GenerateForm', '$routeParams', 'LoadBreadCrumbs', 'ProcessErrors', 'ParseTypeChange',
'ParseVariableString', 'Empty', 'LookUpInit', 'InventoryList', 'CredentialList','ProjectList', 'RelatedSearchInit', 'RelatedPaginateInit',
function($location, GetBasePath, Rest, JobTemplateForm, GenerateForm, $routeParams, LoadBreadCrumbs, ProcessErrors,ParseTypeChange,
ParseVariableString, Empty, LookUpInit, InventoryList, CredentialList, ProjectList, RelatedSearchInit, RelatedPaginateInit) {
return function(params) {
'ParseVariableString', 'Empty', 'LookUpInit', 'InventoryList', 'CredentialList','ProjectList', 'RelatedSearchInit', 'RelatedPaginateInit',
function($location, GetBasePath, Rest, JobTemplateForm, GenerateForm, $routeParams, LoadBreadCrumbs, ProcessErrors,ParseTypeChange,
ParseVariableString, Empty, LookUpInit, InventoryList, CredentialList, ProjectList, RelatedSearchInit, RelatedPaginateInit) {
return function(params) {
var scope = params.scope,
defaultUrl = GetBasePath('job_templates'),
// generator = GenerateForm,
form = JobTemplateForm(),
// loadingFinishedCount = 0,
// base = $location.path().replace(/^\//, '').split('/')[0],
master = {},
id = $routeParams.template_id,
relatedSets = {};
// checkSCMStatus, getPlaybooks, callback,
// choicesCount = 0;
var scope = params.scope,
defaultUrl = GetBasePath('job_templates'),
// generator = GenerateForm,
form = JobTemplateForm(),
// loadingFinishedCount = 0,
// base = $location.path().replace(/^\//, '').split('/')[0],
master = {},
id = $routeParams.template_id,
relatedSets = {};
// checkSCMStatus, getPlaybooks, callback,
// choicesCount = 0;
// 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.
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 " +
"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 + "\" " +
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 " +
"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>";
};
// 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.
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 " +
"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 + "\" " +
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 " +
"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>";
};
// The md5 helper emits NewMD5Generated whenever a new key is available
if (scope.removeNewMD5Generated) {
scope.removeNewMD5Generated();
}
scope.removeNewMD5Generated = scope.$on('NewMD5Generated', function() {
scope.configKeyChange();
});
// The md5 helper emits NewMD5Generated whenever a new key is available
if (scope.removeNewMD5Generated) {
scope.removeNewMD5Generated();
}
scope.removeNewMD5Generated = scope.$on('NewMD5Generated', function() {
scope.configKeyChange();
});
// Fired when user enters a key value
scope.configKeyChange = function() {
scope.example_config_key = scope.host_config_key;
scope.setCallbackHelp();
};
// Fired when user enters a key value
scope.configKeyChange = function() {
scope.example_config_key = scope.host_config_key;
scope.setCallbackHelp();
};
// Set initial values and construct help text
scope.callback_server_path = $location.protocol() + '://' + $location.host() + (($location.port()) ? ':' + $location.port() : '');
scope.example_config_key = '5a8ec154832b780b9bdef1061764ae5a';
scope.example_template_id = 'N';
scope.setCallbackHelp();
// Set initial values and construct help text
scope.callback_server_path = $location.protocol() + '://' + $location.host() + (($location.port()) ? ':' + $location.port() : '');
scope.example_config_key = '5a8ec154832b780b9bdef1061764ae5a';
scope.example_template_id = 'N';
scope.setCallbackHelp();
scope.fillJobTemplate = function(){
// id = id || $rootScope.copy.id;
// Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl + id);
Rest.get()
.success(function (data) {
var fld, i;
LoadBreadCrumbs({ path: '/job_templates/' + id, title: data.name });
for (fld in form.fields) {
if (fld !== 'variables' && data[fld] !== null && data[fld] !== undefined) {
if (form.fields[fld].type === 'select') {
if (scope[fld + '_options'] && scope[fld + '_options'].length > 0) {
for (i = 0; i < scope[fld + '_options'].length; i++) {
if (data[fld] === scope[fld + '_options'][i].value) {
scope[fld] = scope[fld + '_options'][i];
}
}
} else {
scope[fld] = data[fld];
}
} else {
scope[fld] = data[fld];
if(fld ==='survey_enabled'){
// $scope.$emit('EnableSurvey', fld);
$('#job_templates_survey_enabled_chbox').attr('checked', scope[fld]);
if(Empty(data.summary_fields.survey)) {
$('#job_templates_delete_survey_btn').hide();
$('#job_templates_edit_survey_btn').hide();
$('#job_templates_create_survey_btn').show();
}
else{
$('#job_templates_delete_survey_btn').show();
$('#job_templates_edit_survey_btn').show();
$('#job_templates_create_survey_btn').hide();
scope.survey_exists = true;
}
}
}
master[fld] = scope[fld];
}
if (fld === 'variables') {
// Parse extra_vars, converting to YAML.
scope.variables = ParseVariableString(data.extra_vars);
master.variables = scope.variables;
}
if (form.fields[fld].type === 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) {
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField];
}
}
scope.fillJobTemplate = function(){
// id = id || $rootScope.copy.id;
// Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl + id);
Rest.get()
.success(function (data) {
var fld, i;
LoadBreadCrumbs({ path: '/job_templates/' + id, title: data.name });
for (fld in form.fields) {
if (fld !== 'variables' && data[fld] !== null && data[fld] !== undefined) {
if (form.fields[fld].type === 'select') {
if (scope[fld + '_options'] && scope[fld + '_options'].length > 0) {
for (i = 0; i < scope[fld + '_options'].length; i++) {
if (data[fld] === scope[fld + '_options'][i].value) {
scope[fld] = scope[fld + '_options'][i];
}
}
} else {
scope[fld] = data[fld];
}
} else {
scope[fld] = data[fld];
if(fld ==='survey_enabled'){
// $scope.$emit('EnableSurvey', fld);
$('#job_templates_survey_enabled_chbox').attr('checked', scope[fld]);
if(Empty(data.summary_fields.survey)) {
$('#job_templates_delete_survey_btn').hide();
$('#job_templates_edit_survey_btn').hide();
$('#job_templates_create_survey_btn').show();
}
else{
$('#job_templates_delete_survey_btn').show();
$('#job_templates_edit_survey_btn').show();
$('#job_templates_create_survey_btn').hide();
scope.survey_exists = true;
}
}
}
master[fld] = scope[fld];
}
if (fld === 'variables') {
// Parse extra_vars, converting to YAML.
scope.variables = ParseVariableString(data.extra_vars);
master.variables = scope.variables;
}
if (form.fields[fld].type === 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) {
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField];
}
}
scope.url = data.url;
scope.url = data.url;
scope.ask_variables_on_launch = (data.ask_variables_on_launch) ? 'true' : 'false';
master.ask_variables_on_launch = scope.ask_variables_on_launch;
scope.ask_variables_on_launch = (data.ask_variables_on_launch) ? 'true' : 'false';
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) {
scope.example_config_key = data.host_config_key;
}
scope.example_template_id = id;
scope.setCallbackHelp();
if (data.host_config_key) {
scope.example_config_key = data.host_config_key;
}
scope.example_template_id = id;
scope.setCallbackHelp();
scope.callback_url = scope.callback_server_path + ((data.related.callback) ? data.related.callback :
GetBasePath('job_templates') + id + '/callback/');
master.callback_url = scope.callback_url;
scope.callback_url = scope.callback_server_path + ((data.related.callback) ? data.related.callback :
GetBasePath('job_templates') + id + '/callback/');
master.callback_url = scope.callback_url;
scope.can_edit = data.summary_fields.can_edit;
scope.can_edit = data.summary_fields.can_edit;
LookUpInit({
scope: scope,
form: form,
current_item: data.inventory,
list: InventoryList,
field: 'inventory',
input_type: "radio"
});
LookUpInit({
scope: scope,
form: form,
current_item: data.inventory,
list: InventoryList,
field: 'inventory',
input_type: "radio"
});
LookUpInit({
url: GetBasePath('credentials') + '?kind=ssh',
scope: scope,
form: form,
current_item: data.credential,
list: CredentialList,
field: 'credential',
hdr: 'Select Machine Credential',
input_type: "radio"
});
LookUpInit({
url: GetBasePath('credentials') + '?kind=ssh',
scope: scope,
form: form,
current_item: data.credential,
list: CredentialList,
field: 'credential',
hdr: 'Select Machine Credential',
input_type: "radio"
});
LookUpInit({
scope: scope,
form: form,
current_item: data.project,
list: ProjectList,
field: 'project',
input_type: "radio"
});
LookUpInit({
scope: scope,
form: form,
current_item: data.project,
list: ProjectList,
field: 'project',
input_type: "radio"
});
RelatedSearchInit({
scope: scope,
form: form,
relatedSets: relatedSets
});
RelatedSearchInit({
scope: scope,
form: form,
relatedSets: relatedSets
});
RelatedPaginateInit({
scope: scope,
relatedSets: relatedSets
});
RelatedPaginateInit({
scope: scope,
relatedSets: relatedSets
});
scope.$emit('jobTemplateLoaded', data.related.cloud_credential, master);
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, {
hdr: 'Error!',
msg: 'Failed to retrieve job template: ' + $routeParams.template_id + '. GET status: ' + status
});
});
};
scope.$emit('jobTemplateLoaded', data.related.cloud_credential, master);
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, {
hdr: 'Error!',
msg: 'Failed to retrieve job template: ' + $routeParams.template_id + '. GET status: ' + status
});
});
};
};
};
}]);
}]);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -9,374 +9,374 @@
* @name helpers.function: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',
'LogViewerOptionsForm', 'EnvTable', 'GetBasePath', 'LookUpName', 'Empty', 'AddPreFormattedText', 'ParseVariableString', 'GetChoices',
function($location, $compile, CreateDialog, GetJob, Wait, GenerateForm, LogViewerStatusForm, AddTable, AddTextarea, LogViewerOptionsForm, EnvTable,
GetBasePath, LookUpName, Empty, AddPreFormattedText, ParseVariableString, GetChoices) {
return function(params) {
var parent_scope = params.scope,
url = params.url,
getIcon = params.getIcon,
scope = parent_scope.$new(true),
base = $location.path().replace(/^\//, '').split('/')[0],
pieces;
.factory('LogViewer', ['$location', '$compile', 'CreateDialog', 'GetJob', 'Wait', 'GenerateForm', 'LogViewerStatusForm', 'AddTable', 'AddTextarea',
'LogViewerOptionsForm', 'EnvTable', 'GetBasePath', 'LookUpName', 'Empty', 'AddPreFormattedText', 'ParseVariableString', 'GetChoices',
function($location, $compile, CreateDialog, GetJob, Wait, GenerateForm, LogViewerStatusForm, AddTable, AddTextarea, LogViewerOptionsForm, EnvTable,
GetBasePath, LookUpName, Empty, AddPreFormattedText, ParseVariableString, GetChoices) {
return function(params) {
var parent_scope = params.scope,
url = params.url,
getIcon = params.getIcon,
scope = parent_scope.$new(true),
base = $location.path().replace(/^\//, '').split('/')[0],
pieces;
if (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] = '';
if (scope.removeModalReady) {
scope.removeModalReady();
}
scope.removeModalReady = scope.$on('ModalReady', function() {
Wait('stop');
$('#logviewer-modal-dialog').dialog('open');
});
for (key in data) {
scope[key] = data[key];
if (scope.removeJobReady) {
scope.removeJobReady();
}
scope.created_by = '';
scope.job_template = '';
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();
if (data.related.created_by) {
pieces = data.related.created_by.replace(/^\//,'').replace(/\/$/,'').split('/');
scope.created_by = parseInt(pieces[pieces.length - 1],10);
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;
// Make sure subsequenct scope references don't bubble up to the parent
for (key in LogViewerStatusForm.fields) {
scope[key] = '';
}
if (data.type === 'project_update') {
scope.name_link = "project";
scope.name_id = data.unified_job_template;
for (key in LogViewerOptionsForm.fields) {
scope[key] = '';
}
if (data.type === 'inventory_update') {
scope.name_link = "inventory_source";
scope.name_id = scope.group;
for (key in data) {
scope[key] = data[key];
}
}
scope.created_by = '';
scope.job_template = '';
AddTable({ scope: scope, form: LogViewerStatusForm, id: 'status-form-container', getIcon: getIcon });
AddTable({ scope: scope, form: LogViewerOptionsForm, id: 'options-form-container', getIcon: getIcon });
if (data.result_stdout) {
$('#logview-tabs li:eq(1)').show();
AddPreFormattedText({
id: 'stdout-form-container',
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;
if (data.related.created_by) {
pieces = data.related.created_by.replace(/^\//,'').replace(/\/$/,'').split('/');
scope.created_by = parseInt(pieces[pieces.length - 1],10);
LookUpName({
scope: scope,
scope_var: 'created_by',
url: GetBasePath('users') + scope.created_by + '/'
});
});
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 + '/'
});
}
// 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') {
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)) {
LookUpName({
scope: scope,
scope_var: 'inventory',
url: GetBasePath('inventory') + scope.inventory + '/'
});
}
AddTable({ scope: scope, form: LogViewerStatusForm, id: 'status-form-container', getIcon: getIcon });
AddTable({ scope: scope, form: LogViewerOptionsForm, id: 'options-form-container', getIcon: getIcon });
if (!Empty(scope.project)) {
LookUpName({
scope: scope,
scope_var: 'project',
url: GetBasePath('projects') + scope.project + '/'
});
}
if (data.result_stdout) {
$('#logview-tabs li:eq(1)').show();
AddPreFormattedText({
id: 'stdout-form-container',
val: data.result_stdout
});
}
if (!Empty(scope.cloud_credential)) {
LookUpName({
scope: scope,
scope_var: 'cloud_credential',
url: GetBasePath('credentials') + scope.cloud_credential + '/'
});
}
if (data.result_traceback) {
$('#logview-tabs li:eq(2)').show();
AddPreFormattedText({
id: 'traceback-form-container',
val: data.result_traceback
});
}
if (!Empty(scope.inventory_source)) {
LookUpName({
scope: scope,
scope_var: 'inventory_source',
url: GetBasePath('inventory_sources') + scope.inventory_source + '/'
});
}
/*if (data.job_env) {
EnvTable({
id: 'env-form-container',
vars: data.job_env
});
}*/
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 });
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)) {
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) {
return function(params) {
var url = params.url,
scope = params.scope;
Rest.setUrl(url);
Rest.get()
.success(function(data){
scope.$emit('JobReady', data);
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve ' + url + '. GET returned: ' + status });
});
};
}])
.factory('GetJob', ['Rest', 'ProcessErrors', function(Rest, ProcessErrors) {
return function(params) {
var url = params.url,
scope = params.scope;
Rest.setUrl(url);
Rest.get()
.success(function(data){
scope.$emit('JobReady', data);
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve ' + url + '. GET returned: ' + status });
});
};
}])
.factory('LookUpName', ['Rest', 'ProcessErrors', 'Empty', function(Rest, ProcessErrors, Empty) {
return function(params) {
var url = params.url,
scope_var = params.scope_var,
scope = params.scope;
Rest.setUrl(url);
Rest.get()
.success(function(data) {
if (scope_var === 'inventory_source') {
scope[scope_var + '_name'] = data.summary_fields.group.name;
}
else if (!Empty(data.name)) {
scope[scope_var + '_name'] = data.name;
}
if (!Empty(data.group)) {
// Used for inventory_source
scope.group = data.group;
}
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve ' + url + '. GET returned: ' + status });
});
};
}])
.factory('LookUpName', ['Rest', 'ProcessErrors', 'Empty', function(Rest, ProcessErrors, Empty) {
return function(params) {
var url = params.url,
scope_var = params.scope_var,
scope = params.scope;
Rest.setUrl(url);
Rest.get()
.success(function(data) {
if (scope_var === 'inventory_source') {
scope[scope_var + '_name'] = data.summary_fields.group.name;
}
else if (!Empty(data.name)) {
scope[scope_var + '_name'] = data.name;
}
if (!Empty(data.group)) {
// Used for inventory_source
scope.group = data.group;
}
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve ' + url + '. GET returned: ' + status });
});
};
}])
.factory('AddTable', ['$compile', 'Empty', 'Find', function($compile, Empty, Find) {
return function(params) {
var form = params.form,
id = params.id,
scope = params.scope,
getIcon = params.getIcon,
fld, html, url, e,
urls = [
{ "variable": "credential", "url": "/#/credentials/" },
{ "variable": "project", "url": "/#/projects/" },
{ "variable": "inventory", "url": "/#/inventories/" },
{ "variable": "cloud_credential", "url": "/#/credentials/" },
{ "variable": "inventory_source", "url": "/#/home/groups/?id={{ group }}" },
{ "variable": "job_template", "url": "/#/job_templates/" },
{ "variable": "created_by", "url": "/#/users/" }
];
html = "<table class=\"table logviewer-status\">\n";
for (fld in form.fields) {
if (!Empty(scope[fld])) {
html += "<tr><td class=\"fld-label col-md-3 col-sm-3 col-xs-3\">" + form.fields[fld].label + "</td>" +
"<td>";
url = Find({ list: urls, key: "variable", val: fld });
if (url) {
html += "<a href=\"" + url.url;
html += (fld === "inventory_source") ? "" : scope[fld];
html += "\" ng-click=\"modalOK()\">{{ " + fld + '_name' + " }}</a>";
}
else if (fld === 'name' && 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()\">{{ " +
( (scope.name_link === 'inventory_source') ? 'inventory_source_name' : fld ) + " }}</a>";
}
else if (fld === 'elapsed') {
html += scope[fld] + " <span class=\"small-text\">seconds</span>";
}
else if (fld === 'status') {
if (getIcon) {
html += "<i class=\"fa icon-job-" + getIcon(scope[fld]) + "\"></i> " + scope[fld];
.factory('AddTable', ['$compile', 'Empty', 'Find', function($compile, Empty, Find) {
return function(params) {
var form = params.form,
id = params.id,
scope = params.scope,
getIcon = params.getIcon,
fld, html, url, e,
urls = [
{ "variable": "credential", "url": "/#/credentials/" },
{ "variable": "project", "url": "/#/projects/" },
{ "variable": "inventory", "url": "/#/inventories/" },
{ "variable": "cloud_credential", "url": "/#/credentials/" },
{ "variable": "inventory_source", "url": "/#/home/groups/?id={{ group }}" },
{ "variable": "job_template", "url": "/#/job_templates/" },
{ "variable": "created_by", "url": "/#/users/" }
];
html = "<table class=\"table logviewer-status\">\n";
for (fld in form.fields) {
if (!Empty(scope[fld])) {
html += "<tr><td class=\"fld-label col-md-3 col-sm-3 col-xs-3\">" + form.fields[fld].label + "</td>" +
"<td>";
url = Find({ list: urls, key: "variable", val: fld });
if (url) {
html += "<a href=\"" + url.url;
html += (fld === "inventory_source") ? "" : scope[fld];
html += "\" ng-click=\"modalOK()\">{{ " + fld + '_name' + " }}</a>";
}
else if (fld === 'name' && 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()\">{{ " +
( (scope.name_link === 'inventory_source') ? 'inventory_source_name' : fld ) + " }}</a>";
}
else if (fld === 'elapsed') {
html += scope[fld] + " <span class=\"small-text\">seconds</span>";
}
else if (fld === 'status') {
if (getIcon) {
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 {
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>";
html += "{{ " + fld ;
html += (form.fields[fld].filter) ? " | " + form.fields[fld].filter : "" ;
html += " }}";
}
html += "</td></tr>\n";
}
else {
html += "{{ " + fld ;
html += (form.fields[fld].filter) ? " | " + form.fields[fld].filter : "" ;
html += " }}";
}
html += "</td></tr>\n";
}
}
html += "</table>\n";
e = angular.element(document.getElementById(id));
e.empty().html(html);
$compile(e)(scope);
};
}])
html += "</table>\n";
e = angular.element(document.getElementById(id));
e.empty().html(html);
$compile(e)(scope);
};
}])
.factory('AddTextarea', [ function() {
return function(params) {
var container_id = params.container_id,
val = params.val,
fld_id = params.fld_id,
html;
html = "<div class=\"form-group\">\n" +
"<textarea id=\"" + fld_id + "\" ng-non-bindable class=\"form-control mono-space\" rows=\"12\" readonly>" + val + "</textarea>" +
"</div>\n";
$('#' + container_id).empty().html(html);
};
}])
.factory('AddTextarea', [ function() {
return function(params) {
var container_id = params.container_id,
val = params.val,
fld_id = params.fld_id,
html;
html = "<div class=\"form-group\">\n" +
"<textarea id=\"" + fld_id + "\" ng-non-bindable class=\"form-control mono-space\" rows=\"12\" readonly>" + val + "</textarea>" +
"</div>\n";
$('#' + container_id).empty().html(html);
};
}])
.factory('AddPreFormattedText', [function() {
return function(params) {
var id = params.id,
val = params.val,
html;
html = "<pre ng-non-bindable>" + val + "</pre>\n";
$('#' + id).empty().html(html);
};
}])
.factory('AddPreFormattedText', [function() {
return function(params) {
var id = params.id,
val = params.val,
html;
html = "<pre ng-non-bindable>" + val + "</pre>\n";
$('#' + id).empty().html(html);
};
}])
.factory('EnvTable', [ function() {
return function(params) {
var id = params.id,
vars = params.vars,
key, html;
html = "<table class=\"table logviewer-status\">\n";
for (key in vars) {
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";
}
html += "</table>\n";
$('#' + id).empty().html(html);
};
}]);
.factory('EnvTable', [ function() {
return function(params) {
var id = params.id,
vars = params.vars,
key, html;
html = "<table class=\"table logviewer-status\">\n";
for (key in vars) {
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";
}
html += "</table>\n";
$('#' + id).empty().html(html);
};
}]);

View File

@ -22,229 +22,229 @@
* })
*/
'use strict';
angular.module('LookUpHelper', ['RestServices', 'Utilities', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ApiLoader', 'ModalDialog'])
export default
angular.module('LookUpHelper', ['RestServices', 'Utilities', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ApiLoader', 'ModalDialog'])
.factory('LookUpInit', ['Alert', 'Rest', 'GenerateList', 'SearchInit', 'PaginateInit', 'GetBasePath', 'FormatDate', 'Empty', 'CreateDialog',
function (Alert, Rest, GenerateList, SearchInit, PaginateInit, GetBasePath, FormatDate, Empty, CreateDialog) {
return function (params) {
.factory('LookUpInit', ['Alert', 'Rest', 'GenerateList', 'SearchInit', 'PaginateInit', 'GetBasePath', 'FormatDate', 'Empty', 'CreateDialog',
function (Alert, Rest, GenerateList, SearchInit, PaginateInit, GetBasePath, FormatDate, Empty, CreateDialog) {
return function (params) {
var parent_scope = params.scope,
form = params.form,
list = params.list,
field = params.field,
instructions = params.instructions,
postAction = params.postAction,
callback = params.callback,
input_type = (params.input_type) ? params.input_type: "checkbox",
defaultUrl, name, watchUrl;
var parent_scope = params.scope,
form = params.form,
list = params.list,
field = params.field,
instructions = params.instructions,
postAction = params.postAction,
callback = params.callback,
input_type = (params.input_type) ? params.input_type: "checkbox",
defaultUrl, name, watchUrl;
if (params.url) {
// pass in a url value to override the default
defaultUrl = params.url;
} else {
defaultUrl = (list.name === 'inventories') ? GetBasePath('inventory') : GetBasePath(list.name);
}
if (params.url) {
// pass in a url value to override the default
defaultUrl = params.url;
} else {
defaultUrl = (list.name === 'inventories') ? GetBasePath('inventory') : GetBasePath(list.name);
}
if ($('#htmlTemplate #lookup-modal-dialog').length > 0) {
$('#htmlTemplate #lookup-modal-dialog').empty();
}
else {
$('#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
});
if ($('#htmlTemplate #lookup-modal-dialog').length > 0) {
$('#htmlTemplate #lookup-modal-dialog').empty();
}
else {
$('#htmlTemplate').append("<div id=\"lookup-modal-dialog\"></div>");
}
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');
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);
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();
}
},{
label: "Select",
onClick: function() {
scope.selectAction();
},
icon: "fa-check",
"class": "btn btn-primary",
"id": "lookup-save-button"
}];
scope.removeModalReady = scope.$on('ModalReady', function() {
$('#lookup-save-button').attr('disabled','disabled');
$('#lookup-modal-dialog').dialog('open');
});
if (scope.removeModalReady) {
scope.removeModalReady();
}
scope.removeModalReady = scope.$on('ModalReady', function() {
$('#lookup-save-button').attr('disabled','disabled');
$('#lookup-modal-dialog').dialog('open');
});
CreateDialog({
scope: scope,
buttons: buttons,
width: 600,
height: (instructions) ? 625 : 500,
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({
scope: scope,
buttons: buttons,
width: 600,
height: (instructions) ? 625 : 500,
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];
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 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 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;
}
});
if (!Empty(scope[field])) {
scope['toggle_' + list.iterator](scope[field]);
}
}
});
if (!Empty(scope[field])) {
scope['toggle_' + list.iterator](scope[field]);
}
scope.search(list.iterator);
});
scope.search(list.iterator);
scope.selectAction = function () {
var i, found = false;
for (i = 0; i < scope[list.name].length; i++) {
if (scope[list.name][i].checked === '1' || scope[list.name][i].checked===1) {
found = true;
parent_scope[field] = scope[list.name][i].id;
if (parent_scope[form.name + '_form'] && form.fields[field] && form.fields[field].sourceModel) {
parent_scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] =
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]
.$setValidity('awlookup', true);
scope.selectAction = function () {
var i, found = false;
for (i = 0; i < scope[list.name].length; i++) {
if (scope[list.name][i].checked === '1' || scope[list.name][i].checked===1) {
found = true;
parent_scope[field] = scope[list.name][i].id;
if (parent_scope[form.name + '_form'] && form.fields[field] && form.fields[field].sourceModel) {
parent_scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] =
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]
.$setValidity('awlookup', true);
}
}
if (parent_scope[form.name + '_form']) {
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) {
var count = 0;
scope[list.name].forEach( function(row, i) {
if (row.id === id) {
if (row.checked === '0') {
scope[list.name][i].checked = '1';
scope[list.name][i].success_class = 'success';
}
else {
scope['toggle_' + list.iterator] = function (id) {
var count = 0;
scope[list.name].forEach( function(row, i) {
if (row.id === id) {
if (row.checked === '0') {
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 = '';
}
} else {
scope[list.name][i].checked = '0';
scope[list.name][i].success_class = '';
}
} else {
scope[list.name][i].checked = '0';
scope[list.name][i].success_class = '';
});
// Check if any rows are checked
scope[list.name].forEach(function(row) {
if (row.checked === '1') {
count++;
}
});
if (count === 0) {
$('#lookup-save-button').attr('disabled','disabled');
}
});
// Check if any rows are checked
scope[list.name].forEach(function(row) {
if (row.checked === '1') {
count++;
else {
$('#lookup-save-button').removeAttr('disabled');
}
});
if (count === 0) {
$('#lookup-save-button').attr('disabled','disabled');
}
else {
$('#lookup-save-button').removeAttr('disabled');
}
};
};
};
};
}]);
}]);

View File

@ -9,156 +9,156 @@
* @name helpers.function:PaginationHelpers
* @description pagination
*/
'use strict';
angular.module('PaginationHelpers', ['Utilities', 'RefreshHelper', 'RefreshRelatedHelper'])
export default
angular.module('PaginationHelpers', ['Utilities', 'RefreshHelper', 'RefreshRelatedHelper'])
.factory('PageRangeSetup', ['Empty',
function (Empty) {
return function (params) {
.factory('PageRangeSetup', ['Empty',
function (Empty) {
return function (params) {
var scope = params.scope,
count = params.count,
next = params.next,
previous = params.previous,
iterator = params.iterator,
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
var scope = params.scope,
count = params.count,
next = params.next,
previous = params.previous,
iterator = params.iterator,
i, first, last;
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
$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');
// 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);
}
Refresh({ scope: scope, set: set, iterator: iterator, url: new_url });
};
};
}
]);
}
])
.factory('RelatedPaginateInit', ['RefreshRelated', '$cookieStore', 'Wait',
function (RefreshRelated, $cookieStore, Wait) {
return function (params) {
var scope = params.scope,
relatedSets = params.relatedSets,
pageSize = (params.pageSize) ? params.pageSize : 10,
key;
for (key in relatedSets) {
scope[relatedSets[key].iterator + '_url'] = relatedSets[key].url;
scope[relatedSets[key].iterator + '_page'] = 0;
scope[relatedSets[key].iterator + '_page_size'] = pageSize;
}
scope.getPage = function (page, set, iterator) {
var new_url = scope[iterator + '_url'].replace(/.page\=\d+/, ''),
connect = (/\/$/.test(new_url)) ? '?' : '&';
new_url += connect + 'page=' + page;
new_url += (scope[iterator + 'SearchParams']) ? '&' + scope[iterator + 'SearchParams'] +
'&page_size=' + scope[iterator + '_page_size'] : 'page_size=' + scope[iterator + 'PageSize'];
Wait('start');
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: new_url });
};
scope.pageIsActive = function (page, iterator) {
return (page === scope[iterator + '_page']) ? 'active' : '';
};
scope.changePageSize = function (set, iterator) {
// Called when a new page size is selected
scope[iterator + '_page'] = 1;
var url = scope[iterator + '_url'];
// Using the session cookie, keep track of user rows per page selection
$cookieStore.put(iterator + '_page_size', scope[iterator + '_page_size']);
url = url.replace(/\/\?.*$/, '/');
url += (scope[iterator + 'SearchParams']) ? '?' + scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + '_page_size'] :
'?page_size=' + scope[iterator + '_page_size'];
RefreshRelated({
scope: scope,
set: set,
iterator: iterator,
url: url
});
};
};
}
])
.factory('PaginateInit', ['Refresh', '$cookieStore', 'Wait',
function (Refresh, $cookieStore, Wait) {
return function (params) {
var scope = params.scope,
list = params.list,
iterator = (params.iterator) ? params.iterator : list.iterator,
pageSize = params.pageSize,
mode = (params.mode) ? params.mode : null;
scope[iterator + '_page'] = (params.page) ? params.page : 1;
scope[iterator + '_url'] = params.url;
scope[iterator + '_mode'] = mode;
if (pageSize) {
scope[iterator + '_page_size'] = params.pageSize;
} else if (mode === 'lookup') {
scope[iterator + '_page_size'] = 5;
} else {
scope[iterator + '_page_size'] = 20;
}
scope.getPage = function (page, set, iterator) {
var new_url = scope[iterator + '_url'].replace(/.page\=\d+/, ''),
connect = (/\/$/.test(new_url)) ? '?' : '&';
new_url += connect + 'page=' + page;
new_url += (scope[iterator + 'SearchParams']) ? '&' + scope[iterator + 'SearchParams'] +
'&page_size=' + scope[iterator + '_page_size'] : '&page_size=' + scope[iterator + 'PageSize'];
Wait('start');
Refresh({ scope: scope, set: set, iterator: iterator, url: new_url });
};
scope.pageIsActive = function (page, iterator) {
return (page === scope[iterator + '_page']) ? 'active' : '';
};
scope.changePageSize = function (set, iterator, spinner) {
// Called whenever a new page size is selected
scope[iterator + '_page'] = 1;
var new_url = scope[iterator + '_url'].replace(/\?page_size\=\d+/, ''),
connect = (/\/$/.test(new_url)) ? '?' : '&';
new_url += (scope[iterator + 'SearchParams']) ? connect + scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + '_page_size'] :
connect + 'page_size=' + scope[iterator + '_page_size'];
if (spinner === undefined || spinner === true) {
Wait('start');
}
Refresh({ scope: scope, set: set, iterator: iterator, url: new_url });
};
};
}
]);

View File

@ -12,87 +12,87 @@
*
*/
'use strict';
angular.module('ParseHelper', ['Utilities', 'AngularCodeMirrorModule'])
.factory('ParseTypeChange', ['Alert', 'AngularCodeMirror', function (Alert, AngularCodeMirror) {
return function (params) {
export default
angular.module('ParseHelper', ['Utilities', 'AngularCodeMirrorModule'])
.factory('ParseTypeChange', ['Alert', 'AngularCodeMirror', function (Alert, AngularCodeMirror) {
return function (params) {
var scope = params.scope,
field_id = params.field_id,
fld = (params.variable) ? params.variable : 'variables',
pfld = (params.parse_variable) ? params.parse_variable : 'parseType',
onReady = params.onReady,
onChange = params.onChange;
var scope = params.scope,
field_id = params.field_id,
fld = (params.variable) ? params.variable : 'variables',
pfld = (params.parse_variable) ? params.parse_variable : 'parseType',
onReady = params.onReady,
onChange = params.onChange;
function removeField() {
//set our model to the last change in CodeMirror and then destroy CodeMirror
scope[fld] = scope.codeMirror.getValue();
function removeField() {
//set our model to the last change in CodeMirror and then destroy CodeMirror
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,
// // 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) {
// var self = scope.codeMirror;
// $('.CodeMirror:eq(1)').empty().remove();
// if (self.element) {
// self.element.show();
// }
// }
// else
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);
}
// 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.
// if( $(".CodeMirror").length >1) {
// var self = scope.codeMirror;
// $('.CodeMirror:eq(1)').empty().remove();
// if (self.element) {
// self.element.show();
// }
// }
// else
scope.codeMirror.destroy();
}
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 );
}
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
try {
removeField();
json_obj = JSON.parse(scope[fld]);
if ($.isEmptyObject(json_obj)) {
scope[fld] = '---';
}
else {
scope[fld] = jsyaml.safeDump(json_obj);
}
createField();
}
catch (e) {
Alert('Parse Error', 'Failed to parse valid JSON. ' + e.message);
setTimeout( function() { scope.$apply( function() { scope[pfld] = 'json'; createField(); }); }, 500 );
}
}
};
};
};
}
]);
}
]);

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -10,388 +10,388 @@
* for the menu piece. The routine for building the menu is in InventoriesEdit controller
* (controllers/Inventories.js)
*/
'use strict';
angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationListDefinition', 'ListGenerator', 'AuthService',
'InventoryHelper', 'InventoryFormDefinition', 'ParseHelper', 'SearchHelper', 'VariablesHelper',
])
export default
angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationListDefinition', 'ListGenerator', 'AuthService',
'InventoryHelper', 'InventoryFormDefinition', 'ParseHelper', 'SearchHelper', 'VariablesHelper',
])
.factory('GetGroupContainerHeight', [ function() {
return function() {
.factory('GetGroupContainerHeight', [ function() {
return function() {
/*console.log('window height: ' + $(window).height());
console.log('main-menu: ' + $('.main-menu').outerHeight());
console.log('main_tabs: ' + $('#main_tabs').outerHeight());
console.log('breadcrumbs: ' + $('#breadcrumbs').outerHeight());
console.log('footer: ' + $('.site-footer').outerHeight());
console.log('group-breadcrumbs: ' + $('.group-breadcrumbs').outerHeight());
console.log('searchwidget: ' + $('#groups-container #search-widget-container').outerHeight());
console.log('group table head: ' + $('#groups_table thead').height());
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() -
$('#groups_table thead').height() ));
*/
var height = $(window).height() - $('#main-menu-container .navbar').outerHeight() - $('#breadcrumbs').outerHeight() -
$('.site-footer').outerHeight() - $('.group-breadcrumbs').outerHeight() - $('#groups-container #search-widget-container').outerHeight() -
$('#groups_table thead').height() - 90;
height = (height < 600) ? 600 : 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));
/*console.log('window height: ' + $(window).height());
console.log('main-menu: ' + $('.main-menu').outerHeight());
console.log('main_tabs: ' + $('#main_tabs').outerHeight());
console.log('breadcrumbs: ' + $('#breadcrumbs').outerHeight());
console.log('footer: ' + $('.site-footer').outerHeight());
console.log('group-breadcrumbs: ' + $('.group-breadcrumbs').outerHeight());
console.log('searchwidget: ' + $('#groups-container #search-widget-container').outerHeight());
console.log('group table head: ' + $('#groups_table thead').height());
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() -
$('#groups_table thead').height() ));
*/
var height = $(window).height() - $('#main-menu-container .navbar').outerHeight() - $('#breadcrumbs').outerHeight() -
$('.site-footer').outerHeight() - $('.group-breadcrumbs').outerHeight() - $('#groups-container #search-widget-container').outerHeight() -
$('#groups_table thead').height() - 90;
height = (height < 600) ? 600 : height;
return height;
};
}
])
}])
.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) {
.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;
};
}])
// 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,
form = InventoryForm,
defaultUrl = GetBasePath('inventory'),
fld, json_data, data;
.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;
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
json_data = ToJSON(scope.parseType, scope.variables);
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);
}
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 (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',
'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) {
scope.removeUpdateInventoryVariables();
}
scope.removeUpdateInventoryVariables = scope.$on('UpdateInventoryVariables', function(e, data) {
Rest.setUrl(data.related.variable_data);
Rest.put(json_data)
.success(function () {
Wait('stop');
scope.$emit('InventorySaved');
if (scope.removeUpdateInventoryVariables) {
scope.removeUpdateInventoryVariables();
}
scope.removeUpdateInventoryVariables = scope.$on('UpdateInventoryVariables', function(e, data) {
Rest.setUrl(data.related.variable_data);
Rest.put(json_data)
.success(function () {
Wait('stop');
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) {
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)
.success(function (data) {
if (scope.variables) {
scope.$emit('UpdateInventoryVariables', data);
} else {
scope.$emit('InventorySaved');
}
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to update inventory. PUT returned status: ' + status });
.factory('EditInventoryProperties', ['InventoryForm', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList',
'GetBasePath', 'ParseTypeChange', 'SaveInventory', 'Wait', 'Store', 'SearchInit', 'ParseVariableString', 'CreateDialog', 'TextareaResize',
function (InventoryForm, GenerateForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, SaveInventory,
Wait, Store, SearchInit, ParseVariableString, CreateDialog, TextareaResize) {
return function (params) {
var parent_scope = params.scope,
inventory_id = params.inventory_id,
generator = GenerateForm,
form = InventoryForm,
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',
'GetBasePath', 'ParseTypeChange', 'SaveInventory', 'Wait', 'Store', 'SearchInit', 'ParseVariableString', 'CreateDialog', 'TextareaResize',
function (InventoryForm, GenerateForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, SaveInventory,
Wait, Store, SearchInit, ParseVariableString, CreateDialog, TextareaResize) {
return function (params) {
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"
}];
var parent_scope = params.scope,
inventory_id = params.inventory_id,
generator = GenerateForm,
form = InventoryForm,
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;
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) {
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();
},
onOpen: function() {
$('#inventory_name').focus();
setTimeout(function() {
$('#inventory-edit-modal-dialog').empty();
},
onResizeStop: function() {
TextareaResize({
scope: scope,
textareaId: 'inventory_variables',
modalId: 'inventory-edit-modal-dialog',
formId: 'inventory_form',
parse: true
formId: 'inventory_form'
});
}, 300);
},
callback: 'InventoryEditDialogReady'
});
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];
},
beforeDestroy: function() {
if (scope.codeMirror) {
scope.codeMirror.destroy();
}
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 });
$('#inventory-edit-modal-dialog').empty();
},
onOpen: function() {
$('#inventory_name').focus();
setTimeout(function() {
TextareaResize({
scope: scope,
textareaId: 'inventory_variables',
modalId: 'inventory-edit-modal-dialog',
formId: 'inventory_form',
parse: true
});
}, 300);
},
callback: 'InventoryEditDialogReady'
});
if (scope.removeInventorySaved) {
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.parseType = 'yaml';
scope.cancelModal = function () {
// Restore prior search state
/*if (scope.searchCleanp) {
scope.searchCleanup();
if (scope.removeInventoryPropertiesLoaded) {
scope.removeInventoryPropertiesLoaded();
}
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');
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 &&
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) {
// ignore
}
scope.$destroy();
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 () {
// Restore prior search state
/*if (scope.searchCleanp) {
scope.searchCleanup();
}
SearchInit({
scope: parent_scope,
set: PreviousSearchParams.set,
list: PreviousSearchParams.list,
url: PreviousSearchParams.defaultUrl,
iterator: PreviousSearchParams.iterator,
sort_order: PreviousSearchParams.sort_order,
setWidgets: false
});*/
try {
$('#inventory-edit-modal-dialog').dialog('close');
}
catch(err) {
// ignore
}
scope.$destroy();
};
scope.saveModal = function () {
scope.inventory_id = inventory_id;
SaveInventory({ scope: scope, parent_scope: parent_scope });
};
};
scope.saveModal = function () {
scope.inventory_id = inventory_id;
SaveInventory({ scope: scope, parent_scope: parent_scope });
};
};
}
]);
}
]);

View File

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

View File

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

View File

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

View File

@ -19,260 +19,260 @@
*
*/
'use strict';
angular.module('RelatedSearchHelper', ['RestServices', 'Utilities', 'RefreshRelatedHelper'])
.factory('RelatedSearchInit', ['$timeout', 'Alert', 'Rest', 'RefreshRelated', 'Wait', 'Empty',
function ($timeout, Alert, Rest, RefreshRelated, Wait, Empty) {
return function (params) {
export default
angular.module('RelatedSearchHelper', ['RestServices', 'Utilities', 'RefreshRelatedHelper'])
.factory('RelatedSearchInit', ['$timeout', 'Alert', 'Rest', 'RefreshRelated', 'Wait', 'Empty',
function ($timeout, Alert, Rest, RefreshRelated, Wait, Empty) {
return function (params) {
var scope = params.scope,
relatedSets = params.relatedSets,
form = params.form, f;
var scope = params.scope,
relatedSets = params.relatedSets,
form = params.form, f;
// add 'selected' class to the selected li element
function setSelectedItem(iterator, label) {
$('#' + iterator + 'SearchDropdown' + ' li').each(function() {
$(this).removeClass('selected');
var link = $(this).find('a');
if (label === link.text()) {
$(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;
}
// add 'selected' class to the selected li element
function setSelectedItem(iterator, label) {
$('#' + iterator + 'SearchDropdown' + ' li').each(function() {
$(this).removeClass('selected');
var link = $(this).find('a');
if (label === link.text()) {
$(this).addClass('selected');
}
});
}
if (Empty(scope[iterator + 'SearchField'])) {
// A field marked as key may not be 'searchable'. Find the first searchable field.
// 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].searchable === undefined || form.related[set].fields[fld].searchable === true) {
scope[iterator + 'SearchField'] = fld;
scope[iterator + 'SearchFieldLabel'] = form.related[set].fields[fld].label;
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;
}
}
}
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']);
}
}
}
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;
if (Empty(scope[iterator + 'SearchField'])) {
// A field marked as key may not be 'searchable'. Find the first searchable field.
for (fld in form.related[set].fields) {
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;
}
}
}
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'];
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 {
scope[iterator + 'SearchParams'] = scope[iterator + 'SearchField'] + '__';
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];
}
}
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'] + '=';
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 && (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']);
if (f.searchType !== undefined && f.searchType === 'int') {
//scope[iterator + 'HideSearchType'] = true;
scope[iterator + 'SearchType'] = 'int';
}
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) {
var sort_order, icon, direction, set;
scope.search(iterator);
// 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');
};
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);
}
});
};
// 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');
}
scope.search = function (iterator) {
//scope[iterator + 'SearchSpin'] = true;
Wait('start');
scope[iterator + 'Loading'] = false;
scope[iterator + 'HoldInput'] = true;
// 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;
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;
}
}
}
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 {
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.search(iterator);
scope[iterator + 'SortOrder'] = sort_order;
scope.search(iterator);
};
};
};
}
]);
}
]);

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