Finixhed applying jsHint linting to js files. Created initial Gruntfile.js build script and package.json script for keeping track of required node modules.

This commit is contained in:
vagrant
2014-02-11 04:52:15 +00:00
parent f891c30ebb
commit d25e712e21
94 changed files with 10589 additions and 11059 deletions

1
.gitignore vendored
View File

@@ -7,6 +7,7 @@ awx/public/static
awx/ui/static/js/awx-min.js awx/ui/static/js/awx-min.js
awx/ui/static/css/awx.min.css awx/ui/static/css/awx.min.css
env/* env/*
node_modules/**
build build
deb-build deb-build
dist dist

32
Gruntfile.js Normal file
View File

@@ -0,0 +1,32 @@
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('./package.json'),
jshint: {
options: {
jshintrc: '.jshintrc'
},
uses_defaults: ['awx/ui/static/js/*','awx/ui/static/lib/ansible/*', '!awx/ui/static/js/awx-min.js']
},
uglify: {
options: {
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %> */'
},
my_target: {
files: {
'awx/ui/static/js/awx-min.js': ['awx/ui/static/js/**/*.js', 'awx/ui/static/lib/ansible/*.js',
'!awx/ui/static/js/awx-min.js']
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['jshint', 'uglify']);
}

View File

@@ -4,7 +4,6 @@
* Our main application mdoule. Declare application routes and perform initialization chores. * Our main application mdoule. Declare application routes and perform initialization chores.
* *
*/ */
var urlPrefix = $basePath; var urlPrefix = $basePath;
angular.module('ansible', [ angular.module('ansible', [
@@ -58,6 +57,7 @@ angular.module('ansible', [
'JobFormDefinition', 'JobFormDefinition',
'JobEventsListDefinition', 'JobEventsListDefinition',
'JobEventDataDefinition', 'JobEventDataDefinition',
'JobEventsFormDefinition',
'JobHostDefinition', 'JobHostDefinition',
'JobSummaryDefinition', 'JobSummaryDefinition',
'ParseHelper', 'ParseHelper',
@@ -75,9 +75,7 @@ angular.module('ansible', [
'ObjectCountWidget', 'ObjectCountWidget',
'StreamWidget', 'StreamWidget',
'JobsHelper', 'JobsHelper',
'InventoryStatusDefinition',
'InventoryGroupsHelpDefinition', 'InventoryGroupsHelpDefinition',
'InventoryHostsHelpDefinition',
'InventoryTree', 'InventoryTree',
'CredentialsHelper', 'CredentialsHelper',
'TimerService', 'TimerService',
@@ -86,170 +84,289 @@ angular.module('ansible', [
'HomeHostListDefinition', 'HomeHostListDefinition',
'ActivityDetailDefinition' 'ActivityDetailDefinition'
]) ])
.config(['$routeProvider', function($routeProvider) { .config(['$routeProvider',
function ($routeProvider) {
$routeProvider. $routeProvider.
when('/jobs', when('/jobs', {
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobsListCtrl }). templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobsListCtrl'
}).
when('/jobs/:id', when('/jobs/:id', {
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobsEdit }). templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobsEdit'
}).
when('/jobs/:id/job_events', when('/jobs/:id/job_events', {
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobEventsList }). templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobEventsList'
}).
when('/jobs/:id/job_host_summaries', when('/jobs/:id/job_host_summaries', {
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobHostSummaryList }). templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobHostSummaryList'
}).
when('/jobs/:job_id/job_events/:event_id', when('/jobs/:job_id/job_events/:event_id', {
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobEventsEdit }). templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobEventsEdit'
}).
when('/job_templates', when('/job_templates', {
{ templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesList }). templateUrl: urlPrefix + 'partials/job_templates.html',
controller: 'JobTemplatesList'
}).
when('/job_templates/add', when('/job_templates/add', {
{ templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesAdd }). templateUrl: urlPrefix + 'partials/job_templates.html',
controller: 'JobTemplatesAdd'
}).
when('/job_templates/:id', when('/job_templates/:id', {
{ templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesEdit }). templateUrl: urlPrefix + 'partials/job_templates.html',
controller: 'JobTemplatesEdit'
}).
when('/projects', when('/projects', {
{ templateUrl: urlPrefix + 'partials/projects.html', controller: ProjectsList }). templateUrl: urlPrefix + 'partials/projects.html',
controller: 'ProjectsList'
}).
when('/projects/add', when('/projects/add', {
{ templateUrl: urlPrefix + 'partials/projects.html', controller: ProjectsAdd }). templateUrl: urlPrefix + 'partials/projects.html',
controller: 'ProjectsAdd'
}).
when('/projects/:id', when('/projects/:id', {
{ templateUrl: urlPrefix + 'partials/projects.html', controller: ProjectsEdit }). templateUrl: urlPrefix + 'partials/projects.html',
controller: 'ProjectsEdit'
}).
when('/projects/:project_id/organizations', when('/projects/:project_id/organizations', {
{ templateUrl: urlPrefix + 'partials/projects.html', controller: OrganizationsList }). templateUrl: urlPrefix + 'partials/projects.html',
controller: 'OrganizationsList'
}).
when('/projects/:project_id/organizations/add', when('/projects/:project_id/organizations/add', {
{ templateUrl: urlPrefix + 'partials/projects.html', controller: OrganizationsAdd }). templateUrl: urlPrefix + 'partials/projects.html',
controller: 'OrganizationsAdd'
}).
when('/hosts/:id/job_host_summaries', when('/hosts/:id/job_host_summaries', {
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobHostSummaryList }). templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobHostSummaryList'
}).
when('/inventories', when('/inventories', {
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: InventoriesList }). templateUrl: urlPrefix + 'partials/inventories.html',
controller: 'InventoriesList'
}).
when('/inventories/add', when('/inventories/add', {
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: InventoriesAdd }). templateUrl: urlPrefix + 'partials/inventories.html',
controller: 'InventoriesAdd'
}).
when('/inventories/:inventory_id', when('/inventories/:inventory_id', {
{ templateUrl: urlPrefix + 'partials/inventory-edit.html', controller: InventoriesEdit }). templateUrl: urlPrefix + 'partials/inventory-edit.html',
controller: 'InventoriesEdit'
}).
when('/organizations', { templateUrl: urlPrefix + 'partials/organizations.html', when('/organizations', {
controller: OrganizationsList }). templateUrl: urlPrefix + 'partials/organizations.html',
controller: 'OrganizationsList'
}).
when('/organizations/add', { templateUrl: urlPrefix + 'partials/organizations.html', when('/organizations/add', {
controller: OrganizationsAdd }). templateUrl: urlPrefix + 'partials/organizations.html',
controller: 'OrganizationsAdd'
}).
when('/organizations/:organization_id', { templateUrl: urlPrefix + 'partials/organizations.html', when('/organizations/:organization_id', {
controller: OrganizationsEdit }). templateUrl: urlPrefix + 'partials/organizations.html',
controller: 'OrganizationsEdit'
}).
when('/organizations/:organization_id/admins', { templateUrl: urlPrefix + 'partials/organizations.html', when('/organizations/:organization_id/admins', {
controller: AdminsList }). templateUrl: urlPrefix + 'partials/organizations.html',
controller: 'AdminsList'
}).
when('/organizations/:organization_id/users', { templateUrl: urlPrefix + 'partials/users.html', when('/organizations/:organization_id/users', {
controller: UsersList }). templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersList'
}).
when('/organizations/:organization_id/users/add', { templateUrl: urlPrefix + 'partials/users.html', when('/organizations/:organization_id/users/add', {
controller: UsersAdd }). templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersAdd'
}).
when('/organizations/:organization_id/users/:user_id', { templateUrl: urlPrefix + 'partials/users.html', when('/organizations/:organization_id/users/:user_id', {
controller: UsersEdit }). templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersEdit'
}).
when('/teams', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams', {
controller: TeamsList }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'TeamsList'
}).
when('/teams/add', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/add', {
controller: TeamsAdd }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'TeamsAdd'
}).
when('/teams/:team_id', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/:team_id', {
controller: TeamsEdit }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'TeamsEdit'
}).
when('/teams/:team_id/permissions/add', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/:team_id/permissions/add', {
controller: PermissionsAdd }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'PermissionsAdd'
}).
when('/teams/:team_id/permissions', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/:team_id/permissions', {
controller: PermissionsList }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'PermissionsList'
}).
when('/teams/:team_id/permissions/:permission_id', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/:team_id/permissions/:permission_id', {
controller: PermissionsEdit }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'PermissionsEdit'
}).
when('/teams/:team_id/users', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/:team_id/users', {
controller: UsersList }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'UsersList'
}).
when('/teams/:team_id/users/:user_id', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/:team_id/users/:user_id', {
controller: UsersEdit }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'UsersEdit'
}).
when('/teams/:team_id/projects', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/:team_id/projects', {
controller: ProjectsList }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'ProjectsList'
}).
when('/teams/:team_id/projects/add', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/:team_id/projects/add', {
controller: ProjectsAdd }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'ProjectsAdd'
}).
when('/teams/:team_id/projects/:project_id', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/:team_id/projects/:project_id', {
controller: ProjectsEdit }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'ProjectsEdit'
}).
when('/teams/:team_id/credentials', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/:team_id/credentials', {
controller: CredentialsList }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'CredentialsList'
}).
when('/teams/:team_id/credentials/add', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/:team_id/credentials/add', {
controller: CredentialsAdd }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'CredentialsAdd'
}).
when('/teams/:team_id/credentials/:credential_id', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/:team_id/credentials/:credential_id', {
controller: CredentialsEdit }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'CredentialsEdit'
}).
when('/credentials', { templateUrl: urlPrefix + 'partials/credentials.html', when('/credentials', {
controller: CredentialsList }). templateUrl: urlPrefix + 'partials/credentials.html',
controller: 'CredentialsList'
}).
when('/credentials/add', { templateUrl: urlPrefix + 'partials/credentials.html', when('/credentials/add', {
controller: CredentialsAdd }). templateUrl: urlPrefix + 'partials/credentials.html',
controller: 'CredentialsAdd'
}).
when('/credentials/:credential_id', { templateUrl: urlPrefix + 'partials/credentials.html', when('/credentials/:credential_id', {
controller: CredentialsEdit }). templateUrl: urlPrefix + 'partials/credentials.html',
controller: 'CredentialsEdit'
}).
when('/users', { templateUrl: urlPrefix + 'partials/users.html', when('/users', {
controller: UsersList }). templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersList'
}).
when('/users/add', { templateUrl: urlPrefix + 'partials/users.html', when('/users/add', {
controller: UsersAdd }). templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersAdd'
}).
when('/users/:user_id', { templateUrl: urlPrefix + 'partials/users.html', when('/users/:user_id', {
controller: UsersEdit }). templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersEdit'
}).
when('/users/:user_id/credentials', { templateUrl: urlPrefix + 'partials/users.html', when('/users/:user_id/credentials', {
controller: CredentialsList }). templateUrl: urlPrefix + 'partials/users.html',
controller: 'CredentialsList'
}).
when('/users/:user_id/permissions/add', { templateUrl: urlPrefix + 'partials/users.html', when('/users/:user_id/permissions/add', {
controller: PermissionsAdd }). templateUrl: urlPrefix + 'partials/users.html',
controller: 'PermissionsAdd'
}).
when('/users/:user_id/permissions', { templateUrl: urlPrefix + 'partials/users.html', when('/users/:user_id/permissions', {
controller: PermissionsList }). templateUrl: urlPrefix + 'partials/users.html',
controller: 'PermissionsList'
}).
when('/users/:user_id/permissions/:permission_id', { templateUrl: urlPrefix + 'partials/users.html', when('/users/:user_id/permissions/:permission_id', {
controller: PermissionsEdit }). templateUrl: urlPrefix + 'partials/users.html',
controller: 'PermissionsEdit'
}).
when('/users/:user_id/credentials/add', { templateUrl: urlPrefix + 'partials/teams.html', when('/users/:user_id/credentials/add', {
controller: CredentialsAdd }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'CredentialsAdd'
}).
when('/teams/:user_id/credentials/:credential_id', { templateUrl: urlPrefix + 'partials/teams.html', when('/teams/:user_id/credentials/:credential_id', {
controller: CredentialsEdit }). templateUrl: urlPrefix + 'partials/teams.html',
controller: 'CredentialsEdit'
}).
when('/login', { templateUrl: urlPrefix + 'partials/home.html', controller: Authenticate }). when('/login', {
templateUrl: urlPrefix + 'partials/home.html',
controller: 'Authenticate'
}).
when('/logout', { templateUrl: urlPrefix + 'partials/home.html', controller: Authenticate }). when('/logout', {
templateUrl: urlPrefix + 'partials/home.html',
controller: 'Authenticate'
}).
when('/home', { templateUrl: urlPrefix + 'partials/home.html', controller: Home }). when('/home', {
templateUrl: urlPrefix + 'partials/home.html',
controller: 'Home'
}).
when('/home/groups', { templateUrl: urlPrefix + 'partials/subhome.html', controller: HomeGroups }). when('/home/groups', {
templateUrl: urlPrefix + 'partials/subhome.html',
controller: 'HomeGroups'
}).
when('/home/hosts', { templateUrl: urlPrefix + 'partials/subhome.html', controller: HomeHosts }). when('/home/hosts', {
templateUrl: urlPrefix + 'partials/subhome.html',
controller: 'HomeHosts'
}).
otherwise({redirectTo: '/home'}); otherwise({
}]) redirectTo: '/home'
});
}
])
.run(['$cookieStore', '$rootScope', 'CheckLicense', '$location', 'Authorization', 'LoadBasePaths', 'ViewLicense', .run(['$cookieStore', '$rootScope', 'CheckLicense', '$location', 'Authorization', 'LoadBasePaths', 'ViewLicense',
'Timer', 'ClearScope', 'HideStream', 'Timer', 'ClearScope', 'HideStream',
function ($cookieStore, $rootScope, CheckLicense, $location, Authorization, LoadBasePaths, ViewLicense, function ($cookieStore, $rootScope, CheckLicense, $location, Authorization, LoadBasePaths, ViewLicense,
@@ -257,11 +374,11 @@ angular.module('ansible', [
LoadBasePaths(); LoadBasePaths();
$rootScope.breadcrumbs = new Array(); $rootScope.breadcrumbs = [];
$rootScope.crumbCache = new Array(); $rootScope.crumbCache = [];
$rootScope.sessionTimer = Timer.init(); $rootScope.sessionTimer = Timer.init();
$rootScope.$on("$routeChangeStart", function(event, next, current) { $rootScope.$on("$routeChangeStart", function (event, next) {
// Before navigating away from current tab, make sure the primary view is visible // Before navigating away from current tab, make sure the primary view is visible
if ($('#stream-container').is(':visible')) { if ($('#stream-container').is(':visible')) {
@@ -275,19 +392,17 @@ angular.module('ansible', [
$cookieStore.put('lastPath', $location.path()); $cookieStore.put('lastPath', $location.path());
} }
if (Authorization.isUserLoggedIn() == false) { if (Authorization.isUserLoggedIn() === false) {
if ( next.templateUrl != (urlPrefix + 'partials/login.html') ) { if (next.templateUrl !== (urlPrefix + 'partials/login.html')) {
$location.path('/login'); $location.path('/login');
} }
} } else if ($rootScope.sessionTimer.isExpired()) {
else if ($rootScope.sessionTimer.isExpired()) { if (next.templateUrl !== (urlPrefix + 'partials/login.html')) {
if ( next.templateUrl != (urlPrefix + 'partials/login.html') ) {
$rootScope.sessionTimer.expireSession(); $rootScope.sessionTimer.expireSession();
$location.path('/login'); $location.path('/login');
} }
} } else {
else { if ($rootScope.current_user === undefined || $rootScope.current_user === null) {
if ($rootScope.current_user == undefined || $rootScope.current_user == null) {
Authorization.restoreUserInfo(); //user must have hit browser refresh Authorization.restoreUserInfo(); //user must have hit browser refresh
} }
CheckLicense(); CheckLicense();
@@ -295,10 +410,9 @@ angular.module('ansible', [
// Make the correct tab active // Make the correct tab active
var base = $location.path().replace(/^\//, '').split('/')[0]; var base = $location.path().replace(/^\//, '').split('/')[0];
if (base == '') { if (base === '') {
base = 'home'; base = 'home';
} } else {
else {
base.replace(/\_/g, ' '); base.replace(/\_/g, ' ');
} }
$('.nav-tabs a[href="#' + base + '"]').tab('show'); $('.nav-tabs a[href="#' + base + '"]').tab('show');
@@ -309,29 +423,28 @@ angular.module('ansible', [
$rootScope.sessionExpired = false; $rootScope.sessionExpired = false;
$cookieStore.put('sessionExpired', false); $cookieStore.put('sessionExpired', false);
$location.path('/login'); $location.path('/login');
} } else {
else {
// If browser refresh, set the user_is_superuser value // If browser refresh, set the user_is_superuser value
$rootScope['user_is_superuser'] = Authorization.getUserInfo('is_superuser'); $rootScope.user_is_superuser = Authorization.getUserInfo('is_superuser');
} }
// If browser refresh, activate the correct tab // If browser refresh, activate the correct tab
var base = ($location.path().replace(/^\//, '').split('/')[0]); var base = ($location.path().replace(/^\//, '').split('/')[0]);
if (base == '') { if (base === '') {
base = 'home'; base = 'home';
$location.path('/home'); $location.path('/home');
} } else {
else {
base.replace(/\_/g, ' '); base.replace(/\_/g, ' ');
} }
$('.nav-tabs a[href="#' + base + '"]').tab('show'); $('.nav-tabs a[href="#' + base + '"]').tab('show');
$rootScope.viewCurrentUser = function () { $rootScope.viewCurrentUser = function () {
$location.path('/users/' + $rootScope.current_user.id); $location.path('/users/' + $rootScope.current_user.id);
} };
$rootScope.viewLicense = function () { $rootScope.viewLicense = function () {
//$location.path('/license'); //$location.path('/license');
ViewLicense(); ViewLicense();
};
} }
}]); ]);

View File

@@ -1,4 +1,4 @@
/************************************ /**********************************************************************
* *
* Copyright (c) 2014 AnsibleWorks, Inc. * Copyright (c) 2014 AnsibleWorks, Inc.
* *
@@ -8,8 +8,10 @@
* *
*/ */
var $AnsibleConfig = /*jshint unused:false */
{
var $AnsibleConfig = {
tooltip_delay: {show: 500, hide: 100}, // Default number of milliseconds to delay displaying/hiding tooltips tooltip_delay: {show: 500, hide: 100}, // Default number of milliseconds to delay displaying/hiding tooltips
debug_mode: true, // Enable console logging messages debug_mode: true, // Enable console logging messages
@@ -23,4 +25,4 @@ var $AnsibleConfig =
session_timeout: 1800 // Number of seconds before an inactive session is automatically timed out and forced to log in again. session_timeout: 1800 // Number of seconds before an inactive session is automatically timed out and forced to log in again.
// Separate from time out value set in API. // Separate from time out value set in API.
} };

View File

@@ -1,12 +1,12 @@
/************************************ /*************************************************
* Copyright (c) 2014 AnsibleWorks, Inc. * Copyright (c) 2014 AnsibleWorks, Inc.
* *
*
* Credentials.js * Credentials.js
* *
* Controller functions for the Credential model. * Controller functions for the Credential model.
* *
*/ */
'use strict'; 'use strict';
function CredentialsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, CredentialList, function CredentialsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, CredentialList,
@@ -114,10 +114,10 @@ function CredentialsList($scope, $rootScope, $location, $log, $routeParams, Rest
var url = defaultUrl + id + '/'; var url = defaultUrl + id + '/';
Rest.setUrl(url); Rest.setUrl(url);
Rest.destroy() Rest.destroy()
.success(function (data, status, headers, config) { .success(function () {
scope.search(list.iterator); scope.search(list.iterator);
}) })
.error(function (data, status, headers, config) { .error(function (data, status) {
Wait('stop'); Wait('stop');
ProcessErrors(scope, data, status, null, { ProcessErrors(scope, data, status, null, {
hdr: 'Error!', hdr: 'Error!',
@@ -143,7 +143,7 @@ CredentialsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeP
function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm, function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
GenerateList, SearchInit, PaginateInit, LookUpInit, UserList, TeamList, GetBasePath, GenerateList, SearchInit, PaginateInit, LookUpInit, UserList, TeamList, GetBasePath,
GetChoices, Empty, KindChange, OwnerChange, FormSave, DebugForm) { GetChoices, Empty, KindChange, OwnerChange, FormSave) {
ClearScope('tree-form'); ClearScope('tree-form');
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope. //scope.
@@ -152,7 +152,6 @@ function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routePar
var form = CredentialForm, var form = CredentialForm,
generator = GenerateForm, generator = GenerateForm,
scope = generator.inject(form, { mode: 'add', related: false }), scope = generator.inject(form, { mode: 'add', related: false }),
base = $location.path().replace(/^\//, '').split('/')[0],
defaultUrl = GetBasePath('credentials'), defaultUrl = GetBasePath('credentials'),
url; url;
@@ -193,10 +192,10 @@ function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routePar
url = GetBasePath('users') + $routeParams.user_id + '/'; url = GetBasePath('users') + $routeParams.user_id + '/';
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success(function (data, status, headers, config) { .success(function (data) {
scope.user_username = data.username; scope.user_username = data.username;
}) })
.error(function (data, status, headers, config) { .error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve user. GET status: ' + status ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve user. GET status: ' + status
}); });
}); });
@@ -210,10 +209,10 @@ function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routePar
url = GetBasePath('teams') + $routeParams.team_id + '/'; url = GetBasePath('teams') + $routeParams.team_id + '/';
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success(function (data, status, headers, config) { .success(function (data) {
scope.team_name = data.name; scope.team_name = data.name;
}) })
.error(function (data, status, headers, config) { .error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve team. GET status: ' + status ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve team. GET status: ' + status
}); });
}); });
@@ -289,7 +288,7 @@ function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routePar
CredentialsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'CredentialForm', 'GenerateForm', CredentialsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'CredentialForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList',
'SearchInit', 'PaginateInit', 'LookUpInit', 'UserList', 'TeamList', 'GetBasePath', 'GetChoices', 'Empty', 'SearchInit', 'PaginateInit', 'LookUpInit', 'UserList', 'TeamList', 'GetBasePath', 'GetChoices', 'Empty',
'KindChange', 'OwnerChange', 'FormSave', 'DebugForm' 'KindChange', 'OwnerChange', 'FormSave'
]; ];

View File

@@ -249,13 +249,12 @@ JobEventsList.$inject = ['$filter', '$scope', '$rootScope', '$location', '$log',
'ProcessErrors', 'GetBasePath', 'LookUpInit', 'ToggleChildren', 'FormatDate', 'EventView', 'Refresh', 'Wait' 'ProcessErrors', 'GetBasePath', 'LookUpInit', 'ToggleChildren', 'FormatDate', 'EventView', 'Refresh', 'Wait'
]; ];
function JobEventsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobEventForm, GenerateForm, function JobEventsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobEventsForm, GenerateForm,
Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, FormatDate, EventView, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, FormatDate, EventView, Wait) {
Wait) {
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior ClearScope('htmlTemplate');
//scope.
// Inject dynamic view var form = JobEventsForm,
var form = JobEventForm,
generator = GenerateForm, generator = GenerateForm,
scope = GenerateForm.inject(form, { mode: 'edit', related: true }), scope = GenerateForm.inject(form, { mode: 'edit', related: true }),
defaultUrl = GetBasePath('base') + 'job_events/' + $routeParams.event_id + '/'; defaultUrl = GetBasePath('base') + 'job_events/' + $routeParams.event_id + '/';
@@ -348,7 +347,7 @@ function JobEventsEdit($scope, $rootScope, $compile, $location, $log, $routePara
} }
JobEventsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobEventForm', JobEventsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobEventsForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', 'FormatDate', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', 'FormatDate',
'EventView', 'Wait' 'EventView', 'Wait'
]; ];

View File

@@ -6,8 +6,7 @@
* *
*/ */
angular.module('ActivityDetailDefinition', []) angular.module('ActivityDetailDefinition', [])
.value( .value('ActivityDetailForm', {
'ActivityDetailForm', {
name: 'activity', name: 'activity',
editTitle: 'Activity Detail', editTitle: 'Activity Detail',

View File

@@ -6,8 +6,7 @@
* *
*/ */
angular.module('CredentialFormDefinition', []) angular.module('CredentialFormDefinition', [])
.value( .value('CredentialForm', {
'CredentialForm', {
addTitle: 'Create Credential', //Legend in add mode addTitle: 'Create Credential', //Legend in add mode
editTitle: '{{ name }}', //Legend in edit mode editTitle: '{{ name }}', //Legend in edit mode
@@ -41,10 +40,14 @@ angular.module('CredentialFormDefinition', [])
label: "Does this credential belong to a team or user?", label: "Does this credential belong to a team or user?",
type: 'radio_group', type: 'radio_group',
ngChange: "ownerChange()", ngChange: "ownerChange()",
options: [ options: [{
{ label: 'User', value: 'user', selected: true }, label: 'User',
{ label: 'Team', value: 'team' } 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 " + 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>", "to the credential. Choosing a team shares the credential with all team members.</p>",
dataTitle: 'Owner', dataTitle: 'Owner',
@@ -58,7 +61,10 @@ angular.module('CredentialFormDefinition', [])
sourceField: 'username', sourceField: 'username',
ngClick: 'lookUpUser()', ngClick: 'lookUpUser()',
ngShow: "owner == 'user'", ngShow: "owner == 'user'",
awRequiredWhen: { variable: "user_required", init: "false" } awRequiredWhen: {
variable: "user_required",
init: "false"
}
}, },
team: { team: {
label: 'Team that owns this credential', label: 'Team that owns this credential',
@@ -67,7 +73,10 @@ angular.module('CredentialFormDefinition', [])
sourceField: 'name', sourceField: 'name',
ngClick: 'lookUpTeam()', ngClick: 'lookUpTeam()',
ngShow: "owner == 'team'", ngShow: "owner == 'team'",
awRequiredWhen: { variable: "team_required", init: "false" } awRequiredWhen: {
variable: "team_required",
init: "false"
}
}, },
kind: { kind: {
label: 'Type', label: 'Type',
@@ -77,8 +86,8 @@ angular.module('CredentialFormDefinition', [])
ngChange: 'kindChange()', ngChange: 'kindChange()',
addRequired: true, addRequired: true,
editRequired: true, editRequired: true,
helpCollapse: [ helpCollapse: [{
{ hdr: 'Select a Credential Type', hdr: 'Select a Credential Type',
content: '<dl>\n' + content: '<dl>\n' +
'<dt>AWS</dt>\n' + '<dt>AWS</dt>\n' +
'<dd>Access keys for Amazon Web Services used for inventory management or deployment.</dd>\n' + '<dd>Access keys for Amazon Web Services used for inventory management or deployment.</dd>\n' +
@@ -99,7 +108,10 @@ angular.module('CredentialFormDefinition', [])
label: 'Access Key', label: 'Access Key',
type: 'text', type: 'text',
ngShow: "kind.value == 'aws'", ngShow: "kind.value == 'aws'",
awRequiredWhen: { variable: "aws_required", init: false }, awRequiredWhen: {
variable: "aws_required",
init: false
},
autocomplete: false, autocomplete: false,
apiField: 'username' apiField: 'username'
}, },
@@ -107,7 +119,10 @@ angular.module('CredentialFormDefinition', [])
label: 'Secret Key', label: 'Secret Key',
type: 'password', type: 'password',
ngShow: "kind.value == 'aws'", ngShow: "kind.value == 'aws'",
awRequiredWhen: { variable: "aws_required", init: false }, awRequiredWhen: {
variable: "aws_required",
init: false
},
autocomplete: false, autocomplete: false,
ask: false, ask: false,
clear: false, clear: false,
@@ -117,14 +132,20 @@ angular.module('CredentialFormDefinition', [])
labelBind: 'usernameLabel', labelBind: 'usernameLabel',
type: 'text', type: 'text',
ngShow: "kind.value && kind.value !== 'aws'", ngShow: "kind.value && kind.value !== 'aws'",
awRequiredWhen: {variable: 'rackspace_required', init: false }, awRequiredWhen: {
variable: 'rackspace_required',
init: false
},
autocomplete: false autocomplete: false
}, },
"api_key": { "api_key": {
label: 'API Key', label: 'API Key',
type: 'password', type: 'password',
ngShow: "kind.value == 'rax'", ngShow: "kind.value == 'rax'",
awRequiredWhen: { variable: "rackspace_required", init: false }, awRequiredWhen: {
variable: "rackspace_required",
init: false
},
autocomplete: false, autocomplete: false,
ask: false, ask: false,
clear: false, clear: false,
@@ -236,7 +257,7 @@ angular.module('CredentialFormDefinition', [])
} }
}, },
buttons: { //for now always generates <button> tags buttons: {
save: { save: {
label: 'Save', label: 'Save',
ngClick: 'formSave()', //$scope.function to call on click, optional ngClick: 'formSave()', //$scope.function to call on click, optional
@@ -248,9 +269,6 @@ angular.module('CredentialFormDefinition', [])
} }
}, },
related: { //related colletions (and maybe items?) related: {}
}
}); //InventoryForm
});

View File

@@ -7,8 +7,7 @@
* *
*/ */
angular.module('GroupFormDefinition', []) angular.module('GroupFormDefinition', [])
.value( .value('GroupForm', {
'GroupForm', {
addTitle: 'Create Group', addTitle: 'Create Group',
editTitle: 'Edit Group', editTitle: 'Edit Group',
@@ -19,10 +18,13 @@ angular.module('GroupFormDefinition', [])
formLabelSize: 'col-lg-3', formLabelSize: 'col-lg-3',
formFieldSize: 'col-lg-9', formFieldSize: 'col-lg-9',
tabs: [ tabs: [{
{ name: 'properties', label: 'Properties'}, name: 'properties',
{ name: 'source', label: 'Source' } label: 'Properties'
], }, {
name: 'source',
label: 'Source'
}],
fields: { fields: {
name: { name: {
@@ -74,7 +76,10 @@ angular.module('GroupFormDefinition', [])
label: 'Script Path', label: 'Script Path',
ngShow: "source && source.value == 'file'", ngShow: "source && source.value == 'file'",
type: 'text', type: 'text',
awRequiredWhen: {variable: "sourcePathRequired", init: "false" }, awRequiredWhen: {
variable: "sourcePathRequired",
init: "false"
},
tab: 'source' tab: 'source'
}, },
credential: { credential: {
@@ -133,8 +138,7 @@ angular.module('GroupFormDefinition', [])
ngShow: "source && (source.value !== '' && source.value !== null)", ngShow: "source && (source.value !== '' && source.value !== null)",
tab: 'source', tab: 'source',
fields: [ fields: [{
{
name: 'overwrite', name: 'overwrite',
label: 'Overwrite', label: 'Overwrite',
type: 'checkbox', type: 'checkbox',
@@ -148,8 +152,7 @@ angular.module('GroupFormDefinition', [])
dataContainer: 'body', dataContainer: 'body',
dataPlacement: 'right', dataPlacement: 'right',
labelClass: 'checkbox-options' labelClass: 'checkbox-options'
}, }, {
{
name: 'overwrite_vars', name: 'overwrite_vars',
label: 'Overwrite Variables', label: 'Overwrite Variables',
type: 'checkbox', type: 'checkbox',
@@ -163,8 +166,7 @@ angular.module('GroupFormDefinition', [])
dataContainer: 'body', dataContainer: 'body',
dataPlacement: 'right', dataPlacement: 'right',
labelClass: 'checkbox-options' labelClass: 'checkbox-options'
}, }, {
{
name: 'update_on_launch', name: 'update_on_launch',
label: 'Update on Launch', label: 'Update on Launch',
type: 'checkbox', type: 'checkbox',
@@ -177,19 +179,18 @@ angular.module('GroupFormDefinition', [])
dataContainer: 'body', dataContainer: 'body',
dataPlacement: 'right', dataPlacement: 'right',
labelClass: 'checkbox-options' labelClass: 'checkbox-options'
} }]
]
} }
}, },
buttons: { //for now always generates <button> tags buttons: {
labelClass: 'col-lg-3', labelClass: 'col-lg-3',
controlClass: 'col-lg-5', controlClass: 'col-lg-5',
save: { save: {
ngClick: 'formSave()', //$scope.function to call on click, optional ngClick: 'formSave()',
ngDisabled: true //Disable when $pristine or $invalid, optional ngDisabled: true
}, },
reset: { reset: {
ngClick: 'formReset()', ngClick: 'formReset()',
@@ -197,9 +198,6 @@ angular.module('GroupFormDefinition', [])
} }
}, },
related: { //related colletions (and maybe items?) related: { }
}
}); });

View File

@@ -7,12 +7,11 @@
* *
*/ */
angular.module('HostGroupsFormDefinition', []) angular.module('HostGroupsFormDefinition', [])
.value( .value('HostGroupsForm', {
'HostGroupsForm', {
editTitle: 'Host Groups', //Legend in edit mode editTitle: 'Host Groups',
name: 'host', //Form name attribute name: 'host',
well: false, //Wrap the form with TB well well: false,
formLabelSize: 'col-lg-3', formLabelSize: 'col-lg-3',
formFieldSize: 'col-lg-9', formFieldSize: 'col-lg-9',
@@ -38,18 +37,16 @@ angular.module('HostGroupsFormDefinition', [])
buttons: { //for now always generates <button> tags buttons: { //for now always generates <button> tags
save: { save: {
ngClick: 'formSave()', //$scope.function to call on click, optional ngClick: 'formSave()',
ngDisabled: true //Disable when $pristine or $invalid, optional ngDisabled: true
}, },
reset: { reset: {
ngClick: 'formReset()', ngClick: 'formReset()',
ngDisabled: true //Disabled when $pristine ngDisabled: true
} }
}, },
related: { //related colletions (and maybe items?) related: { }
}
}); //UserForm }); //UserForm

View File

@@ -7,13 +7,12 @@
* *
*/ */
angular.module('HostFormDefinition', []) angular.module('HostFormDefinition', [])
.value( .value('HostForm', {
'HostForm', {
addTitle: 'Create Host', //Legend in add mode addTitle: 'Create Host',
editTitle: '{{ name }}', //Legend in edit mode editTitle: '{{ name }}',
name: 'host', //Form name attribute name: 'host',
well: false, //Wrap the form with TB well well: false,
formLabelSize: 'col-lg-3', formLabelSize: 'col-lg-3',
formFieldSize: 'col-lg-9', formFieldSize: 'col-lg-9',
@@ -89,9 +88,6 @@ angular.module('HostFormDefinition', [])
} }
}, },
related: { //related colletions (and maybe items?) related: {}
}
}); });

View File

@@ -7,8 +7,7 @@
* *
*/ */
angular.module('InventoryFormDefinition', []) angular.module('InventoryFormDefinition', [])
.value( .value('InventoryForm', {
'InventoryForm', {
addTitle: 'Create Inventory', addTitle: 'Create Inventory',
editTitle: '{{ inventory_name | capitalize }}', editTitle: '{{ inventory_name | capitalize }}',
@@ -49,7 +48,10 @@ angular.module('InventoryFormDefinition', [])
sourceModel: 'organization', sourceModel: 'organization',
sourceField: 'name', sourceField: 'name',
ngClick: 'lookUpOrganization()', ngClick: 'lookUpOrganization()',
awRequiredWhen: {variable: "organizationrequired", init: "true" } awRequiredWhen: {
variable: "organizationrequired",
init: "true"
}
}, },
inventory_variables: { inventory_variables: {
realName: 'variables', realName: 'variables',
@@ -74,14 +76,14 @@ angular.module('InventoryFormDefinition', [])
} }
}, },
buttons: { //for now always generates <button> tags buttons: {
save: { save: {
ngClick: 'formSave()', //$scope.function to call on click, optional ngClick: 'formSave()',
ngDisabled: true //Disable when $pristine or $invalid, optional ngDisabled: true
}, },
reset: { reset: {
ngClick: 'formReset()', ngClick: 'formReset()',
ngDisabled: true //Disabled when $pristine ngDisabled: true
} }
}, },
@@ -89,5 +91,4 @@ angular.module('InventoryFormDefinition', [])
} }
}); //InventoryForm });

View File

@@ -1,27 +0,0 @@
/*********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* InventoryGroups.js
* Form definition for Groups model
*
*
*/
angular.module('InventoryGroupsFormDefinition', [])
.value(
'InventoryGroupsForm', {
type: 'groupsview',
title: "groupTitle",
editTitle: 'Groups',
iterator: 'group',
fields: {
},
actions: {
},
fieldActions: {
}
}); //InventoryGroupsForm

View File

@@ -1,147 +0,0 @@
/*********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* InventoryHosts.js
* Form definition for Hosts model
*
*
*/
angular.module('InventoryHostsFormDefinition', [])
.value(
'InventoryHostsForm', {
type: 'hostsview',
title: "groupTitle",
editTitle: 'Hosts',
iterator: 'host',
fields: {
name: {
key: true,
label: 'Name',
ngClick: "editHost(\{\{ host.id \}\}, '\{\{ host.name \}\}')"
},
active_failures: {
label: 'Job Status',
ngHref: "\{\{ host.activeFailuresLink \}\}",
awToolTip: "\{\{ host.badgeToolTip \}\}",
dataPlacement: 'top',
badgeNgHref: '\{\{ host.activeFailuresLink \}\}',
badgeIcon: "\{\{ 'icon-failures-' + host.has_active_failures \}\}",
badgePlacement: 'left',
badgeToolTip: "\{\{ host.badgeToolTip \}\}",
badgeTipPlacement: 'top',
searchable: false,
nosort: true
},
enabled_flag: {
label: 'Enabled',
badgeIcon: "\{\{ 'icon-enabled-' + host.enabled \}\}",
badgePlacement: 'left',
badgeToolTip: "\{\{ host.enabledToolTip \}\}",
badgeTipPlacement: "top",
badgeTipWatch: "host.enabledToolTip",
ngClick: "toggle_host_enabled(\{\{ host.id \}\}, \{\{ host.has_inventory_sources \}\})",
searchable: false,
showValue: false
},
groups: {
label: 'Groups',
searchable: true,
sourceModel: 'groups',
sourceField: 'name',
nosort: true
},
enabled: {
label: 'Disabled?',
searchSingleValue: true,
searchType: 'boolean',
searchValue: 'false',
searchOnly: true
},
has_active_failures: {
label: 'Has failed jobs?',
searchSingleValue: true,
searchType: 'boolean',
searchValue: 'true',
searchOnly: true
},
has_inventory_sources: {
label: 'Has external source?',
searchSingleValue: true,
searchType: 'boolean',
searchValue: 'true',
searchOnly: true
}
},
actions: {
add: {
label: 'Copy',
ngClick: "addHost()",
ngHide: "hostAddHide",
awToolTip: "Copy an existing host to the selected group",
dataPlacement: 'top',
'class': 'btn-xs btn-success',
icon: 'icon-check'
},
create: {
label: 'Create New',
ngClick: 'createHost()',
ngHide: 'hostCreateHide',
awToolTip: 'Create a new host and add it to the selected group',
dataPlacement: 'top',
'class': 'btn-xs btn-success',
icon: 'icon-plus'
},
help: {
dataPlacement: 'top',
icon: "icon-question-sign",
mode: 'all',
'class': 'btn-xs btn-info btn-help',
awToolTip: "<div style=\"padding-top:10px; text-align: left;\"><p>Need help getting started?</p>" +
"<p>Click here for help with this page</p></div>",
iconSize: 'large',
ngClick: "showHelp()",
id: "hosts-page-help"
},
stream: {
'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
dataPlacement: "top",
icon: "icon-comments-alt",
mode: 'edit',
iconSize: 'large'
}
},
fieldActions: {
ViewJobs: {
type: 'DropDown',
label: 'Jobs',
icon: 'icon-zoom-in',
"class": "btn-default btn-xs",
options: [
{ ngClick: "allJobs(\{\{ host.id \}\})", label: 'All', ngShow: 'host.last_job' },
{ ngClick: "allHostSummaries(\{\{ host.id \}\},'\{\{ host.name \}\}', \{\{ inventory_id \}\})", label: 'All summaries',
ngShow: 'host.last_job' },
{ ngClick: 'viewJobs(\{\{ host.last_job \}\})', label: 'Latest', ngShow: 'host.last_job' },
{ ngClick: "viewLastEvents(\{\{ host.id \}\}, '\{\{ host.last_job \}\}', '\{\{ host.name \}\}', " +
"'\{\{ host.summary_fields.last_job.name \}\}')", label: 'Latest events', ngShow: 'host.last_job' },
{ ngClick: "viewLastSummary(\{\{ host.id \}\}, '\{\{ host.last_job \}\}', '\{\{ host.name \}\}', " +
"'\{\{ host.summary_fields.last_job.name \}\}')", label: 'Latest summary', ngShow: 'host.last_job' },
{ ngClick: "", label: 'No job data available', ngShow: 'host.last_job == null' }
]
},
"delete": {
ngClick: "deleteHost(\{\{ host.id \}\},'\{\{ host.name \}\}')",
icon: 'icon-trash',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete host'
}
}
}); //InventoryHostsForm

View File

@@ -1,57 +0,0 @@
/*********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* InventoryStatus.js
* Form definition for Inventory Status -JSON view
*
*
*/
angular.module('InventoryStatusDefinition', [])
.value(
'InventoryStatusForm', {
name: 'inventory_update',
editTitle: 'Inventory Status',
well: false,
'class': 'horizontal-narrow',
fields: {
license_error: {
type: 'alertblock',
'class': 'alert-info',
alertTxt: 'The invenvtory update process exceeded the available number of licensed hosts. ' +
'<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

View File

@@ -7,10 +7,9 @@
* *
*/ */
angular.module('JobEventDataDefinition', []) angular.module('JobEventDataDefinition', [])
.value( .value('JobEventDataForm', {
'JobEventDataForm', {
editTitle: '{{ id }} - {{ event_display }}', //Legend in edit mode editTitle: '{{ id }} - {{ event_display }}',
name: 'job_events', name: 'job_events',
well: false, well: false,
'class': 'horizontal-narrow', 'class': 'horizontal-narrow',

View File

@@ -0,0 +1,144 @@
/*********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* JobEventsForm.js
*
*/
angular.module('JobEventsFormDefinition', [])
.value('JobEventsForm', {
name: 'job_events',
well: false,
forceListeners: true,
fields: {
status: {
labelClass: 'job-{{ status }}',
type: 'custom',
section: 'Event',
control: "<div class=\"job-event-status job-{{ status }}\"><i class=\"fa icon-job-{{ status }}\"></i> {{ status }}</div>"
},
id: {
label: 'ID',
type: 'text',
readonly: true,
section: 'Event',
'class': 'span1'
},
created: {
label: 'Created On',
type: 'text',
section: 'Event',
readonly: true
},
host: {
label: 'Host',
type: 'text',
readonly: true,
section: 'Event',
ngShow: "host !== ''"
},
play: {
label: 'Play',
type: 'text',
readonly: true,
section: 'Event',
ngShow: "play !== ''"
},
task: {
label: 'Task',
type: 'text',
readonly: true,
section: 'Event',
ngShow: "task !== ''"
},
rc: {
label: 'Return Code',
type: 'text',
readonly: true,
section: 'Results',
'class': 'span1',
ngShow: "rc !== ''"
},
msg: {
label: 'Msg',
type: 'textarea',
readonly: true,
section: 'Results',
'class': 'nowrap',
ngShow: "msg !== ''",
rows: 10
},
stdout: {
label: 'Std Out',
type: 'textarea',
readonly: true,
section: 'Results',
'class': 'nowrap',
ngShow: "stdout !== ''",
rows: 10
},
stderr: {
label: 'Std Err',
type: 'textarea',
readonly: true,
section: 'Results',
'class': 'nowrap',
ngShow: "stderr !== ''",
rows: 10
},
results: {
label: 'Results',
type: 'textarea',
section: 'Results',
readonly: true,
'class': 'nowrap',
ngShow: "results !== ''",
rows: 10
},
start: {
label: 'Start',
type: 'text',
readonly: true,
section: 'Timing',
ngShow: "start !== ''"
},
traceback: {
label: false,
type: 'textarea',
readonly: true,
section: 'Traceback',
'class': 'nowrap',
ngShow: "traceback !== ''",
rows: 10
},
end: {
label: 'End',
type: 'text',
readonly: true,
section: 'Timing',
ngShow: "end !== ''"
},
delta: {
label: 'Elapsed',
type: 'text',
readonly: true,
section: 'Timing',
ngShow: "delta !== ''"
},
module_name: {
label: 'Name',
type: 'text',
readonly: true,
section: 'Module',
ngShow: "module_name !== ''"
},
module_args: {
label: 'Args',
type: 'text',
readonly: true,
section: 'Module',
ngShow: "module_args !== ''"
}
}
});

View File

@@ -7,8 +7,7 @@
* *
*/ */
angular.module('JobSummaryDefinition', []) angular.module('JobSummaryDefinition', [])
.value( .value('JobSummary', {
'JobSummary', {
editTitle: '{{ id }} - {{ name }}', editTitle: '{{ id }} - {{ name }}',
name: 'jobs', name: 'jobs',
@@ -46,5 +45,4 @@ angular.module('JobSummaryDefinition', [])
ngShow: 'result_traceback != ""' ngShow: 'result_traceback != ""'
} }
} }
}); });

View File

@@ -7,11 +7,10 @@
* *
*/ */
angular.module('JobTemplateFormDefinition', []) angular.module('JobTemplateFormDefinition', [])
.value( .value('JobTemplateForm', {
'JobTemplateForm', {
addTitle: 'Create Job Templates', //Legend in add mode addTitle: 'Create Job Templates',
editTitle: '{{ name }}', //Legend in edit mode editTitle: '{{ name }}',
name: 'job_templates', name: 'job_templates',
twoColumns: true, twoColumns: true,
well: true, well: true,
@@ -203,8 +202,7 @@ angular.module('JobTemplateFormDefinition', [])
"<p>For example, you might have a task consisiting of a long list of actions. Tag values can be assigned to each action. " + "<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>" + "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 " + "<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" + "in the Job Tags field:</p>\n<blockquote>configuration,packages</blockquote>\n",
"<blockquote>configuration,packages</blockquote>\n",
dataTitle: "Job Tags", dataTitle: "Job Tags",
dataPlacement: "right", dataPlacement: "right",
dataContainer: "body" dataContainer: "body"
@@ -277,7 +275,7 @@ angular.module('JobTemplateFormDefinition', [])
} }
}, },
related: { //related colletions (and maybe items?) related: {
jobs: { jobs: {
type: 'collection', type: 'collection',
@@ -312,9 +310,9 @@ angular.module('JobTemplateFormDefinition', [])
}, },
status: { status: {
label: 'Status', label: 'Status',
"class": 'job-\{\{ job.status \}\}', "class": 'job-{{ job.status }}',
searchType: 'select', searchType: 'select',
linkTo: "\{\{ job.statusLinkTo \}\}", linkTo: "{{}} job.statusLinkTo }}",
searchOptions: [ searchOptions: [
{ name: "new", value: "new" }, { name: "new", value: "new" },
{ name: "waiting", value: "waiting" }, { name: "waiting", value: "waiting" },
@@ -323,13 +321,14 @@ angular.module('JobTemplateFormDefinition', [])
{ name: "successful", value: "successful" }, { name: "successful", value: "successful" },
{ name: "error", value: "error" }, { name: "error", value: "error" },
{ name: "failed", value: "failed" }, { name: "failed", value: "failed" },
{ name: "canceled", value: "canceled" } ], { name: "canceled", value: "canceled" }
badgeIcon: 'fa icon-job-\{\{ job.status \}\}', ],
badgeIcon: 'fa icon-job-{{ job.status }}',
badgePlacement: 'left', badgePlacement: 'left',
badgeToolTip: "\{\{ job.statusBadgeToolTip \}\}", badgeToolTip: "{{ job.statusBadgeToolTip }}",
badgeTipPlacement: 'top', badgeTipPlacement: 'top',
badgeNgHref: "\{\{ job.statusLinkTo \}\}", badgeNgHref: "{{ job.statusLinkTo }}",
awToolTip: "\{\{ job.statusBadgeToolTip \}\}", awToolTip: "{{ job.statusBadgeToolTip }}",
dataPlacement: 'top' dataPlacement: 'top'
} }
}, },
@@ -337,7 +336,7 @@ angular.module('JobTemplateFormDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'View', label: 'View',
ngClick: "edit('jobs', \{\{ job.id \}\}, '\{\{ job.name \}\}')", ngClick: "edit('jobs', job.id, job.name)",
icon: 'icon-zoom-in' icon: 'icon-zoom-in'
} }
} }

View File

@@ -7,8 +7,7 @@
* @dict * @dict
*/ */
angular.module('JobFormDefinition', []) angular.module('JobFormDefinition', [])
.value( .value('JobForm', {
'JobForm', {
addTitle: 'Create Job', addTitle: 'Create Job',
editTitle: '{{ id }} - {{ name }}', editTitle: '{{ id }} - {{ name }}',
@@ -217,7 +216,7 @@ angular.module('JobFormDefinition', [])
"<p>For example, you might have a task consisiting of a long list of actions. Tag values can be assigned to each action. " + "<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>" + "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 " + "<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" + "in the Job Tags field:</p>\n" +
"<blockquote>configuration,packages</blockquote>\n", "<blockquote>configuration,packages</blockquote>\n",
dataTitle: "Job Tags", dataTitle: "Job Tags",
dataContainer: 'body', dataContainer: 'body',
@@ -281,20 +280,20 @@ angular.module('JobFormDefinition', [])
} }
}, },
buttons: { //for now always generates <button> tags buttons: {
save: { save: {
label: 'Save', label: 'Save',
icon: 'icon-ok', icon: 'icon-ok',
"class": 'btn-success', "class": 'btn-success',
ngClick: 'formSave()', //$scope.function to call on click, optional ngClick: 'formSave()',
ngDisabled: true //Disable when $pristine or $invalid, optional ngDisabled: true
}, },
reset: { reset: {
ngClick: 'formReset()', ngClick: 'formReset()',
label: 'Reset', label: 'Reset',
icon: 'icon-undo', icon: 'icon-undo',
'class': 'btn btn-default', 'class': 'btn btn-default',
ngDisabled: true //Disabled when $pristine ngDisabled: true
} }
}, },
@@ -302,7 +301,8 @@ angular.module('JobFormDefinition', [])
status: { status: {
//label: 'Job Status', //label: 'Job Status',
type: 'custom', type: 'custom',
control: '<div class=\"job-detail-status\"><span style="padding-right: 15px; font-weight: bold;">Status</span> <i class=\"fa icon-job-\{\{ status \}\}\"></i> \{\{ status \}\}</div>', 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 readonly: true
}, },
created: { created: {
@@ -315,7 +315,7 @@ angular.module('JobFormDefinition', [])
type: 'textarea', type: 'textarea',
readonly: true, readonly: true,
xtraWide: true, xtraWide: true,
rows: "\{\{ stdout_rows \}\}", rows: "{{ stdout_rows }}",
"class": 'nowrap mono-space', "class": 'nowrap mono-space',
ngShow: "result_stdout != ''" ngShow: "result_stdout != ''"
}, },
@@ -324,7 +324,7 @@ angular.module('JobFormDefinition', [])
type: 'textarea', type: 'textarea',
xtraWide: true, xtraWide: true,
readonly: true, readonly: true,
rows: "\{\{ traceback_rows \}\}", rows: "{{ traceback_rows }}",
"class": 'nowrap mono-space', "class": 'nowrap mono-space',
ngShow: "result_traceback != ''" ngShow: "result_traceback != ''"
} }
@@ -343,5 +343,4 @@ angular.module('JobFormDefinition', [])
} }
} }
}); //Form });

View File

@@ -0,0 +1,84 @@
/*********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* LicenseForm.js
*
*
*/
'use strict';
angular.module('LicenseFormDefinition', [])
.value('LicenseForm', {
name: 'license',
well: false,
forceListeners: true,
fields: {
license_status: {
type: 'custom',
control: "<div class=\"license-status\" ng-class=\"status_color\"><i class=\"fa fa-circle\"></i> " +
"{{ license_status }}</span></div>",
readonly: true,
section: 'License'
},
license_key: {
label: 'Key',
type: 'textarea',
'class': 'modal-input-xlarge',
readonly: true,
section: 'License'
},
license_date: {
label: 'Expires On',
type: 'text',
readonly: true,
section: 'License'
},
time_remaining: {
label: 'Time Left',
type: 'text',
readonly: true,
section: 'License'
},
available_instances: {
label: 'Available',
type: 'text',
readonly: true,
section: 'Managed Hosts'
},
current_instances: {
label: 'Used',
type: 'text',
readonly: true,
section: 'Managed Hosts'
},
free_instances: {
label: 'Remaining',
type: 'text',
readonly: true,
section: 'Managed Hosts',
controlNGClass: 'free_instances_class',
labelNGClass: 'free_instances_class'
},
company_name: {
label: 'Company',
type: 'text',
readonly: true,
section: 'Contact Info'
},
contact_name: {
label: 'Contact',
type: 'text',
readonly: true,
section: 'Contact Info'
},
contact_email: {
label: 'Contact Email',
type: 'text',
readonly: true,
section: 'Contact Info'
}
}
});

View File

@@ -7,13 +7,12 @@
* *
*/ */
angular.module('OrganizationFormDefinition', []) angular.module('OrganizationFormDefinition', [])
.value( .value('OrganizationForm', {
'OrganizationForm', {
addTitle: 'Create Organization', //Title in add mode addTitle: 'Create Organization', //Title in add mode
editTitle: '{{ name }}', //Title in edit mode editTitle: '{{ name }}', //Title in edit mode
name: 'organization', //entity or model name in singular form name: 'organization', //entity or model name in singular form
well: true, //Wrap the form with TB well/ well: true,
actions: { actions: {
stream: { stream: {
@@ -54,7 +53,7 @@ angular.module('OrganizationFormDefinition', [])
} }
}, },
related: { //related colletions (and maybe items?) related: {
users: { users: {
type: 'collection', type: 'collection',
@@ -87,14 +86,14 @@ angular.module('OrganizationFormDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "edit('users', \{\{ user.id \}\}, '\{\{ user.username \}\}')", ngClick: "edit('users', user.id, user.username)",
icon: 'icon-edit', icon: 'icon-edit',
'class': 'btn-default', 'class': 'btn-default',
awToolTip: 'Edit user' awToolTip: 'Edit user'
}, },
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "delete('users', \{\{ user.id \}\}, '\{\{ user.username \}\}', 'users')", ngClick: "delete('users', user.id, user.username, 'users')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-danger', "class": 'btn-danger',
awToolTip: 'Remove user' awToolTip: 'Remove user'
@@ -131,14 +130,14 @@ angular.module('OrganizationFormDefinition', [])
fieldActions: { // Actions available on each row fieldActions: { // Actions available on each row
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "edit('users', \{\{ admin.id \}\}, '\{\{ admin.username \}\}')", ngClick: "edit('users', admin.id, admin.username)",
icon: 'icon-edit', icon: 'icon-edit',
awToolTip: 'Edit administrator', awToolTip: 'Edit administrator',
'class': 'btn-default' 'class': 'btn-default'
}, },
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "delete('admins', \{\{ admin.id \}\}, '\{\{ admin.username \}\}', 'administrators')", ngClick: "delete('admins', admin.id, admin.username, 'administrators')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-danger', "class": 'btn-danger',
awToolTip: 'Remove administrator' awToolTip: 'Remove administrator'
@@ -149,5 +148,3 @@ angular.module('OrganizationFormDefinition', [])
} }
}); //OrganizationForm }); //OrganizationForm

View File

@@ -8,8 +8,7 @@
* *
*/ */
angular.module('PermissionFormDefinition', []) angular.module('PermissionFormDefinition', [])
.value( .value('PermissionsForm', {
'PermissionsForm', {
addTitle: 'Add Permission', //Title in add mode addTitle: 'Add Permission', //Title in add mode
editTitle: '{{ name }}', //Title in edit mode editTitle: '{{ name }}', //Title in edit mode
@@ -32,10 +31,14 @@ angular.module('PermissionFormDefinition', [])
label: 'Permission Type', label: 'Permission Type',
labelClass: 'prepend-asterisk', labelClass: 'prepend-asterisk',
type: 'radio_group', type: 'radio_group',
options: [ options: [{
{ label: 'Inventory', value: 'Inventory', selected: true }, label: 'Inventory',
{ label: 'Deployment', value: 'Deploy'} value: 'Inventory',
], selected: true
}, {
label: 'Deployment',
value: 'Deploy'
}],
ngChange: 'selectCategory()' ngChange: 'selectCategory()'
}, },
name: { name: {
@@ -66,7 +69,10 @@ angular.module('PermissionFormDefinition', [])
sourceField: 'name', sourceField: 'name',
ngShow: "category == 'Deploy'", ngShow: "category == 'Deploy'",
ngClick: 'lookUpProject()', ngClick: 'lookUpProject()',
awRequiredWhen: { variable: "projectrequired", init: "false" } awRequiredWhen: {
variable: "projectrequired",
init: "false"
}
}, },
inventory: { inventory: {
label: 'Inventory', label: 'Inventory',
@@ -74,36 +80,54 @@ angular.module('PermissionFormDefinition', [])
sourceModel: 'inventory', sourceModel: 'inventory',
sourceField: 'name', sourceField: 'name',
ngClick: 'lookUpInventory()', ngClick: 'lookUpInventory()',
awRequiredWhen: {variable: "inventoryrequired", init: "true" } awRequiredWhen: {
variable: "inventoryrequired",
init: "true"
}
}, },
permission_type: { permission_type: {
label: 'Permission', label: 'Permission',
labelClass: 'prepend-asterisk', labelClass: 'prepend-asterisk',
type: 'radio_group', type: 'radio_group',
options: [ options: [{
{label: 'Read', value: 'read', ngShow: "category == 'Inventory'" }, label: 'Read',
{label: 'Write', value: 'write', ngShow: "category == 'Inventory'" }, value: 'read',
{label: 'Admin', value: 'admin', ngShow: "category == 'Inventory'" }, ngShow: "category == 'Inventory'"
{label: 'Run', value: 'run', ngShow: "category == 'Deploy'" }, }, {
{label: 'Check', value: 'check', ngShow: "category == 'Deploy'" } label: 'Write',
], value: 'write',
helpCollapse: [{ hdr: 'Permission', ngBind: 'permissionTypeHelp' }] ngShow: "category == 'Inventory'"
}, {
label: 'Admin',
value: 'admin',
ngShow: "category == 'Inventory'"
}, {
label: 'Run',
value: 'run',
ngShow: "category == 'Deploy'"
}, {
label: 'Check',
value: 'check',
ngShow: "category == 'Deploy'"
}],
helpCollapse: [{
hdr: 'Permission',
ngBind: 'permissionTypeHelp'
}]
} }
}, },
buttons: { //for now always generates <button> tags buttons: {
save: { save: {
ngClick: 'formSave()', //$scope.function to call on click, optional ngClick: 'formSave()',
ngDisabled: true //Disable when $pristine or $invalid, optional ngDisabled: true
}, },
reset: { reset: {
ngClick: 'formReset()', ngClick: 'formReset()',
ngDisabled: true //Disabled when $pristine ngDisabled: true
} }
}, },
related: { //related colletions (and maybe items?) related: { }
}
}); // Form }); // Form

View File

@@ -7,8 +7,7 @@
* *
*/ */
angular.module('ProjectStatusDefinition', []) angular.module('ProjectStatusDefinition', [])
.value( .value('ProjectStatusForm', {
'ProjectStatusForm', {
name: 'project_update', name: 'project_update',
editTitle: 'SCM Status', editTitle: 'SCM Status',

View File

@@ -8,8 +8,7 @@
* *
*/ */
angular.module('ProjectFormDefinition', []) angular.module('ProjectFormDefinition', [])
.value( .value('ProjectsForm', {
'ProjectsForm', {
addTitle: 'Create Project', // Title in add mode addTitle: 'Create Project', // Title in add mode
editTitle: '{{ name }}', // Title in edit mode editTitle: '{{ name }}', // Title in edit mode
@@ -52,7 +51,10 @@ angular.module('ProjectFormDefinition', [])
editRequired: false, editRequired: false,
excludeMode: 'edit', excludeMode: 'edit',
ngClick: 'lookUpOrganization()', ngClick: 'lookUpOrganization()',
awRequiredWhen: {variable: "organizationrequired", init: "true" }, awRequiredWhen: {
variable: "organizationrequired",
init: "true"
},
awPopOver: '<p>A project must have at least one organization. Pick one organization now to create the project, and then after ' + awPopOver: '<p>A project must have at least one organization. Pick one organization now to create the project, and then after ' +
'the project is created you can add additional organizations.</p><p>Only super users and organization administrators are allowed ' + 'the project is created you can add additional organizations.</p><p>Only super users and organization administrators are allowed ' +
'to make changes to projects. Associating one or more organizations to a project determins which organizations admins have ' + 'to make changes to projects. Associating one or more organizations to a project determins which organizations admins have ' +
@@ -99,7 +101,10 @@ angular.module('ProjectFormDefinition', [])
type: 'select', type: 'select',
id: 'local-path-select', id: 'local-path-select',
ngOptions: 'path.label for path in project_local_paths', ngOptions: 'path.label for path in project_local_paths',
awRequiredWhen: { variable: "pathRequired", init: false }, awRequiredWhen: {
variable: "pathRequired",
init: false
},
ngShow: "scm_type.value == '' && !showMissingPlaybooksAlert", ngShow: "scm_type.value == '' && !showMissingPlaybooksAlert",
awPopOver: '<p>Select from the list of directories found in the base path.' + awPopOver: '<p>Select from the list of directories found in the base path.' +
'Together the base path and the playbook directory provide the full path used to locate playbooks.</p>' + 'Together the base path and the playbook directory provide the full path used to locate playbooks.</p>' +
@@ -112,29 +117,34 @@ angular.module('ProjectFormDefinition', [])
label: 'SCM URL', label: 'SCM URL',
type: 'text', type: 'text',
ngShow: "scm_type && scm_type.value !== ''", ngShow: "scm_type && scm_type.value !== ''",
awRequiredWhen: { variable: "scmRequired", init: false }, awRequiredWhen: {
helpCollapse: [ variable: "scmRequired",
{ hdr: 'GIT URLs', init: false
},
helpCollapse: [{
hdr: 'GIT URLs',
content: '<p>Example URLs for GIT SCM include:</p><ul class=\"no-bullets\"><li>https://github.com/ansible/ansible.git</li>' + content: '<p>Example URLs for GIT SCM include:</p><ul class=\"no-bullets\"><li>https://github.com/ansible/ansible.git</li>' +
'<li>git@github.com:ansible/ansible.git</li><li>git://servername.example.com/ansible.git</li></ul>' + '<li>git@github.com:ansible/ansible.git</li><li>git://servername.example.com/ansible.git</li></ul>' +
'<p><strong>Note:</strong> If using SSH protocol for GitHub or Bitbucket, enter in the SSH key only, ' + '<p><strong>Note:</strong> If using SSH protocol for GitHub or Bitbucket, enter in the SSH key only, ' +
'do not enter a username (other than git). Additionally, GitHub and Bitbucket do not support password authentication when using ' + 'do not enter a username (other than git). Additionally, GitHub and Bitbucket do not support password authentication when using ' +
'SSH protocol. GIT read only protocol (git://) does not use username or password information.', 'SSH protocol. GIT read only protocol (git://) does not use username or password information.',
show: "scm_type.value == 'git'" }, show: "scm_type.value == 'git'"
{ hdr: 'SVN URLs', }, {
hdr: 'SVN URLs',
content: '<p>Example URLs for Subversion SCM include:</p>' + content: '<p>Example URLs for Subversion SCM include:</p>' +
'<ul class=\"no-bullets\"><li>https://github.com/ansible/ansible</li><li>svn://servername.example.com/path</li>' + '<ul class=\"no-bullets\"><li>https://github.com/ansible/ansible</li><li>svn://servername.example.com/path</li>' +
'<li>svn+ssh://servername.example.com/path</li></ul>', '<li>svn+ssh://servername.example.com/path</li></ul>',
show: "scm_type.value == 'svn'" }, show: "scm_type.value == 'svn'"
{ hdr: 'Mercurial URLs', }, {
hdr: 'Mercurial URLs',
content: '<p>Example URLs for Mercurial SCM include:</p>' + content: '<p>Example URLs for Mercurial SCM include:</p>' +
'<ul class=\"no-bullets\"><li>https://bitbucket.org/username/project</li><li>ssh://hg@bitbucket.org/username/project</li>' + '<ul class=\"no-bullets\"><li>https://bitbucket.org/username/project</li><li>ssh://hg@bitbucket.org/username/project</li>' +
'<li>ssh://server.example.com/path</li></ul>' + '<li>ssh://server.example.com/path</li></ul>' +
'<p><strong>Note:</strong> Mercurial does not support password authentication for SSH. ' + '<p><strong>Note:</strong> Mercurial does not support password authentication for SSH. ' +
'If applicable, add the username, password and key below. Do not put the username and key in the URL. ' + 'If applicable, add the username, password and key below. Do not put the username and key in the URL. ' +
'If using Bitbucket and SSH, do not supply your Bitbucket username.', 'If using Bitbucket and SSH, do not supply your Bitbucket username.',
show: "scm_type.value == 'hg'" } show: "scm_type.value == 'hg'"
] }]
}, },
scm_branch: { scm_branch: {
labelBind: "scmBranchLabel", labelBind: "scmBranchLabel",
@@ -157,8 +167,7 @@ angular.module('ProjectFormDefinition', [])
label: 'SCM Update Options', label: 'SCM Update Options',
type: 'checkbox_group', type: 'checkbox_group',
ngShow: "scm_type && scm_type.value !== ''", ngShow: "scm_type && scm_type.value !== ''",
fields: [ fields: [{
{
name: 'scm_clean', name: 'scm_clean',
label: 'Clean', label: 'Clean',
type: 'checkbox', type: 'checkbox',
@@ -169,8 +178,7 @@ angular.module('ProjectFormDefinition', [])
dataContainer: 'body', dataContainer: 'body',
dataPlacement: 'right', dataPlacement: 'right',
labelClass: 'checkbox-options' labelClass: 'checkbox-options'
}, }, {
{
name: 'scm_delete_on_update', name: 'scm_delete_on_update',
label: 'Delete on Update', label: 'Delete on Update',
type: 'checkbox', type: 'checkbox',
@@ -182,8 +190,7 @@ angular.module('ProjectFormDefinition', [])
dataContainer: 'body', dataContainer: 'body',
dataPlacement: 'right', dataPlacement: 'right',
labelClass: 'checkbox-options' labelClass: 'checkbox-options'
}, }, {
{
name: 'scm_update_on_launch', name: 'scm_update_on_launch',
label: 'Update on Launch', label: 'Update on Launch',
type: 'checkbox', type: 'checkbox',
@@ -194,23 +201,22 @@ angular.module('ProjectFormDefinition', [])
dataContainer: 'body', dataContainer: 'body',
dataPlacement: 'right', dataPlacement: 'right',
labelClass: 'checkbox-options' labelClass: 'checkbox-options'
} }]
]
} }
}, },
buttons: { //for now always generates <button> tags buttons: {
save: { save: {
ngClick: 'formSave()', //$scope.function to call on click, optional ngClick: 'formSave()',
ngDisabled: true //Disable when $pristine or $invalid, optional ngDisabled: true
}, },
reset: { reset: {
ngClick: 'formReset()', ngClick: 'formReset()',
ngDisabled: true //Disabled when $pristine ngDisabled: true
} }
}, },
related: { //related colletions (and maybe items?) related: {
organizations: { organizations: {
type: 'collection', type: 'collection',
title: 'Organizations', title: 'Organizations',
@@ -239,14 +245,14 @@ angular.module('ProjectFormDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "edit('organizations', \{\{ organization.id \}\}, '\{\{ organization.name \}\}')", ngClick: "edit('organizations', organization.id, organization.name)",
icon: 'icon-edit', icon: 'icon-edit',
awToolTip: 'Edit the organization', awToolTip: 'Edit the organization',
'class': 'btn btn-default' 'class': 'btn btn-default'
}, },
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "delete('organizations', \{\{ organization.id \}\}, '\{\{ organization.name \}\}', 'organizations')", ngClick: "delete('organizations', organization.id, organization.name, 'organizations')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-danger', "class": 'btn-danger',
awToolTip: 'Delete the organization' awToolTip: 'Delete the organization'
@@ -256,5 +262,3 @@ angular.module('ProjectFormDefinition', [])
} }
}); // Form }); // Form

View File

@@ -7,8 +7,7 @@
* *
*/ */
angular.module('TeamFormDefinition', []) angular.module('TeamFormDefinition', [])
.value( .value('TeamForm', {
'TeamForm', {
addTitle: 'Create Team', //Legend in add mode addTitle: 'Create Team', //Legend in add mode
editTitle: '{{ name }}', //Legend in edit mode editTitle: '{{ name }}', //Legend in edit mode
@@ -51,22 +50,25 @@ angular.module('TeamFormDefinition', [])
sourceModel: 'organization', sourceModel: 'organization',
sourceField: 'name', sourceField: 'name',
ngClick: 'lookUpOrganization()', ngClick: 'lookUpOrganization()',
awRequiredWhen: {variable: "teamrequired", init: "true" } awRequiredWhen: {
variable: "teamrequired",
init: "true"
}
} }
}, },
buttons: { //for now always generates <button> tags buttons: {
save: { save: {
ngClick: 'formSave()', //$scope.function to call on click, optional ngClick: 'formSave()',
ngDisabled: true //Disable when $pristine or $invalid, optional ngDisabled: true
}, },
reset: { reset: {
ngClick: 'formReset()', ngClick: 'formReset()',
ngDisabled: true //Disabled when $pristine ngDisabled: true
} }
}, },
related: { //related colletions (and maybe items?) related: {
credentials: { credentials: {
type: 'collection', type: 'collection',
@@ -96,14 +98,14 @@ angular.module('TeamFormDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "edit('credentials', \{\{ credential.id \}\}, '\{\{ credential.name \}\}')", ngClick: "edit('credentials', credential.id, credential.name)",
icon: 'icon-edit', icon: 'icon-edit',
awToolTip: 'Modify the credential', awToolTip: 'Modify the credential',
'class': 'btn btn-default' 'class': 'btn btn-default'
}, },
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "delete('credentials', \{\{ credential.id \}\}, '\{\{ credential.name \}\}', 'credentials')", ngClick: "delete('credentials', credential.id, credential.name, 'credentials')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-danger', "class": 'btn-danger',
awToolTip: 'Remove the credential' awToolTip: 'Remove the credential'
@@ -131,7 +133,7 @@ angular.module('TeamFormDefinition', [])
name: { name: {
key: true, key: true,
label: 'Name', label: 'Name',
ngClick: "edit('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}')" ngClick: "edit('permissions', permission.id, permission.name)"
}, },
inventory: { inventory: {
label: 'Inventory', label: 'Inventory',
@@ -153,7 +155,7 @@ angular.module('TeamFormDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "edit('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}')", ngClick: "edit('permissions', permission.id, permission.name)",
icon: 'icon-edit', icon: 'icon-edit',
awToolTip: 'Edit the permission', awToolTip: 'Edit the permission',
'class': 'btn btn-default' 'class': 'btn btn-default'
@@ -161,7 +163,7 @@ angular.module('TeamFormDefinition', [])
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "delete('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}', 'permissions')", ngClick: "delete('permissions', permission.id, permission.name, 'permissions')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-danger', "class": 'btn-danger',
awToolTip: 'Delete the permission', awToolTip: 'Delete the permission',
@@ -198,14 +200,14 @@ angular.module('TeamFormDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "edit('projects', \{\{ project.id \}\}, '\{\{ project.name \}\}')", ngClick: "edit('projects', project.id, project.name)",
icon: 'icon-edit', icon: 'icon-edit',
awToolTip: 'Modify the project', awToolTip: 'Modify the project',
'class': 'btn btn-default' 'class': 'btn btn-default'
}, },
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "delete('projects', \{\{ project.id \}\}, '\{\{ project.name \}\}', 'projects')", ngClick: "delete('projects', project.id, project.name, 'projects')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-danger', "class": 'btn-danger',
awToolTip: 'Remove the project' awToolTip: 'Remove the project'
@@ -244,14 +246,14 @@ angular.module('TeamFormDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "edit('users', \{\{ user.id \}\}, '\{\{ user.username \}\}')", ngClick: "edit('users', user.id, user.username)",
icon: 'icon-edit', icon: 'icon-edit',
awToolTip: 'Edit user', awToolTip: 'Edit user',
'class': 'btn btn-default' 'class': 'btn btn-default'
}, },
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "delete('users', \{\{ user.id \}\}, '\{\{ user.username \}\}', 'users')", ngClick: "delete('users', user.id, user.username, 'users')",
icon: 'icon-terash', icon: 'icon-terash',
"class": 'btn-danger', "class": 'btn-danger',
awToolTip: 'Remove user' awToolTip: 'Remove user'
@@ -262,4 +264,3 @@ angular.module('TeamFormDefinition', [])
} }
}); //InventoryForm }); //InventoryForm

View File

@@ -7,13 +7,12 @@
* *
*/ */
angular.module('UserFormDefinition', []) angular.module('UserFormDefinition', [])
.value( .value('UserForm', {
'UserForm', {
addTitle: 'Create User', //Legend in add mode addTitle: 'Create User',
editTitle: '{{ username }}', //Legend in edit mode editTitle: '{{ username }}',
name: 'user', //Form name attribute name: 'user',
well: true, //Wrap the form with TB well well: true,
forceListeners: true, forceListeners: true,
actions: { actions: {
@@ -57,12 +56,18 @@ angular.module('UserFormDefinition', [])
sourceField: 'name', sourceField: 'name',
ngClick: 'lookUpOrganization()', ngClick: 'lookUpOrganization()',
excludeMode: 'edit', excludeMode: 'edit',
awRequiredWhen: { variable: "orgrequired", init: true } awRequiredWhen: {
variable: "orgrequired",
init: true
}
}, },
username: { username: {
label: 'Username', label: 'Username',
type: 'text', type: 'text',
awRequiredWhen: { variable: "not_ldap_user", init: true }, awRequiredWhen: {
variable: "not_ldap_user",
init: true
},
autocomplete: false autocomplete: false
}, },
password: { password: {
@@ -100,18 +105,18 @@ angular.module('UserFormDefinition', [])
} }
}, },
buttons: { //for now always generates <button> tags buttons: {
save: { save: {
ngClick: 'formSave()', //$scope.function to call on click, optional ngClick: 'formSave()',
ngDisabled: true //Disable when $pristine or $invalid, optional ngDisabled: true
}, },
reset: { reset: {
ngClick: 'formReset()', ngClick: 'formReset()',
ngDisabled: true //Disabled when $pristine ngDisabled: true
} }
}, },
related: { //related colletions (and maybe items?) related: {
credentials: { credentials: {
type: 'collection', type: 'collection',
@@ -141,14 +146,14 @@ angular.module('UserFormDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "edit('credentials', \{\{ credential.id \}\}, '\{\{ credential.name \}\}')", ngClick: "edit('credentials', credential.id, credential.name)",
icon: 'icon-edit', icon: 'icon-edit',
awToolTip: 'Edit the credential', awToolTip: 'Edit the credential',
'class': 'btn btn-default' 'class': 'btn btn-default'
}, },
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "delete('credentials', \{\{ credential.id \}\}, '\{\{ credential.name \}\}', 'credentials')", ngClick: "delete('credentials', credential.id, credential.name, 'credentials')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-danger', "class": 'btn-danger',
awToolTip: 'Delete the credential' awToolTip: 'Delete the credential'
@@ -176,7 +181,7 @@ angular.module('UserFormDefinition', [])
name: { name: {
key: true, key: true,
label: 'Name', label: 'Name',
ngClick: "edit('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}')" ngClick: "edit('permissions', permission.id, permission.name)"
}, },
inventory: { inventory: {
label: 'Inventory', label: 'Inventory',
@@ -199,7 +204,7 @@ angular.module('UserFormDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "edit('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}')", ngClick: "edit('permissions', permission.id, permission.name)",
icon: 'icon-edit', icon: 'icon-edit',
awToolTip: 'Edit the permission', awToolTip: 'Edit the permission',
'class': 'btn btn-default' 'class': 'btn btn-default'
@@ -207,7 +212,7 @@ angular.module('UserFormDefinition', [])
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "delete('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}', 'permissions')", ngClick: "delete('permissions', permission.id, permission.name, 'permissions')",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-danger', "class": 'btn-danger',
awToolTip: 'Delete the permission', awToolTip: 'Delete the permission',
@@ -224,8 +229,7 @@ angular.module('UserFormDefinition', [])
open: false, // Open accordion on load? open: false, // Open accordion on load?
base: '/organizations', base: '/organizations',
actions: { actions: {},
},
fields: { fields: {
name: { name: {
@@ -244,8 +248,7 @@ angular.module('UserFormDefinition', [])
iterator: 'organization', iterator: 'organization',
open: false, open: false,
actions: { actions: {},
},
fields: { fields: {
name: { name: {
@@ -264,8 +267,7 @@ angular.module('UserFormDefinition', [])
iterator: 'team', iterator: 'team',
open: false, open: false,
actions: { actions: {},
},
fields: { fields: {
name: { name: {
@@ -284,8 +286,7 @@ angular.module('UserFormDefinition', [])
iterator: 'project', iterator: 'project',
open: false, open: false,
actions: { actions: {},
},
fields: { fields: {
name: { name: {
@@ -301,4 +302,3 @@ angular.module('UserFormDefinition', [])
} }
}); //UserForm }); //UserForm

View File

@@ -8,58 +8,79 @@
* @dict * @dict
*/ */
'use strict';
angular.module('InventoryGroupsHelpDefinition', []) angular.module('InventoryGroupsHelpDefinition', [])
.value( .value('InventoryGroupsHelp', {
'InventoryGroupsHelp', {
story: { story: {
hdr: 'Building your inventory', hdr: 'Building your inventory',
width: 510, width: 510,
height: 560, height: 560,
steps: [ steps: [{
{
intro: 'Start by creating a group:', intro: 'Start by creating a group:',
img: { src: 'groups001.png', maxWidth: 338 , maxHeight: 222 }, img: {
src: 'groups001.png',
maxWidth: 338,
maxHeight: 222
},
box: "Click <i class=\"fa fa-plus\"></i> on the groups list (the left side of the page) to add a new group.", box: "Click <i class=\"fa fa-plus\"></i> on the groups list (the left side of the page) to add a new group.",
autoOffNotice: true autoOffNotice: true
}, }, {
{
intro: 'Enter group properties:', intro: 'Enter group properties:',
img: { src: 'groups002.png', maxWidth: 443, maxHeight: 251 }, img: {
src: 'groups002.png',
maxWidth: 443,
maxHeight: 251
},
box: 'Enter the group name, a description and any inventory variables. Variables can be entered using either JSON or YAML syntax. ' + box: 'Enter the group name, a description and any inventory variables. Variables can be entered using either JSON or YAML syntax. ' +
'For more on inventory variables, see <a href=\"http://docs.ansible.com/intro_inventory.html\" target="_blank"> ' + 'For more on inventory variables, see <a href=\"http://docs.ansible.com/intro_inventory.html\" target="_blank"> ' +
'docs.ansible.com/intro_inventory.html</a>' 'docs.ansible.com/intro_inventory.html</a>'
}, }, {
{
intro: 'Cloud inventory: select cloud source', intro: 'Cloud inventory: select cloud source',
img: { src: 'groups003.png', maxWidth: 412, maxHeight: 215 }, img: {
src: 'groups003.png',
maxWidth: 412,
maxHeight: 215
},
box: "For a cloud inventory, choose the cloud provider from the list and select your credentials. If you have not already setup " + box: "For a cloud inventory, choose the cloud provider from the list and select your credentials. If you have not already setup " +
"credentials for the provider, you will need to do that first on the <a href=\"/#/credentials\" " + "credentials for the provider, you will need to do that first on the <a href=\"/#/credentials\" " +
"target=\"_blank\">Credentials</a> tab." "target=\"_blank\">Credentials</a> tab."
}, }, {
{
intro: 'Cloud inventory: synchronize Tower with the cloud', intro: 'Cloud inventory: synchronize Tower with the cloud',
img: { src: 'groups004.png', maxWidth: 261, maxHeight: 221 }, img: {
box: "To pull the cloud inventory into Tower, initiate an inventory sync by clicking <i class=\"fa fa-exchange\"></i>." src: 'groups004.png',
maxWidth: 261,
maxHeight: 221
}, },
{ box: "To pull the cloud inventory into Tower, initiate an inventory sync by clicking <i class=\"fa fa-exchange\"></i>."
}, {
intro: "Groups can have subgroups:", intro: "Groups can have subgroups:",
img: { src: 'groups005.png', maxWidth: 430, maxHeight: 206 }, img: {
src: 'groups005.png',
maxWidth: 430,
maxHeight: 206
},
box: "<div class=\"text-left\">First, select a group. Then click <i class=\"fa fa-plus\"></i> to create a new group. The new group " + box: "<div class=\"text-left\">First, select a group. Then click <i class=\"fa fa-plus\"></i> to create a new group. The new group " +
"will be added to the selected group.</div>" "will be added to the selected group.</div>"
}, }, {
{
intro: 'Copy or move groups:', intro: 'Copy or move groups:',
img: { src: 'groups006.png', maxWidth: 263, maxHeight: 211 }, img: {
src: 'groups006.png',
maxWidth: 263,
maxHeight: 211
},
box: "<div class=\"text-left\">Copy or move a group by dragging and dropping its name onto another group name. A dialog will appear " + box: "<div class=\"text-left\">Copy or move a group by dragging and dropping its name onto another group name. A dialog will appear " +
"asking if the group should be coppied or moved.</div>" "asking if the group should be coppied or moved.</div>"
}, }, {
{
intro: 'Adding hosts:', intro: 'Adding hosts:',
img: { src: 'groups007.png', maxWidth: 466, maxHeight: 178 }, img: {
src: 'groups007.png',
maxWidth: 466,
maxHeight: 178
},
box: "<div class=\"text-left\"><p>First, select a Group. " + box: "<div class=\"text-left\"><p>First, select a Group. " +
"Then click <i class=\"fa fa-plus\"></i> on the hosts list (the right side of the page) to create a host. " + "Then click <i class=\"fa fa-plus\"></i> on the hosts list (the right side of the page) to create a host. " +
"The new host will be part of the selected group.</p><p>Note hosts cannot be added to the All Hosts group.</p></div>" "The new host will be part of the selected group.</p><p>Note hosts cannot be added to the All Hosts group.</p></div>"
} }]
]
} }
}); });

View File

@@ -1,24 +0,0 @@
/*********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* InventoryHosts.js
* Help object for Inventory-> Hosts page.
*
*
*/
angular.module('InventoryHostsHelpDefinition', [])
.value(
'InventoryHostsHelp', {
story: {
hdr: 'Managing Hosts',
steps: {
step1: {
intro: 'Start by selecting a group:',
img: { src: 'help003.png', maxWidth: 315 , maxHeight: 198 },
box: "On the group selector, click the name of a group. Hosts contained in the group" +
" will appear on the right.",
height: 500
}
}
}
});

View File

@@ -7,34 +7,36 @@
* *
*/ */
'use strict';
angular.module('AccessHelper', ['RestServices', 'Utilities', 'ngCookies']) angular.module('AccessHelper', ['RestServices', 'Utilities', 'ngCookies'])
.factory('CheckAccess', ['$rootScope', 'Alert', 'Rest', 'GetBasePath', 'ProcessErrors', .factory('CheckAccess', ['$rootScope', 'Alert', 'Rest', 'GetBasePath', 'ProcessErrors',
function ($rootScope, Alert, Rest, GetBasePath, ProcessErrors) { function ($rootScope, Alert, Rest, GetBasePath, ProcessErrors) {
return function (params) { return function (params) {
// set PermissionAddAllowed to true or false based on user access. admins and org admins are granted // set PermissionAddAllowed to true or false based on user access. admins and org admins are granted
// accesss. // accesss.
var me = $rootScope.current_user; var me = $rootScope.current_user,
var scope = params.scope; scope = params.scope;
if (me.is_superuser) { if (me.is_superuser) {
scope.PermissionAddAllowed = true; scope.PermissionAddAllowed = true;
} } else {
else {
if (me.related.admin_of_organizations) { if (me.related.admin_of_organizations) {
Rest.setUrl(me.related.admin_of_organizations); Rest.setUrl(me.related.admin_of_organizations);
Rest.get() Rest.get()
.success( function(data, status, headers, config) { .success(function (data) {
if (data.results.length > 0) { if (data.results.length > 0) {
scope.PermissionAddAllowed = true; scope.PermissionAddAllowed = true;
} } else {
else {
scope.PermissionAddAllowed = false; scope.PermissionAddAllowed = false;
} }
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, {
{ hdr: 'Error!', msg: 'Call to ' + me.related.admin_of_organizations + hdr: 'Error!',
' failed. DELETE returned status: ' + status }); msg: 'Call to ' + me.related.admin_of_organizations +
' failed. DELETE returned status: ' + status
});
}); });
} }
} }
@@ -42,36 +44,35 @@ angular.module('AccessHelper', ['RestServices', 'Utilities', 'ngCookies'])
// Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.'); // Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
//} //}
//return access; //return access;
};
} }
}]) ])
.factory('CheckLicense', ['$rootScope', '$cookieStore', 'Alert', '$location', 'Authorization', .factory('CheckLicense', ['$rootScope', '$cookieStore', 'Alert', '$location', 'Authorization',
function ($rootScope, $cookieStore, Alert, $location, Authorization) { function ($rootScope, $cookieStore, Alert, $location, Authorization) {
return function () { return function () {
// Check license status and alert the user, if needed // Check license status and alert the user, if needed
var status = 'success'; var status = 'success',
var hdr, msg; hdr, msg,
var license = $cookieStore.get('license'); license = $cookieStore.get('license'),
purchase_msg = '<p>To purchase a license or extend an existing license ' +
var purchase_msg = '<p>To purchase a license or extend an existing license ' +
'<a href="http://www.ansible.com/ansible-pricing" target="_blank"><strong>visit the Ansible online store</strong></a>, ' + '<a href="http://www.ansible.com/ansible-pricing" target="_blank"><strong>visit the Ansible online store</strong></a>, ' +
'or visit <strong><a href="https://support.ansible.com" target="_blank">support.ansible.com</a></strong> for assistance.</p>'; 'or visit <strong><a href="https://support.ansible.com" target="_blank">support.ansible.com</a></strong> for assistance.</p>';
if (license && !Authorization.licenseTested()) { if (license && !Authorization.licenseTested()) {
// This is our first time evaluating the license // This is our first time evaluating the license
license['tested'] = true; license.tested = true;
$cookieStore.remove('license'); $cookieStore.remove('license');
$cookieStore.put('license', license); $cookieStore.put('license', license);
$rootScope.license_tested = true; $rootScope.license_tested = true;
if (license['valid_key'] !== undefined && license['valid_key'] == false) { if (license.valid_key !== undefined && license.valid_key === false) {
// The license is invalid. Stop the user from logging in. // The license is invalid. Stop the user from logging in.
status = 'alert-danger'; status = 'alert-danger';
hdr = 'License Error'; hdr = 'License Error';
msg = '<p>There is a problem with the /etc/awx/license file on your Tower server. Check to make sure Tower can access ' + msg = '<p>There is a problem with the /etc/awx/license file on your Tower server. Check to make sure Tower can access ' +
'the file.</p>' + purchase_msg; 'the file.</p>' + purchase_msg;
Alert(hdr, msg, status, null, false, true); Alert(hdr, msg, status, null, false, true);
} } else if (license.demo !== undefined && license.demo === true) {
else if (license['demo'] !== undefined && license['demo'] == true) {
// demo // demo
status = 'alert-info'; status = 'alert-info';
hdr = 'Tower Demo'; hdr = 'Tower Demo';
@@ -79,21 +80,20 @@ angular.module('AccessHelper', ['RestServices', 'Utilities', 'ngCookies'])
purchase_msg; purchase_msg;
Alert(hdr, msg, status); Alert(hdr, msg, status);
} }
if (license['date_expired'] !== undefined && license['date_expired'] == true) { if (license.date_expired !== undefined && license.date_expired === true) {
// expired // expired
status = 'alert-info'; status = 'alert-info';
hdr = 'License Expired'; hdr = 'License Expired';
msg = '<p>Your Ansible Tower License has expired and is no longer compliant. You can continue, but you will be ' + msg = '<p>Your Ansible Tower License has expired and is no longer compliant. You can continue, but you will be ' +
'unable to add any additional hosts.</p>' + purchase_msg; 'unable to add any additional hosts.</p>' + purchase_msg;
Alert(hdr, msg, status); Alert(hdr, msg, status);
} } else if (license.date_warning !== undefined && license.date_warning === true) {
else if (license['date_warning'] !== undefined && license['date_warning'] == true) {
status = 'alert-info'; status = 'alert-info';
hdr = 'License Warning'; hdr = 'License Warning';
msg = '<p>Your Ansible Tower license is about to expire!</p>' + purchase_msg; msg = '<p>Your Ansible Tower license is about to expire!</p>' + purchase_msg;
Alert(hdr, msg, status); Alert(hdr, msg, status);
} }
if (license['free_instances'] !== undefined && parseInt(license['free_instances']) <= 0) { if (license.free_instances !== undefined && parseInt(license.free_instances) <= 0) {
status = 'alert-info'; status = 'alert-info';
hdr = 'License Warning'; hdr = 'License Warning';
msg = '<p>Your Ansible Tower license has reached capacity for the number of managed ' + msg = '<p>Your Ansible Tower license has reached capacity for the number of managed ' +
@@ -101,5 +101,6 @@ angular.module('AccessHelper', ['RestServices', 'Utilities', 'ngCookies'])
Alert(hdr, msg, status, null, true); Alert(hdr, msg, status, null, true);
} }
} }
};
} }
}]); ]);

View File

@@ -9,34 +9,35 @@
* *
*/ */
'use strict';
angular.module('ChildrenHelper', ['RestServices', 'Utilities']) angular.module('ChildrenHelper', ['RestServices', 'Utilities'])
.factory('ToggleChildren', ['Alert', 'Rest', 'GetBasePath','ProcessErrors','FormatDate', .factory('ToggleChildren', [ function () {
function(Alert, Rest, GetBasePath, ProcessErrors, FormatDate) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var list = params.list; list = params.list,
var id = params.id; id = params.id,
var set = scope[list.name]; // set is now a pointer to scope[list.name] set = scope[list.name],
i, clicked, found = false;
function expand(node) { function expand(node) {
set[node]['ngicon'] = 'fa fa-minus-square-o node-toggle'; var i;
for (var i = node + 1; i < set.length; i++) { set[node].ngicon = 'fa fa-minus-square-o node-toggle';
if (set[i].parent == set[node].id) { for (i = node + 1; i < set.length; i++) {
set[i]['show'] = true; if (set[i].parent === set[node].id) {
//if (set[i].related.children) { set[i].show = true;
// expand(i);
//}
} }
} }
} }
function collapse(node) { function collapse(node) {
set[node]['ngicon'] = 'fa fa-plus-square-o node-toggle'; var i;
for (var i = node + 1; i < set.length; i++) { set[node].ngicon = 'fa fa-plus-square-o node-toggle';
if (set[i].parent == set[node].id) { for (i = node + 1; i < set.length; i++) {
set[i]['show'] = false; if (set[i].parent === set[node].id) {
if (set[i]['related']['children']) { set[i].show = false;
if (set[i].related.children) {
collapse(i); collapse(i);
} }
} }
@@ -44,37 +45,20 @@ angular.module('ChildrenHelper', ['RestServices', 'Utilities'])
} }
// Scan the array list and find the clicked element // Scan the array list and find the clicked element
var clicked; for (i = 0; i < set.length && found === false; i++) {
var found = false; if (set[i].id === id) {
for (var i = 0; i < set.length && found == false; i++){
if (set[i].id == id) {
clicked = i; clicked = i;
found = true; found = true;
} }
} }
// Expand or collapse children based on clicked element's icon // Expand or collapse children based on clicked element's icon
if (/plus-square-o/.test(set[clicked]['ngicon'])) { if (/plus-square-o/.test(set[clicked].ngicon)) {
// Expand: lookup and display children // Expand: lookup and display children
expand(clicked); expand(clicked);
} } else if (/minus-square-o/.test(set[clicked].ngicon)) {
else if (/minus-square-o/.test(set[clicked]['ngicon'])) {
collapse(clicked); collapse(clicked);
} }
};
} }
}]); ]);

View File

@@ -7,109 +7,111 @@
* *
*/ */
'use strict';
angular.module('CredentialsHelper', ['Utilities']) angular.module('CredentialsHelper', ['Utilities'])
.factory('KindChange', [ 'Empty', function(Empty) { .factory('KindChange', ['Empty',
function (Empty) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var form = params.form; reset = params.reset,
var reset = params.reset; collapse, id;
// Put things in a default state // Put things in a default state
scope['usernameLabel'] = 'Username'; scope.usernameLabel = 'Username';
scope['aws_required'] = false; scope.aws_required = false;
scope['rackspace_required'] = false; scope.rackspace_required = false;
scope['sshKeyDataLabel'] = 'SSH Private Key'; scope.sshKeyDataLabel = 'SSH Private Key';
if (!Empty(scope['kind'])) { if (!Empty(scope.kind)) {
// Apply kind specific settings // Apply kind specific settings
switch(scope['kind'].value) { switch (scope.kind.value) {
case 'aws': case 'aws':
scope['aws_required'] = true; scope.aws_required = true;
break; break;
case 'rax': case 'rax':
scope['rackspace_required'] = true; scope.rackspace_required = true;
break; break;
case 'ssh': case 'ssh':
scope['usernameLabel'] = 'SSH Username'; scope.usernameLabel = 'SSH Username';
break; break;
case 'scm': case 'scm':
scope['sshKeyDataLabel'] = 'SCM Private Key'; scope.sshKeyDataLabel = 'SCM Private Key';
break; break;
} }
} }
// Reset all the field values related to Kind. // Reset all the field values related to Kind.
if (reset) { if (reset) {
scope['access_key'] = null; scope.access_key = null;
scope['secret_key'] = null; scope.secret_key = null;
scope['api_key'] = null; scope.api_key = null;
scope['username'] = null; scope.username = null;
scope['password'] = null; scope.password = null;
scope['password_confirm'] = null; scope.password_confirm = null;
scope['ssh_key_data'] = null; scope.ssh_key_data = null;
scope['ssh_key_unlock'] = null; scope.ssh_key_unlock = null;
scope['ssh_key_unlock_confirm'] = null; scope.ssh_key_unlock_confirm = null;
scope['sudo_username'] = null; scope.sudo_username = null;
scope['sudo_password'] = null; scope.sudo_password = null;
scope['sudo_password_confirm'] = null; scope.sudo_password_confirm = null;
} }
// Collapse or open help widget based on whether scm value is selected // Collapse or open help widget based on whether scm value is selected
var collapse = $('#credential_kind').parent().find('.panel-collapse').first(); collapse = $('#credential_kind').parent().find('.panel-collapse').first();
var id = collapse.attr('id'); id = collapse.attr('id');
if (!Empty(scope.kind) && scope.kind.value !== '') { if (!Empty(scope.kind) && scope.kind.value !== '') {
if ($('#' + id + '-icon').hasClass('icon-minus')) { if ($('#' + id + '-icon').hasClass('icon-minus')) {
scope.accordionToggle('#' + id); scope.accordionToggle('#' + id);
} }
} } else {
else {
if ($('#' + id + '-icon').hasClass('icon-plus')) { if ($('#' + id + '-icon').hasClass('icon-plus')) {
scope.accordionToggle('#' + id); scope.accordionToggle('#' + id);
} }
} }
};
} }
}]) ])
.factory('OwnerChange', [ function() { .factory('OwnerChange', [
function () {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var owner = scope['owner']; owner = scope.owner;
if (owner == 'team') { if (owner === 'team') {
scope['team_required'] = true; scope.team_required = true;
scope['user_required'] = false; scope.user_required = false;
scope['user'] = null; scope.user = null;
scope['user_username'] = null; scope.user_username = null;
} else {
scope.team_required = false;
scope.user_required = true;
scope.team = null;
scope.team_name = null;
} }
else { };
scope['team_required'] = false;
scope['user_required'] = true;
scope['team'] = null;
scope['team_name'] = null;
} }
])
}
}])
.factory('FormSave', ['$location', 'Rest', 'ProcessErrors', 'Empty', 'GetBasePath', 'CredentialForm', 'ReturnToCaller', 'Wait', .factory('FormSave', ['$location', 'Alert', 'Rest', 'ProcessErrors', 'Empty', 'GetBasePath', 'CredentialForm', 'ReturnToCaller', 'Wait',
function($location, Rest, ProcessErrors, Empty, GetBasePath, CredentialForm, ReturnToCaller, Wait) { function ($location, Alert, Rest, ProcessErrors, Empty, GetBasePath, CredentialForm, ReturnToCaller, Wait) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var mode = params.mode; // add or edit mode = params.mode,
var form = CredentialForm; form = CredentialForm,
var data = {} data = {}, fld, url;
for (var fld in form.fields) { for (fld in form.fields) {
if (fld !== 'access_key' && fld !== 'secret_key' && fld !== 'ssh_username' && if (fld !== 'access_key' && fld !== 'secret_key' && fld !== 'ssh_username' &&
fld !== 'ssh_password') { fld !== 'ssh_password') {
if (scope[fld] === null) { if (scope[fld] === null) {
data[fld] = ""; data[fld] = "";
} } else {
else {
data[fld] = scope[fld]; data[fld] = scope[fld];
} }
} }
@@ -118,65 +120,72 @@ angular.module('CredentialsHelper', ['Utilities'])
if (!Empty(scope.team)) { if (!Empty(scope.team)) {
data.team = scope.team; data.team = scope.team;
data.user = ""; data.user = "";
} } else {
else {
data.user = scope.user; data.user = scope.user;
data.team = ""; data.team = "";
} }
data['kind'] = scope['kind'].value; data.kind = scope.kind.value;
switch (data['kind']) { switch (data.kind) {
case 'ssh': case 'ssh':
data['password'] = scope['ssh_password']; data.password = scope.ssh_password;
break; break;
case 'aws': case 'aws':
data['username'] = scope['access_key']; data.username = scope.access_key;
data['password'] = scope['secret_key']; data.password = scope.secret_key;
break; break;
case 'rax': case 'rax':
data['password'] = scope['api_key']; data.password = scope.api_key;
break; break;
} }
if (Empty(data.team) && Empty(data.user)) { if (Empty(data.team) && Empty(data.user)) {
Alert('Missing User or Team', 'You must provide either a User or a Team. If this credential will only be accessed by a specific ' + Alert('Missing User or Team', 'You must provide either a User or a Team. If this credential will only be accessed by a specific ' +
'user, select a User. To allow a team of users to access this credential, select a Team.', 'alert-danger'); 'user, select a User. To allow a team of users to access this credential, select a Team.', 'alert-danger');
} } else {
else {
Wait('start'); Wait('start');
if (mode == 'add') { if (mode === 'add') {
var url = (!Empty(data.team)) ? GetBasePath('teams') + data.team + '/credentials/' : url = (!Empty(data.team)) ? GetBasePath('teams') + data.team + '/credentials/' :
GetBasePath('users') + data.user + '/credentials/'; GetBasePath('users') + data.user + '/credentials/';
Rest.setUrl(url); Rest.setUrl(url);
Rest.post(data) Rest.post(data)
.success( function(data, status, headers, config) { .success(function () {
Wait('stop'); Wait('stop');
var base = $location.path().replace(/^\//, '').split('/')[0]; var base = $location.path().replace(/^\//, '').split('/')[0];
(base == 'credentials') ? ReturnToCaller() : ReturnToCaller(1); if (base === 'credentials') {
}) ReturnToCaller();
.error( function(data, status, headers, config) {
Wait('stop');
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to create new Credential. POST status: ' + status });
});
} }
else { ReturnToCaller(1);
var url = GetBasePath('credentials') + scope.id + '/'; })
.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.setUrl(url);
Rest.put(data) Rest.put(data)
.success( function(data, status, headers, config) { .success(function () {
Wait('stop'); Wait('stop');
var base = $location.path().replace(/^\//, '').split('/')[0]; var base = $location.path().replace(/^\//, '').split('/')[0];
(base == 'credentials') ? ReturnToCaller() : ReturnToCaller(1); if (base === 'credentials') {
ReturnToCaller();
}
ReturnToCaller(1);
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
Wait('stop'); Wait('stop');
ProcessErrors(scope, data, status, form, ProcessErrors(scope, data, status, form, {
{ hdr: 'Error!', msg: 'Failed to update Credential. PUT status: ' + status }); hdr: 'Error!',
msg: 'Failed to update Credential. PUT status: ' + status
});
}); });
} }
} }
};
} }
}]); ]);

View File

@@ -6,169 +6,32 @@
* EventView - show the job_events form in a modal dialog * EventView - show the job_events form in a modal dialog
* *
*/ */
angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefinition'])
'use strict';
angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefinition', 'JobEventsFormDefinition'])
.factory('EventView', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm', .factory('EventView', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'JobEventDataForm', 'Empty', 'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'JobEventDataForm', 'Empty', 'JobEventsForm',
function ($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath, function ($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath,
FormatDate, JobEventDataForm, Empty) { FormatDate, JobEventDataForm, Empty, JobEventsForm) {
return function (params) { return function (params) {
// We're going to manipulate the form object each time the user clicks on View button. We can't rely on what's var event_id = params.event_id,
// left of the form in memory each time. Instead we have to define the form from scratch, so for now we're generator = GenerateForm,
// keeping it here inline rather than a separate file. form = angular.copy(JobEventsForm),
// scope,
// Form manipulation is done to remove any empty values. In order for a section (or accordion) to not be drawn, defaultUrl = GetBasePath('base') + 'job_events/' + event_id + '/';
// it needs to be removed prior to call jqueryui. Otherwise, attempting to hide accordion pieces after the
// the accordion is rendered creates undesired behavior.
var form = {
name: 'job_events',
well: false,
forceListeners: true,
fields: {
status: {
labelClass: 'job-\{\{ status \}\}',
type: 'custom',
section: 'Event',
control: '<div class=\"job-event-status job-\{\{ status \}\}\"><i class=\"fa icon-job-{{ status }}"></i> \{\{ status \}\}</div>'
},
id: {
label: 'ID',
type: 'text',
readonly: true,
section: 'Event',
'class': 'span1'
},
created: {
label: 'Created On',
type: 'text',
section: 'Event',
readonly: true
},
host: {
label: 'Host',
type: 'text',
readonly: true,
section: 'Event',
ngShow: "host !== ''"
},
play: {
label: 'Play',
type: 'text',
readonly: true,
section: 'Event',
ngShow: "play !== ''"
},
task: {
label: 'Task',
type: 'text',
readonly: true,
section: 'Event',
ngShow: "task !== ''"
},
rc: {
label: 'Return Code',
type: 'text',
readonly: true,
section: 'Results',
'class': 'span1',
ngShow: "rc !== ''"
},
msg: {
label: 'Msg',
type: 'textarea',
readonly: true,
section: 'Results',
'class': 'nowrap',
ngShow: "msg !== ''",
rows: 10
},
stdout: {
label: 'Std Out',
type: 'textarea',
readonly: true,
section: 'Results',
'class': 'nowrap',
ngShow: "stdout !== ''",
rows: 10
},
stderr: {
label: 'Std Err',
type: 'textarea',
readonly: true,
section: 'Results',
'class': 'nowrap',
ngShow: "stderr !== ''",
rows: 10
},
results: {
label: 'Results',
type: 'textarea',
section: 'Results',
readonly: true,
'class': 'nowrap',
ngShow: "results !== ''",
rows: 10
},
start: {
label: 'Start',
type: 'text',
readonly: true,
section: 'Timing',
ngShow: "start !== ''"
},
traceback: {
label: false,
type: 'textarea',
readonly: true,
section: 'Traceback',
'class': 'nowrap',
ngShow: "traceback !== ''",
rows: 10
},
end: {
label: 'End',
type: 'text',
readonly: true,
section: 'Timing',
ngShow: "end !== ''"
},
delta: {
label: 'Elapsed',
type: 'text',
readonly: true,
section: 'Timing',
ngShow: "delta !== ''"
},
module_name: {
label: 'Name',
type: 'text',
readonly: true,
section: 'Module',
ngShow: "module_name !== ''"
},
module_args: {
label: 'Args',
type: 'text',
readonly: true,
section: 'Module',
ngShow: "module_args !== ''"
}
}
};
var event_id = params.event_id;
var generator = GenerateForm;
var scope;
var defaultUrl = GetBasePath('base') + 'job_events/' + event_id + '/';
// Retrieve detail record and prepopulate the form // Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl); Rest.setUrl(defaultUrl);
Rest.get() Rest.get()
.success( function(data, status, headers, config) { .success(function (data) {
var i, n, fld, rows, txt, cDate;
// If event_data is not available, remove fields that depend on it // If event_data is not available, remove fields that depend on it
if ($.isEmptyObject(data['event_data']) || !data['event_data']['res'] || typeof data['event_data']['res'] == 'string') { if ($.isEmptyObject(data.event_data) || !data.event_data.res || typeof data.event_data.res === 'string') {
for (var fld in form.fields) { for (fld in form.fields) {
switch (fld) { switch (fld) {
case 'start': case 'start':
case 'end': case 'end':
@@ -187,12 +50,12 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
} }
} }
if ($.isEmptyObject(data['event_data']) || !data['event_data']['res'] || typeof data['event_data']['res'] != 'string') { if ($.isEmptyObject(data.event_data) || !data.event_data.res || typeof data.event_data.res !== 'string') {
delete form.fields['traceback']; delete form.fields.traceback;
} }
// Remove remaining form fields that do not have a corresponding data value // Remove remaining form fields that do not have a corresponding data value
for (var fld in form.fields) { for (fld in form.fields) {
switch (fld) { switch (fld) {
case 'start': case 'start':
case 'end': case 'end':
@@ -202,13 +65,12 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
case 'stderr': case 'stderr':
case 'msg': case 'msg':
case 'rc': case 'rc':
if (data['event_data'] && data['event_data']['res'] && Empty(data['event_data']['res'][fld])) { if (data.event_data && data.event_data.res && Empty(data.event_data.res[fld])) {
delete form.fields[fld]; delete form.fields[fld];
} } else {
else { if (form.fields[fld].type === 'textarea') {
if (form.fields[fld].type == 'textarea') { n = data.event_data.res[fld].match(/\n/g);
var n = data['event_data']['res'][fld].match(/\n/g); rows = (n) ? n.length : 1;
var rows = (n) ? n.length : 1;
rows = (rows > 10) ? 10 : rows; rows = (rows > 10) ? 10 : rows;
rows = (rows < 3) ? 3 : rows; rows = (rows < 3) ? 3 : rows;
form.fields[fld].rows = rows; form.fields[fld].rows = rows;
@@ -216,27 +78,24 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
} }
break; break;
case 'results': case 'results':
if ( data['event_data'] && data['event_data']['res'] && data['event_data']['res'][fld] == undefined) { if (data.event_data && data.event_data.res && data.event_data.res[fld] === undefined) {
// not defined // not defined
delete form.fields[fld]; delete form.fields[fld];
} } else if (!Array.isArray(data.event_data.res[fld]) || data.event_data.res[fld].length === 0) {
else if (!Array.isArray(data['event_data']['res'][fld]) || data['event_data']['res'][fld].length == 0) {
// defined, but empty // defined, but empty
delete form.fields[fld]; delete form.fields[fld];
} } else {
else {
// defined and not empty, so attempt to size the textarea field // defined and not empty, so attempt to size the textarea field
var txt = ''; txt = '';
for (var i=0; i < data['event_data']['res'][fld].length; i++) { for (i = 0; i < data.event_data.res[fld].length; i++) {
txt += data['event_data']['res'][fld][i]; txt += data.event_data.res[fld][i];
} }
if (txt == '') { if (txt === '') {
// there's an array, but the actual text is empty // there's an array, but the actual text is empty
delete form.fields[fld]; delete form.fields[fld];
} } else {
else { n = txt.match(/\n/g);
var n = txt.match(/\n/g); rows = (n) ? n.length : 1;
var rows = (n) ? n.length : 1;
rows = (rows > 10) ? 10 : rows; rows = (rows > 10) ? 10 : rows;
rows = (rows < 3) ? 3 : rows; rows = (rows < 3) ? 3 : rows;
form.fields[fld].rows = rows; form.fields[fld].rows = rows;
@@ -245,9 +104,9 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
break; break;
case 'module_name': case 'module_name':
case 'module_args': case 'module_args':
if (data['event_data'] && data['event_data']['res']) { if (data.event_data && data.event_data.res) {
if (data['event_data']['res']['invocation'] === undefined || if (data.event_data.res.invocation === undefined ||
data['event_data']['res']['invocation'][fld] === undefined) { data.event_data.res.invocation[fld] === undefined) {
delete form.fields[fld]; delete form.fields[fld];
} }
} }
@@ -256,60 +115,68 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
} }
// load the form // load the form
scope = generator.inject(form, { mode: 'edit', modal: true, related: false}); scope = generator.inject(form, {
mode: 'edit',
modal: true,
related: false
});
generator.reset(); generator.reset();
scope.formModalAction = function () { scope.formModalAction = function () {
$('#form-modal').modal("hide"); $('#form-modal').modal("hide");
} };
scope.formModalActionLabel = 'OK'; scope.formModalActionLabel = 'OK';
scope.formModalCancelShow = false; scope.formModalCancelShow = false;
scope.formModalInfo = 'View JSON'; scope.formModalInfo = 'View JSON';
$('#form-modal .btn-success').removeClass('btn-success').addClass('btn-none'); $('#form-modal .btn-success').removeClass('btn-success').addClass('btn-none');
$('#form-modal').addClass('skinny-modal'); $('#form-modal').addClass('skinny-modal');
scope.formModalHeader = data['event_display'].replace(/^\u00a0*/g,''); scope.formModalHeader = data.event_display.replace(/^\u00a0*/g, '');
// Respond to View JSON button // Respond to View JSON button
scope.formModalInfoAction = function () { scope.formModalInfoAction = function () {
var generator = GenerateForm; var generator = GenerateForm,
var scope = generator.inject(JobEventDataForm, { mode: 'edit', modal: true, related: false, scope = generator.inject(JobEventDataForm, {
modal_selector: '#form-modal2', modal_body_id: 'form-modal2-body', modal_title_id: 'formModal2Header' }); mode: 'edit',
modal: true,
related: false,
modal_selector: '#form-modal2',
modal_body_id: 'form-modal2-body',
modal_title_id: 'formModal2Header'
});
generator.reset(); generator.reset();
scope.formModal2Header = data['event_display'].replace(/^\u00a0*/g,''); scope.formModal2Header = data.event_display.replace(/^\u00a0*/g, '');
scope.event_data = JSON.stringify(data['event_data'], null, '\t'); scope.event_data = JSON.stringify(data.event_data, null, '\t');
scope.formModal2ActionLabel = 'OK'; scope.formModal2ActionLabel = 'OK';
scope.formModal2CancelShow = false; scope.formModal2CancelShow = false;
scope.formModal2Info = false; scope.formModal2Info = false;
scope.formModalInfo = 'View JSON'; scope.formModalInfo = 'View JSON';
scope.formModal2Action = function () { scope.formModal2Action = function () {
$('#form-modal2').modal("hide"); $('#form-modal2').modal("hide");
} };
$('#form-modal2 .btn-success').removeClass('btn-success').addClass('btn-none'); $('#form-modal2 .btn-success').removeClass('btn-success').addClass('btn-none');
};
if (typeof data.event_data.res === 'string') {
scope.traceback = data.event_data.res;
} }
if (typeof data['event_data']['res'] == 'string') { for (fld in form.fields) {
scope['traceback'] = data['event_data']['res'];
}
for (var fld in form.fields) {
switch (fld) { switch (fld) {
case 'status': case 'status':
if (data['failed']) { if (data.failed) {
scope['status'] = 'error'; scope.status = 'error';
} } else if (data.changed) {
else if (data['changed']) { scope.status = 'changed';
scope['status'] = 'changed'; } else {
} scope.status = 'success';
else {
scope['status'] = 'success';
} }
break; break;
case 'created': case 'created':
var cDate = new Date(data['created']); cDate = new Date(data.created);
scope['created'] = FormatDate(cDate); scope.created = FormatDate(cDate);
break; break;
case 'host': case 'host':
if (data['summary_fields'] && data['summary_fields']['host']) { if (data.summary_fields && data.summary_fields.host) {
scope['host'] = data['summary_fields']['host']['name']; scope.host = data.summary_fields.host.name;
} }
break; break;
case 'id': case 'id':
@@ -319,16 +186,16 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
break; break;
case 'start': case 'start':
case 'end': case 'end':
if (data['event_data'] && data['event_data']['res'] && !Empty(data['event_data']['res'][fld])) { if (data.event_data && data.event_data.res && !Empty(data.event_data.res[fld])) {
scope[fld] = data['event_data']['res'][fld]; scope[fld] = data.event_data.res[fld];
} }
break; break;
case 'results': case 'results':
if (Array.isArray(data['event_data']['res'][fld]) && data['event_data']['res'][fld].length > 0 ) { if (Array.isArray(data.event_data.res[fld]) && data.event_data.res[fld].length > 0) {
var txt = ''; txt = '';
for (var i=0; i < data['event_data']['res'][fld].length; i++) { for (i = 0; i < data.event_data.res[fld].length; i++) {
txt += data['event_data']['res'][fld][i]; txt += data.event_data.res[fld][i];
} }
if (txt !== '') { if (txt !== '') {
scope[fld] = txt; scope[fld] = txt;
@@ -340,14 +207,14 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
case 'stderr': case 'stderr':
case 'delta': case 'delta':
case 'rc': case 'rc':
if (data['event_data'] && data['event_data']['res'] && data['event_data']['res'][fld] !== undefined) { if (data.event_data && data.event_data.res && data.event_data.res[fld] !== undefined) {
scope[fld] = data['event_data']['res'][fld]; scope[fld] = data.event_data.res[fld];
} }
break; break;
case 'module_name': case 'module_name':
case 'module_args': case 'module_args':
if (data['event_data']['res'] && data['event_data']['res']['invocation']) { if (data.event_data.res && data.event_data.res.invocation) {
scope[fld] = data['event_data']['res']['invocation'][fld]; scope[fld] = data.event_data.res.invocation[fld];
} }
break; break;
} }
@@ -358,11 +225,11 @@ angular.module('EventsHelper', ['RestServices', 'Utilities', 'JobEventDataDefini
} }
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
$('#form-modal').modal("hide"); $('#form-modal').modal("hide");
ProcessErrors(scope, data, status, form, ProcessErrors(scope, data, status, form, { hdr: 'Error!',
{ hdr: 'Error!', msg: 'Failed to retrieve event: ' + event_id + '. GET status: ' + status }); msg: 'Failed to retrieve event: ' + event_id + '. GET status: ' + status });
}); });
};
} }
}]); ]);

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,8 @@
/* jshint loopfunc: true */ /* jshint loopfunc: true */
'use strict';
angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'HostListDefinition', angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'HostListDefinition',
'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'AuthService', 'HostsHelper', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'AuthService', 'HostsHelper',
'InventoryHelper', 'RelatedSearchHelper', 'InventoryFormDefinition', 'SelectionHelper', 'InventoryHelper', 'RelatedSearchHelper', 'InventoryFormDefinition', 'SelectionHelper',

View File

@@ -4,130 +4,119 @@
* JobSubmission.js * JobSubmission.js
* *
*/ */
'use strict';
angular.module('JobSubmissionHelper', ['RestServices', 'Utilities', 'CredentialFormDefinition', 'CredentialsListDefinition', angular.module('JobSubmissionHelper', ['RestServices', 'Utilities', 'CredentialFormDefinition', 'CredentialsListDefinition',
'LookUpHelper', 'ProjectFormDefinition', 'JobSubmissionHelper' ]) 'LookUpHelper', 'ProjectFormDefinition', 'JobSubmissionHelper'
])
.factory('PromptPasswords', ['CredentialForm', 'JobTemplateForm', '$compile', 'Rest', '$location', 'ProcessErrors', .factory('PromptPasswords', ['CredentialForm', 'JobTemplateForm', '$compile', 'Rest', '$location', 'ProcessErrors',
'GetBasePath', 'Alert', 'Empty', 'Wait', 'GetBasePath', 'Alert', 'Empty', 'Wait',
function (CredentialForm, JobTemplateForm, $compile, Rest, $location, ProcessErrors, GetBasePath, Alert, Empty, Wait) { function (CredentialForm, JobTemplateForm, $compile, Rest, $location, ProcessErrors, GetBasePath, Alert, Empty, Wait) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var passwords = params.passwords; passwords = params.passwords,
var start_url = params.start_url; start_url = params.start_url,
var form = params.form; form = params.form,
var html = ''; html = '',
var field, element, dialogScope, fld; field, element, fld, i, current_form,
var base = $location.path().replace(/^\//,'').split('/')[0]; base = $location.path().replace(/^\//, '').split('/')[0],
var extra_html = params.extra_html; extra_html = params.extra_html;
function navigate(canceled) { function navigate(canceled) {
//Decide where to send the user once the modal dialog closes //Decide where to send the user once the modal dialog closes
if (!canceled) { if (!canceled) {
if (base == 'jobs') { if (base === 'jobs') {
scope.refreshJob(); scope.refreshJob();
} } else {
else {
$location.path('/jobs'); $location.path('/jobs');
} }
} } else {
else {
$location.path('/' + base); $location.path('/' + base);
} }
} }
function cancel() { function cancel() {
// Delete a job // Delete a job
var url = GetBasePath('jobs') + scope.job_id +'/' var url = GetBasePath('jobs') + scope.job_id + '/';
Rest.setUrl(url); Rest.setUrl(url);
Rest.destroy() Rest.destroy()
.success ( function(data, status, headers, config) { .success(function () {
if (form.name == 'credential') { if (form.name === 'credential') {
navigate(true); navigate(true);
} }
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, { hdr: 'Error!',
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
}); });
} }
scope.cancelJob = function () { scope.cancelJob = function () {
// User clicked cancel button // User clicked cancel button
$('#password-modal').modal('hide'); $('#password-modal').modal('hide');
if (form.name == 'credential') { if (form.name === 'credential') {
cancel(); cancel();
} } else {
else {
scope.$emit('UpdateSubmitted', 'canceled'); scope.$emit('UpdateSubmitted', 'canceled');
} }
} };
scope.startJob = function () { scope.startJob = function () {
var pswd = {}, value_supplied = false;
$('#password-modal').modal('hide'); $('#password-modal').modal('hide');
Wait('start'); Wait('start');
var pswd = {}; $('.password-field').each(function () {
var value_supplied = false;
$('.password-field').each(function(index) {
pswd[$(this).attr('name')] = $(this).val(); pswd[$(this).attr('name')] = $(this).val();
if ($(this).val() != '' && $(this).val() !== null) { if ($(this).val() !== '' && $(this).val() !== null) {
value_supplied = true; value_supplied = true;
} }
}); });
if (Empty(passwords) || passwords.length == 0 || value_supplied) { if (Empty(passwords) || passwords.length === 0 || value_supplied) {
Rest.setUrl(start_url); Rest.setUrl(start_url);
Rest.post(pswd) Rest.post(pswd)
.success( function(data, status, headers, config) { .success(function () {
scope.$emit('UpdateSubmitted', 'started'); scope.$emit('UpdateSubmitted', 'started');
if (form.name == 'credential') { if (form.name === 'credential') {
navigate(false); navigate(false);
} }
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
Wait('stop'); Wait('stop');
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, { hdr: 'Error!',
{ hdr: 'Error!', msg: 'POST to ' + start_url + ' failed with status: ' + status }); msg: 'POST to ' + start_url + ' failed with status: ' + status });
}); });
} } else {
else {
Wait('stop'); Wait('stop');
Alert('No Passwords', 'Required password(s) not provided. The request was not submitted.', 'alert-info'); Alert('No Passwords', 'Required password(s) not provided. The request was not submitted.', 'alert-info');
if (form.name == 'credential') { if (form.name === 'credential') {
// No passwords provided, so we can't start the job. Rather than leave the job in a 'new' // No passwords provided, so we can't start the job. Rather than leave the job in a 'new'
// state, let's delete it. // state, let's delete it.
cancelJob(); scope.cancelJob();
}
} }
} }
};
if (passwords && passwords.length > 0) { if (passwords && passwords.length > 0) {
Wait('stop'); Wait('stop');
// Prompt for passwords // Prompt for passwords
html += "<form class=\"form-horizontal\" name=\"password_form\" novalidate>\n"; html += "<form class=\"form-horizontal\" name=\"password_form\" novalidate>\n";
html += (extra_html) ? extra_html : ""; html += (extra_html) ? extra_html : "";
var current_form; for (i = 0; i < passwords.length; i++) {
for (var i=0; i < passwords.length; i++) {
// Add the password field // Add the password field
if (form.name == 'credential') { if (form.name === 'credential') {
// this is a job. we could be prompting for inventory and/or SCM passwords // this is a job. we could be prompting for inventory and/or SCM passwords
if (form.fields[passwords[i]]) { if (form.fields[passwords[i]]) {
current_form = form; current_form = form;
} }
/*
else if (ProjectsForm.fields[passwords[i]]) {
current_form = ProjectsForm;
}
else if (GroupForm.fields[passwords[i]]) {
current_form = GroupForm;
}
*/
else { else {
// No match found. Abandon ship! // No match found. Abandon ship!
Alert('Form Not Found', 'Could not locate form for: ' + passwords[i], 'alert-danger'); Alert('Form Not Found', 'Could not locate form for: ' + passwords[i], 'alert-danger');
$location('/#/jobs'); $location('/#/jobs');
} }
} } else {
else {
current_form = form; current_form = form;
} }
field = current_form.fields[passwords[i]]; field = current_form.fields[passwords[i]];
@@ -181,39 +170,40 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
html += "</div>\n"; html += "</div>\n";
} }
html += "</form>\n"; html += "</form>\n";
var element = angular.element(document.getElementById('password-body')); element = angular.element(document.getElementById('password-body'));
element.html(html); element.html(html);
$compile(element.contents())(scope); $compile(element.contents())(scope);
$('#password-modal').modal(); $('#password-modal').modal();
$('#password-modal').on('shown.bs.modal', function () { $('#password-modal').on('shown.bs.modal', function () {
$('#password-body').find('input[type="password"]:first').focus(); $('#password-body').find('input[type="password"]:first').focus();
}); });
} } else {
else {
scope.startJob(); scope.startJob();
} }
};
} }
}]) ])
.factory('SubmitJob', ['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'CredentialList', .factory('SubmitJob', ['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'CredentialList',
'LookUpInit', 'CredentialForm', 'ProcessErrors', 'JobTemplateForm', 'Wait', 'LookUpInit', 'CredentialForm', 'ProcessErrors', 'JobTemplateForm', 'Wait',
function (PromptPasswords, $compile, Rest, $location, GetBasePath, CredentialList, LookUpInit, CredentialForm, function (PromptPasswords, $compile, Rest, $location, GetBasePath, CredentialList, LookUpInit, CredentialForm,
ProcessErrors, JobTemplateForm, Wait) { ProcessErrors, JobTemplateForm, Wait) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var id = params.id; id = params.id,
var template_name = (params.template) ? params.template : null; template_name = (params.template) ? params.template : null,
var base = $location.path().replace(/^\//,'').split('/')[0]; base = $location.path().replace(/^\//, '').split('/')[0],
var url = GetBasePath(base) + id + '/'; url = GetBasePath(base) + id + '/';
function postJob(data) { function postJob(data) {
var dt, url, name;
// Create the job record // Create the job record
if (scope.credentialWatchRemove) { if (scope.credentialWatchRemove) {
scope.credentialWatchRemove(); scope.credentialWatchRemove();
} }
var dt = new Date().toISOString(); dt = new Date().toISOString();
var url = (data.related.jobs) ? data.related.jobs : data.related.job_template + 'jobs/'; url = (data.related.jobs) ? data.related.jobs : data.related.job_template + 'jobs/';
var name = (template_name) ? template_name : data.name; name = (template_name) ? template_name : data.name;
Wait('start'); Wait('start');
Rest.setUrl(url); Rest.setUrl(url);
Rest.post({ Rest.post({
@@ -228,8 +218,7 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
limit: data.limit, limit: data.limit,
verbosity: data.verbosity, verbosity: data.verbosity,
extra_vars: data.extra_vars extra_vars: data.extra_vars
}) }).success(function (data) {
.success( function(data, status, headers, config) {
scope.job_id = data.id; scope.job_id = data.id;
if (data.passwords_needed_to_start.length > 0) { if (data.passwords_needed_to_start.length > 0) {
// Passwords needed. Prompt for passwords, then start job. // Passwords needed. Prompt for passwords, then start job.
@@ -239,42 +228,39 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
start_url: data.related.start, start_url: data.related.start,
form: CredentialForm form: CredentialForm
}); });
} } else {
else {
// No passwords needed, start the job! // No passwords needed, start the job!
Rest.setUrl(data.related.start); Rest.setUrl(data.related.start);
Rest.post() Rest.post()
.success( function(data, status, headers, config) { .success(function () {
Wait('stop'); Wait('stop');
var base = $location.path().replace(/^\//, '').split('/')[0]; var base = $location.path().replace(/^\//, '').split('/')[0];
if (base == 'jobs') { if (base === 'jobs') {
scope.refresh(); scope.refresh();
} } else {
else {
$location.path('/jobs'); $location.path('/jobs');
} }
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, { hdr: 'Error!',
{ hdr: 'Error!', msg: 'Failed to start job. POST returned status: ' + status }); msg: 'Failed to start job. POST returned status: ' + status });
}); });
} }
}) }).error(function (data, status) {
.error( function(data, status, headers, config) {
Wait('stop'); Wait('stop');
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, { hdr: 'Error!',
{ hdr: 'Error!', msg: 'Failed to create job. POST returned status: ' + status }); msg: 'Failed to create job. POST returned status: ' + status });
}); });
}; }
// Get the job or job_template record // Get the job or job_template record
Wait('start'); Wait('start');
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success( function(data, status, headers, config) { .success(function (data) {
// Create a job record // Create a job record
scope.credential = ''; scope.credential = '';
if (data.credential == '' || data.credential == null) { if (data.credential === '' || data.credential === null) {
// Template does not have credential, prompt for one // Template does not have credential, prompt for one
Wait('stop'); Wait('stop');
if (scope.credentialWatchRemove) { if (scope.credentialWatchRemove) {
@@ -284,7 +270,7 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
if (newVal !== oldVal) { if (newVal !== oldVal) {
// After user selects a credential from the modal, // After user selects a credential from the modal,
// submit the job // submit the job
if (scope.credential != '' && scope.credential !== null && scope.credential !== undefined) { if (scope.credential !== '' && scope.credential !== null && scope.credential !== undefined) {
data.credential = scope.credential; data.credential = scope.credential;
postJob(data); postJob(data);
} }
@@ -299,32 +285,32 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
hdr: 'Credential Required' hdr: 'Credential Required'
}); });
scope.lookUpCredential(); scope.lookUpCredential();
} } else {
else {
// We have what we need, submit the job // We have what we need, submit the job
postJob(data); postJob(data);
} }
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, { hdr: 'Error!',
{ hdr: 'Error!', msg: 'Failed to get job template details. GET returned status: ' + status }); msg: 'Failed to get job template details. GET returned status: ' + status });
}); });
}; };
}]) }
])
// Sumbit SCM Update request // Sumbit SCM Update request
.factory('ProjectUpdate', ['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'ProcessErrors', 'Alert', .factory('ProjectUpdate', ['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'ProcessErrors', 'Alert',
'ProjectsForm', 'Wait', 'ProjectsForm', 'Wait',
function (PromptPasswords, $compile, Rest, $location, GetBasePath, ProcessErrors, Alert, ProjectsForm, Wait) { function (PromptPasswords, $compile, Rest, $location, GetBasePath, ProcessErrors, Alert, ProjectsForm, Wait) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var project_id = params.project_id; project_id = params.project_id,
var url = GetBasePath('projects') + project_id + '/update/'; url = GetBasePath('projects') + project_id + '/update/';
if (scope.removeUpdateSubmitted) { if (scope.removeUpdateSubmitted) {
scope.removeUpdateSubmitted(); scope.removeUpdateSubmitted();
} }
scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function(e, action) { scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function () {
// Refresh the project list after update request submitted // Refresh the project list after update request submitted
Wait('stop'); Wait('stop');
Alert('Update Started', 'The request to start the SCM update process was submitted. ' + Alert('Update Started', 'The request to start the SCM update process was submitted. ' +
@@ -350,12 +336,13 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
Wait('start'); Wait('start');
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success( function(data, status, headers, config) { .success(function (data) {
var i, extra_html;
Wait('stop'); Wait('stop');
if (data.can_update) { if (data.can_update) {
var extra_html = ''; extra_html = '';
for (var i=0; i < scope.projects.length; i++) { for (i = 0; i < scope.projects.length; i++) {
if (scope.projects[i].id == project_id) { if (scope.projects[i].id === project_id) {
extra_html += "<div class=\"form-group\">\n"; extra_html += "<div class=\"form-group\">\n";
extra_html += "<label class=\"control-label col-lg-3 normal-weight\" for=\"scm_url\">SCM URL</label>\n"; extra_html += "<label class=\"control-label col-lg-3 normal-weight\" for=\"scm_url\">SCM URL</label>\n";
extra_html += "<div class=\"col-lg-9\">\n"; extra_html += "<div class=\"col-lg-9\">\n";
@@ -383,18 +370,20 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
} }
extra_html += "</p>"; extra_html += "</p>";
scope.$emit('SCMSubmit', data.passwords_needed_to_update, extra_html); scope.$emit('SCMSubmit', data.passwords_needed_to_update, extra_html);
} } else {
else {
Alert('Permission Denied', 'You do not have access to update this project. Please contact your system administrator.', Alert('Permission Denied', 'You do not have access to update this project. Please contact your system administrator.',
'alert-danger'); 'alert-danger');
} }
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, {
{ hdr: 'Error!', msg: 'Failed to get project update details: ' + url + ' GET status: ' + status }); hdr: 'Error!',
msg: 'Failed to get project update details: ' + url + ' GET status: ' + status
});
}); });
}; };
}]) }
])
// Sumbit Inventory Update request // Sumbit Inventory Update request
@@ -403,18 +392,15 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
function (PromptPasswords, $compile, Rest, $location, GetBasePath, ProcessErrors, Alert, GroupForm, BuildTree, Wait) { function (PromptPasswords, $compile, Rest, $location, GetBasePath, ProcessErrors, Alert, GroupForm, BuildTree, Wait) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var inventory_id = params.inventory_id; url = params.url,
var url = params.url; group_id = params.group_id,
var group_name = params.group_name; tree_id = params.tree_id;
var group_source = params.group_source;
var group_id = params.group_id;
var tree_id = params.tree_id;
if (scope.removeHostReloadComplete) { if (scope.removeHostReloadComplete) {
scope.removeHostReloadComplete(); scope.removeHostReloadComplete();
} }
scope.removeHostReloadComplete = scope.$on('HostReloadComplete', function(e) { scope.removeHostReloadComplete = scope.$on('HostReloadComplete', function () {
Wait('stop'); Wait('stop');
Alert('Update Started', 'Your request to start the inventory sync process was submitted. Monitor progress ' + Alert('Update Started', 'Your request to start the inventory sync process was submitted. Monitor progress ' +
'by clicking the <i class="fa fa-refresh fa-lg"></i> button.', 'alert-info'); 'by clicking the <i class="fa fa-refresh fa-lg"></i> button.', 'alert-info');
@@ -427,13 +413,12 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
scope.removeUpdateSubmitted(); scope.removeUpdateSubmitted();
} }
scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function (e, action) { scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function (e, action) {
if (action == 'started') { if (action === 'started') {
if (scope.refreshGroups) { if (scope.refreshGroups) {
scope.selected_tree_id = tree_id; scope.selected_tree_id = tree_id;
scope.selected_group_id = group_id; scope.selected_group_id = group_id;
scope.refreshGroups(); scope.refreshGroups();
} } else if (scope.refresh) {
else if (scope.refresh) {
scope.refresh(); scope.refresh();
} }
scope.$emit('HostReloadComplete'); scope.$emit('HostReloadComplete');
@@ -458,23 +443,22 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
Wait('start'); Wait('start');
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success( function(data, status, headers, config) { .success(function (data) {
if (data.can_update) { if (data.can_update) {
//var extra_html = "<div class=\"inventory-passwd-msg\">Starting inventory update for <em>" + group_name + //var extra_html = "<div class=\"inventory-passwd-msg\">Starting inventory update for <em>" + group_name +
// "</em>. Please provide the " + group_source + " credentials:</div>\n"; // "</em>. Please provide the " + group_source + " credentials:</div>\n";
scope.$emit('InventorySubmit', data.passwords_needed_to_update); scope.$emit('InventorySubmit', data.passwords_needed_to_update);
} } else {
else {
Wait('stop'); Wait('stop');
Alert('Permission Denied', 'You do not have access to run the update. Please contact your system administrator.', Alert('Permission Denied', 'You do not have access to run the update. Please contact your system administrator.',
'alert-danger'); 'alert-danger');
} }
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
Wait('stop'); Wait('stop');
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, { hdr: 'Error!',
{ hdr: 'Error!', msg: 'Failed to get inventory_source details. ' + url + 'GET status: ' + status }); msg: 'Failed to get inventory_source details. ' + url + 'GET status: ' + status });
}); });
}; };
}]); }
]);

View File

@@ -7,9 +7,12 @@
* *
*/ */
'use strict';
angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinition', 'InventoryHelper']) angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinition', 'InventoryHelper'])
.factory('JobStatusToolTip', [ function() { .factory('JobStatusToolTip', [
function () {
return function (status) { return function (status) {
var toolTip; var toolTip;
switch (status) { switch (status) {
@@ -38,7 +41,8 @@ angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinitio
} }
return toolTip; return toolTip;
}; };
}]) }
])
.factory('ShowJobSummary', ['Rest', 'Wait', 'GetBasePath', 'FormatDate', 'ProcessErrors', 'GenerateForm', 'JobSummary', .factory('ShowJobSummary', ['Rest', 'Wait', 'GetBasePath', 'FormatDate', 'ProcessErrors', 'GenerateForm', 'JobSummary',
'WatchInventoryWindowResize', 'WatchInventoryWindowResize',
@@ -46,35 +50,31 @@ angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinitio
return function (params) { return function (params) {
// Display status info in a modal dialog- called from inventory edit page // Display status info in a modal dialog- called from inventory edit page
var job_id = params.job_id; var job_id = params.job_id,
generator = GenerateForm,
form = JobSummary,
scope, ww, wh, x, y, maxrows, url, html;
var generator = GenerateForm; html = '<div id=\"status-modal-dialog\" title=\"Job ' + job_id + '\">' +
var form = JobSummary;
// Using jquery dialog for its expandable property
var html = '<div id=\"status-modal-dialog\" title=\"Job ' + job_id + '\">' +
'<div id=\"form-container\" style=\"width: 100%;\"></div></div>\n'; '<div id=\"form-container\" style=\"width: 100%;\"></div></div>\n';
$('#inventory-modal-container').empty().append(html); $('#inventory-modal-container').empty().append(html);
var scope = generator.inject(form, { mode: 'edit', id: 'form-container', breadCrumbs: false, related: false });
scope = generator.inject(form, { mode: 'edit', id: 'form-container', breadCrumbs: false, related: false });
// Set modal dimensions based on viewport width // Set modal dimensions based on viewport width
var ww = $(document).width(); ww = $(document).width();
var wh = $('body').height(); wh = $('body').height();
var x, y, maxrows;
if (ww > 1199) { if (ww > 1199) {
// desktop // desktop
x = 675; x = 675;
y = (750 > wh) ? wh - 20 : 750; y = (750 > wh) ? wh - 20 : 750;
maxrows = 20; maxrows = 20;
} } else if (ww <= 1199 && ww >= 768) {
else if (ww <= 1199 && ww >= 768) {
x = 550; x = 550;
y = (620 > wh) ? wh - 15 : 620; y = (620 > wh) ? wh - 15 : 620;
maxrows = 15; maxrows = 15;
} } else {
else {
x = (ww - 20); x = (ww - 20);
y = (500 > wh) ? wh : 500; y = (500 > wh) ? wh : 500;
maxrows = 10; maxrows = 10;
@@ -82,7 +82,11 @@ angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinitio
// Create the modal // Create the modal
$('#status-modal-dialog').dialog({ $('#status-modal-dialog').dialog({
buttons: { 'OK': function() { $( this ).dialog( 'close' ); } }, buttons: {
'OK': function () {
$(this).dialog('close');
}
},
modal: true, modal: true,
width: x, width: x,
height: y, height: y,
@@ -90,15 +94,19 @@ angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinitio
create: function () { create: function () {
// fix the close button // fix the close button
$('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-titlebar button') $('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-titlebar button')
.empty().attr({ 'class': 'close' }).text('x'); .empty().attr({
'class': 'close'
}).text('x');
// fix the OK button // fix the OK button
$('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-buttonset button:first') $('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-buttonset button:first')
.attr({ 'class': 'btn btn-primary' }); .attr({
'class': 'btn btn-primary'
});
}, },
resizeStop: function () { resizeStop: function () {
// for some reason, after resizing dialog the form and fields (the content) doesn't expand to 100% // for some reason, after resizing dialog the form and fields (the content) doesn't expand to 100%
var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]'); var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]'),
var content = dialog.find('#status-modal-dialog'); content = dialog.find('#status-modal-dialog');
content.width(dialog.width() - 28); content.width(dialog.width() - 28);
}, },
close: function () { close: function () {
@@ -121,16 +129,17 @@ angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinitio
}); });
function calcRows(content) { function calcRows(content) {
var n = content.match(/\n/g); var n = content.match(/\n/g),
var rows = (n) ? n.length : 1; rows = (n) ? n.length : 1;
return (rows > maxrows) ? 20 : rows; return (rows > maxrows) ? 20 : rows;
} }
Wait('start'); Wait('start');
var url = GetBasePath('jobs') + job_id + '/'; url = GetBasePath('jobs') + job_id + '/';
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success(function (data) { .success(function (data) {
var cDate;
scope.id = data.id; scope.id = data.id;
scope.name = data.name; scope.name = data.name;
scope.status = data.status; scope.status = data.status;
@@ -138,15 +147,15 @@ angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinitio
scope.result_traceback = data.result_traceback; scope.result_traceback = data.result_traceback;
scope.stdout_rows = calcRows(scope.result_stdout); scope.stdout_rows = calcRows(scope.result_stdout);
scope.traceback_rows = calcRows(scope.result_traceback); scope.traceback_rows = calcRows(scope.result_traceback);
var cDate = new Date(data.created); cDate = new Date(data.created);
scope.created = FormatDate(cDate); scope.created = FormatDate(cDate);
$('#status-modal-dialog').dialog('open'); $('#status-modal-dialog').dialog('open');
}) })
.error(function (data, status) { .error(function (data, status) {
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, { hdr: 'Error!',
{ hdr: 'Error!', msg: 'Attempt to load job failed. GET returned status: ' + status }); msg: 'Attempt to load job failed. GET returned status: ' + status });
}); });
}; };
}]); }
]);

View File

@@ -14,39 +14,40 @@
* }) * })
*/ */
'use strict';
angular.module('LookUpHelper', ['RestServices', 'Utilities', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ApiLoader']) angular.module('LookUpHelper', ['RestServices', 'Utilities', 'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'ApiLoader'])
.factory('LookUpInit', ['Alert', 'Rest', 'GenerateList', 'SearchInit', 'PaginateInit', 'GetBasePath', 'FormatDate', 'Empty', .factory('LookUpInit', ['Alert', 'Rest', 'GenerateList', 'SearchInit', 'PaginateInit', 'GetBasePath', 'FormatDate', 'Empty',
function (Alert, Rest, GenerateList, SearchInit, PaginateInit, GetBasePath, FormatDate, Empty) { function (Alert, Rest, GenerateList, SearchInit, PaginateInit, GetBasePath, FormatDate, Empty) {
return function (params) { return function (params) {
var scope = params.scope; // form scope var scope = params.scope,
var form = params.form; // form object form = params.form,
var list = params.list; // list object list = params.list,
var field = params.field; // form field field = params.field,
var postAction = params.postAction //action to perform post user selection postAction = params.postAction,
defaultUrl, name, hdr, watchUrl;
var defaultUrl;
if (params.url) { if (params.url) {
// pass in a url value to override the default // pass in a url value to override the default
defaultUrl = params.url; defaultUrl = params.url;
} } else {
else { defaultUrl = (list.name === 'inventories') ? GetBasePath('inventory') : GetBasePath(list.name);
defaultUrl = (list.name == 'inventories') ? GetBasePath('inventory') : GetBasePath(list.name);
} }
// Show pop-up // Show pop-up
var name = list.iterator.charAt(0).toUpperCase() + list.iterator.substring(1); name = list.iterator.charAt(0).toUpperCase() + list.iterator.substring(1);
var hdr = (params.hdr) ? params.hdr : 'Select ' + name; hdr = (params.hdr) ? params.hdr : 'Select ' + name;
var watchUrl = (/\/$/.test(defaultUrl)) ? defaultUrl + '?' : defaultUrl + '&'; watchUrl = (/\/$/.test(defaultUrl)) ? defaultUrl + '?' : defaultUrl + '&';
watchUrl += form.fields[field].sourceField + '__' + 'iexact=:value'; 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-url', watchUrl);
$('input[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').attr('data-source', field); $('input[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').attr('data-source', field);
scope['lookUp' + name] = function () { scope['lookUp' + name] = function () {
var listGenerator = GenerateList; var listGenerator = GenerateList,
var listScope = listGenerator.inject(list, { mode: 'lookup', hdr: hdr }); listScope = listGenerator.inject(list, { mode: 'lookup', hdr: hdr });
$('#lookup-modal').on('hidden.bs.modal', function () { $('#lookup-modal').on('hidden.bs.modal', function () {
// If user clicks cancel without making a selection, make sure that field values are // If user clicks cancel without making a selection, make sure that field values are
@@ -54,7 +55,7 @@ angular.module('LookUpHelper', [ 'RestServices', 'Utilities', 'SearchHelper', 'P
if (listScope.searchCleanup) { if (listScope.searchCleanup) {
listScope.searchCleanup(); listScope.searchCleanup();
} }
if (scope[field] == '' || scope[field] == null) { if (scope[field] === '' || scope[field] === null) {
scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] = ''; scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] = '';
if (!scope.$$phase) { if (!scope.$$phase) {
scope.$digest(); scope.$digest();
@@ -63,10 +64,9 @@ angular.module('LookUpHelper', [ 'RestServices', 'Utilities', 'SearchHelper', 'P
}); });
listScope.selectAction = function () { listScope.selectAction = function () {
var found = false; var found = false, i;
var name; for (i = 0; i < listScope[list.name].length; i++) {
for (var i=0; i < listScope[list.name].length; i++) { if (listScope[list.name][i].checked === '1') {
if (listScope[list.name][i]['checked'] == '1') {
found = true; found = true;
scope[field] = listScope[list.name][i].id; scope[field] = listScope[list.name][i].id;
if (scope[form.name + '_form'] && form.fields[field] && form.fields[field].sourceModel) { if (scope[form.name + '_form'] && form.fields[field] && form.fields[field].sourceModel) {
@@ -83,41 +83,52 @@ angular.module('LookUpHelper', [ 'RestServices', 'Utilities', 'SearchHelper', 'P
listGenerator.hide(); listGenerator.hide();
} }
} }
if (found == false) { if (found === false) {
Alert('Missing Selection', 'Oops, you failed to make a selection. Click on a row to make your selection, ' + Alert('Missing Selection', 'Oops, you failed to make a selection. Click on a row to make your selection, ' +
'and then click the Select button.'); 'and then click the Select button.');
} } else {
else {
if (postAction) { if (postAction) {
postAction(); postAction();
} }
} }
} };
listScope['toggle_' + list.iterator] = function (id) { listScope['toggle_' + list.iterator] = function (id) {
for (var i=0; i < scope[list.name].length; i++) { var i;
if (listScope[list.name][i]['id'] == id) { for (i = 0; i < scope[list.name].length; i++) {
listScope[list.name][i]['checked'] = '1'; if (listScope[list.name][i].id === id) {
listScope[list.name][i]['success_class'] = 'success'; listScope[list.name][i].checked = '1';
} listScope[list.name][i].success_class = 'success';
else { } else {
listScope[list.name][i]['checked'] = '0'; listScope[list.name][i].checked = '0';
listScope[list.name][i]['success_class'] = ''; listScope[list.name][i].success_class = '';
} }
} }
} };
SearchInit({ scope: listScope, set: list.name, list: list, url: defaultUrl });
PaginateInit({ scope: listScope, list: list, url: defaultUrl, mode: 'lookup' }); SearchInit({
scope: listScope,
set: list.name,
list: list,
url: defaultUrl
});
PaginateInit({
scope: listScope,
list: list,
url: defaultUrl,
mode: 'lookup'
});
// If user made a selection previously, mark it as selected when modal loads // If user made a selection previously, mark it as selected when modal loads
if (listScope.lookupPostRefreshRemove) { if (listScope.lookupPostRefreshRemove) {
listScope.lookupPostRefreshRemove(); listScope.lookupPostRefreshRemove();
} }
listScope.lookupPostRefreshRemove = scope.$on('PostRefresh', function () { listScope.lookupPostRefreshRemove = scope.$on('PostRefresh', function () {
for (var fld in list.fields) { var fld, i;
if (list.fields[fld].type && list.fields[fld].type == 'date') { for (fld in list.fields) {
if (list.fields[fld].type && list.fields[fld].type === 'date') {
//convert dates to our standard format //convert dates to our standard format
for (var i=0; i < scope[list.name].length; i++) { for (i = 0; i < scope[list.name].length; i++) {
scope[list.name][i][fld] = FormatDate(new Date(scope[list.name][i][fld])); scope[list.name][i][fld] = FormatDate(new Date(scope[list.name][i][fld]));
} }
} }
@@ -126,8 +137,8 @@ angular.module('LookUpHelper', [ 'RestServices', 'Utilities', 'SearchHelper', 'P
// Put it back based on the value of sourceModel_sourceName // Put it back based on the value of sourceModel_sourceName
if (scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] !== '' && if (scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] !== '' &&
scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] !== null) { scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] !== null) {
for (var i=0; i < listScope[list.name].length; i++) { for (i = 0; i < listScope[list.name].length; i++) {
if (listScope[list.name][i][form.fields[field].sourceField] == if (listScope[list.name][i][form.fields[field].sourceField] ===
scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField]) { scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField]) {
scope[field] = listScope[list.name][i].id; scope[field] = listScope[list.name][i].id;
//scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] = //scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] =
@@ -146,8 +157,7 @@ angular.module('LookUpHelper', [ 'RestServices', 'Utilities', 'SearchHelper', 'P
listScope.search(list.iterator); listScope.search(list.iterator);
};
};
} }
} ]);
}]);

View File

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

View File

@@ -8,14 +8,17 @@
* *
*/ */
'use strict';
angular.module('ParseHelper', []) angular.module('ParseHelper', [])
.factory('ParseTypeChange', [function() { .factory('ParseTypeChange', [
function () {
return function (scope, varName, parseTypeName) { return function (scope, varName, parseTypeName) {
// Toggle displayed variable string between JSON and YAML // Toggle displayed variable string between JSON and YAML
var fld = (varName) ? varName : 'variables'; var fld = (varName) ? varName : 'variables',
var pfld = (parseTypeName) ? parseTypeName : 'parseType'; pfld = (parseTypeName) ? parseTypeName : 'parseType';
scope.blockParseTypeWatch = false; scope.blockParseTypeWatch = false;
scope.blockVariableDataWatch = false; scope.blockVariableDataWatch = false;
@@ -24,40 +27,37 @@ angular.module('ParseHelper', [])
scope['remove' + fld + 'Watch'](); scope['remove' + fld + 'Watch']();
} }
scope['remove' + fld + 'Watch'] = scope.$watch(pfld, function (newVal, oldVal) { scope['remove' + fld + 'Watch'] = scope.$watch(pfld, function (newVal, oldVal) {
var json_obj;
if (newVal !== oldVal) { if (newVal !== oldVal) {
if (newVal == 'json') { if (newVal === 'json') {
if (scope[fld] && !/^---$/.test(scope[fld])) { if (scope[fld] && !/^---$/.test(scope[fld])) {
// convert YAML to JSON // convert YAML to JSON
try { try {
var json_obj = jsyaml.load(scope[fld]); //parse yaml into an obj json_obj = jsyaml.load(scope[fld]); //parse yaml into an obj
scope[fld] = JSON.stringify(json_obj, null, " "); scope[fld] = JSON.stringify(json_obj, null, " ");
} } catch (err) {
catch (err) {
// ignore parse errors. allow the user to paste values in and sync the // ignore parse errors. allow the user to paste values in and sync the
// radio button later. parse errors will be flagged on save. // radio button later. parse errors will be flagged on save.
} }
} else {
scope[fld] = "{}";
} }
else { } else {
scope[fld] = "\{\}";
}
}
else {
if (scope[fld] && !/^\{\}$/.test(scope[fld])) { if (scope[fld] && !/^\{\}$/.test(scope[fld])) {
// convert JSON to YAML // convert JSON to YAML
try { try {
var json_obj = JSON.parse(scope[fld]); json_obj = JSON.parse(scope[fld]);
scope[fld] = jsyaml.safeDump(json_obj); scope[fld] = jsyaml.safeDump(json_obj);
} } catch (err) {
catch (err) {
// ignore the errors. allow the user to paste values in and sync the // ignore the errors. allow the user to paste values in and sync the
// radio button later. parse errors will be flagged on save. // radio button later. parse errors will be flagged on save.
} }
} } else {
else {
scope[fld] = "---"; scope[fld] = "---";
} }
} }
} }
}); });
};
} }
}]); ]);

View File

@@ -9,12 +9,13 @@
angular.module('PermissionsHelper', []) angular.module('PermissionsHelper', [])
// Handle category change event // Handle category change event
.factory('PermissionCategoryChange', [ function() { .factory('PermissionCategoryChange', [
function () {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var reset = params.reset; reset = params.reset;
if (scope.category == 'Inventory') { if (scope.category === 'Inventory') {
scope.projectrequired = false; scope.projectrequired = false;
scope.permissionTypeHelp = scope.permissionTypeHelp =
"<dl>\n" + "<dl>\n" +
@@ -25,8 +26,7 @@ angular.module('PermissionsHelper', [])
"<dt>Admin</dt>\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" + "<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"; "</dl>\n";
} } else {
else {
scope.projectrequired = true; scope.projectrequired = true;
scope.permissionTypeHelp = scope.permissionTypeHelp =
"<dl>\n" + "<dl>\n" +
@@ -40,9 +40,8 @@ angular.module('PermissionsHelper', [])
} }
if (reset) { if (reset) {
scope.permission_type = (scope.category == 'Inventory') ? 'read' : 'run'; //default to the first option scope.permission_type = (scope.category === 'Inventory') ? 'read' : 'run'; //default to the first option
} }
};
} }
}]); ]);

View File

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

View File

@@ -9,6 +9,8 @@
* *
*/ */
'use strict';
angular.module('ProjectsHelper', ['RestServices', 'Utilities', 'ProjectStatusDefinition', 'ProjectFormDefinition']) angular.module('ProjectsHelper', ['RestServices', 'Utilities', 'ProjectStatusDefinition', 'ProjectFormDefinition'])
.factory('ProjectStatus', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm', .factory('ProjectStatus', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GenerateForm',
@@ -17,76 +19,81 @@ angular.module('ProjectsHelper', ['RestServices', 'Utilities', 'ProjectStatusDef
FormatDate, ProjectStatusForm, Wait) { FormatDate, ProjectStatusForm, Wait) {
return function (params) { return function (params) {
var project_id = params.project_id; var project_id = params.project_id,
var last_update = params.last_update; last_update = params.last_update,
generator = GenerateForm,
var generator = GenerateForm; form = ProjectStatusForm,
var form = ProjectStatusForm; html, scope, ww, wh, x, y, maxrows;
Wait('start'); Wait('start');
// Using jquery dialog for its expandable property // Using jquery dialog for its expandable property
var html = "<div id=\"status-modal-dialog\"><div id=\"form-container\" style=\"width: 100%;\"></div></div>\n"; html = "<div id=\"status-modal-dialog\"><div id=\"form-container\" style=\"width: 100%;\"></div></div>\n";
$('#projects-modal-container').empty().append(html); $('#projects-modal-container').empty().append(html);
var scope = generator.inject(form, { mode: 'edit', id: 'form-container', related: false, breadCrumbs: false }); scope = generator.inject(form, { mode: 'edit', id: 'form-container', related: false, breadCrumbs: false });
generator.reset(); generator.reset();
// Set modal dimensions based on viewport width // Set modal dimensions based on viewport width
var ww = $(document).width(); ww = $(document).width();
var wh = $('body').height(); wh = $('body').height();
var x, y, maxrows;
if (ww > 1199) { if (ww > 1199) {
// desktop // desktop
x = 675; x = 675;
y = (750 > wh) ? wh - 20 : 750; y = (750 > wh) ? wh - 20 : 750;
maxrows = 20; maxrows = 20;
} } else if (ww <= 1199 && ww >= 768) {
else if (ww <= 1199 && ww >= 768) {
x = 550; x = 550;
y = (620 > wh) ? wh - 15 : 620; y = (620 > wh) ? wh - 15 : 620;
maxrows = 15; maxrows = 15;
} } else {
else {
x = (ww - 20); x = (ww - 20);
y = (500 > wh) ? wh : 500; y = (500 > wh) ? wh : 500;
maxrows = 10; maxrows = 10;
} }
// Create the modal // Create the modal
$('#status-modal-dialog').dialog({ $('#status-modal-dialog').dialog({
buttons: { "OK": function() { $( this ).dialog( "close" ); } }, buttons: {
"OK": function () {
$(this).dialog("close");
}
},
modal: true, modal: true,
width: x, width: x,
height: y, height: y,
autoOpen: false, autoOpen: false,
create: function (e, ui) { create: function () {
// fix the close button // fix the close button
$('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-titlebar button').empty().attr({ 'class': 'close' }).text('x'); $('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-titlebar button').empty().attr({
'class': 'close'
}).text('x');
// fix the OK button // fix the OK button
$('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-buttonset button:first') $('.ui-dialog[aria-describedby="status-modal-dialog"]').find('.ui-dialog-buttonset button:first')
.attr({ 'class': 'btn btn-primary' }); .attr({
'class': 'btn btn-primary'
});
}, },
resizeStop: function(e, ui) { resizeStop: function () {
// for some reason, after resizing dialog the form and fields (the content) doesn't expand to 100% // for some reason, after resizing dialog the form and fields (the content) doesn't expand to 100%
var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]'); var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]'),
var content = dialog.find('#status-modal-dialog'); content = dialog.find('#status-modal-dialog');
content.width(dialog.width() - 28); content.width(dialog.width() - 28);
}, },
close: function(e, ui) { close: function () {
// Destroy on close // Destroy on close
// Destroy on close // Destroy on close
$('.tooltip').each( function(index) { $('.tooltip').each(function () {
// Remove any lingering tooltip <div> elements // Remove any lingering tooltip <div> elements
$(this).remove(); $(this).remove();
}); });
$('.popover').each(function(index) { $('.popover').each(function () {
// remove lingering popover <div> elements // remove lingering popover <div> elements
$(this).remove(); $(this).remove();
}); });
$('#status-modal-dialog').dialog('destroy'); $('#status-modal-dialog').dialog('destroy');
$('#projects-modal-container').empty(); $('#projects-modal-container').empty();
}, },
open: function(e, ui) { open: function () {
Wait('stop'); Wait('stop');
} }
}); });
@@ -94,34 +101,35 @@ angular.module('ProjectsHelper', ['RestServices', 'Utilities', 'ProjectStatusDef
// Retrieve detail record and prepopulate the form // Retrieve detail record and prepopulate the form
Rest.setUrl(last_update); Rest.setUrl(last_update);
Rest.get() Rest.get()
.success( function(data, status, headers, config) { .success(function (data) {
var results = data; var results = data, fld;
for (var fld in form.fields) { for (fld in form.fields) {
if (results[fld]) { if (results[fld]) {
if (fld == 'created') { if (fld === 'created') {
scope[fld] = FormatDate(new Date(results[fld])); scope[fld] = FormatDate(new Date(results[fld]));
} } else {
else {
scope[fld] = results[fld]; scope[fld] = results[fld];
} }
} } else {
else {
if (results.summary_fields.project[fld]) { if (results.summary_fields.project[fld]) {
scope[fld] = results.summary_fields.project[fld] scope[fld] = results.summary_fields.project[fld];
} }
} }
} }
$('#status-modal-dialog') $('#status-modal-dialog')
.dialog({ title: results.summary_fields.project.name + ' Status'}) .dialog({
title: results.summary_fields.project.name + ' Status'
})
.dialog('open'); .dialog('open');
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
$('#form-modal').modal("hide"); $('#form-modal').modal("hide");
ProcessErrors(scope, data, status, form, ProcessErrors(scope, data, status, form, {
{ hdr: 'Error!', msg: 'Failed to retrieve status of project: ' + project_id + '. GET status: ' + status }); hdr: 'Error!',
msg: 'Failed to retrieve status of project: ' + project_id + '. GET status: ' + status
}); });
});
};
} }
}]); ]);

View File

@@ -10,22 +10,24 @@
* }) * })
*/ */
'use strict';
angular.module('SelectionHelper', ['Utilities', 'RestServices']) angular.module('SelectionHelper', ['Utilities', 'RestServices'])
.factory('SelectionInit', ['Rest', 'Alert', 'ProcessErrors', 'ReturnToCaller', 'Wait', .factory('SelectionInit', ['Rest', 'Alert', 'ProcessErrors', 'ReturnToCaller', 'Wait',
function (Rest, Alert, ProcessErrors, ReturnToCaller, Wait) { function (Rest, Alert, ProcessErrors, ReturnToCaller, Wait) {
return function (params) { return function (params) {
var scope = params.scope; // current scope var scope = params.scope,
var list = params.list; // list object list = params.list,
var target_url = params.url; // URL to POST selected objects target_url = params.url,
var returnToCaller = params.returnToCaller; returnToCaller = params.returnToCaller,
selected;
if (params.selected !== undefined) { if (params.selected !== undefined) {
var selected = params.selected; selected = params.selected;
} } else {
else { selected = []; //array of selected row IDs
var selected = []; //array of selected row IDs
} }
scope.formModalActionDisabled = true; scope.formModalActionDisabled = true;
@@ -33,17 +35,18 @@ angular.module('SelectionHelper', ['Utilities', 'RestServices'])
// toggle row selection // toggle row selection
scope['toggle_' + list.iterator] = function (id, ischeckbox) { scope['toggle_' + list.iterator] = function (id, ischeckbox) {
for (var i=0; i < scope[list.name].length; i++) { var i, j, found;
if (scope[list.name][i]['id'] == id) { for (i = 0; i < scope[list.name].length; i++) {
if ( (scope[list.name][i]['checked'] == '0' && !ischeckbox) || (scope[list.name][i]['checked'] == 1 && ischeckbox) ) { if (scope[list.name][i].id === id) {
if ((scope[list.name][i].checked === '0' && !ischeckbox) || (scope[list.name][i].checked === 1 && ischeckbox)) {
// select the row // select the row
scope[list.name][i]['checked'] = '1'; scope[list.name][i].checked = '1';
scope[list.name][i]['success_class'] = 'success'; scope[list.name][i].success_class = 'success';
// add selected object to the array // add selected object to the array
var found = false; found = false;
for (var j=0; j < selected.length; j++) { for (j = 0; j < selected.length; j++) {
if (selected[j].id == id) { if (selected[j].id === id) {
found = true; found = true;
break; break;
} }
@@ -51,15 +54,14 @@ angular.module('SelectionHelper', ['Utilities', 'RestServices'])
if (!found) { if (!found) {
selected.push(scope[list.name][i]); selected.push(scope[list.name][i]);
} }
} } else {
else {
// unselect the row // unselect the row
scope[list.name][i]['checked'] = '0'; scope[list.name][i].checked = '0';
scope[list.name][i]['success_class'] = ''; scope[list.name][i].success_class = '';
// remove selected object from the array // remove selected object from the array
for (var j=0; j < selected.length; j++) { for (j = 0; j < selected.length; j++) {
if (selected[j].id == id) { if (selected[j].id === id) {
selected.splice(j, 1); selected.splice(j, 1);
break; break;
} }
@@ -70,17 +72,18 @@ angular.module('SelectionHelper', ['Utilities', 'RestServices'])
if (selected.length > 0) { if (selected.length > 0) {
scope.formModalActionDisabled = false; scope.formModalActionDisabled = false;
scope.disableSelectBtn = false; scope.disableSelectBtn = false;
} } else {
else {
scope.formModalActionDisabled = true; scope.formModalActionDisabled = true;
scope.disableSelectBtn = true; scope.disableSelectBtn = true;
} }
} };
// Add the selections // Add the selections
scope.finishSelection = function () { scope.finishSelection = function () {
Rest.setUrl(target_url); Rest.setUrl(target_url);
var queue = [];
var queue = [], j;
scope.formModalActionDisabled = true; scope.formModalActionDisabled = true;
scope.disableSelectBtn = true; scope.disableSelectBtn = true;
@@ -90,53 +93,54 @@ angular.module('SelectionHelper', ['Utilities', 'RestServices'])
selected = []; selected = [];
if (returnToCaller !== undefined) { if (returnToCaller !== undefined) {
ReturnToCaller(returnToCaller); ReturnToCaller(returnToCaller);
} } else {
else {
$('#form-modal').modal('hide'); $('#form-modal').modal('hide');
scope.$emit('modalClosed'); 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) { if (scope.callFinishedRemove) {
scope.callFinishedRemove(); scope.callFinishedRemove();
} }
scope.callFinishedRemove = scope.$on('callFinished', function () { scope.callFinishedRemove = scope.$on('callFinished', function () {
// We call the API for each selected item. We need to hang out until all the api // We call the API for each selected item. We need to hang out until all the api
// calls are finished. // calls are finished.
if (queue.length == selected.length) { var i, errors=0;
if (queue.length === selected.length) {
Wait('stop'); Wait('stop');
var errors = 0; for (i = 0; i < queue.length; i++) {
for (var i=0; i < queue.length; i++) { if (queue[i].result === 'error') {
if (queue[i].result == 'error') { ProcessErrors(scope, queue[i].data, queue[i].status, null, { hdr: 'POST Failure',
ProcessErrors(scope, queue[i].data, queue[i].status, null, msg: 'Failed to add ' + list.iterator + '. POST returned status: ' + queue[i].status });
{ hdr: 'POST Failure', msg: 'Failed to add ' + list.iterator +
'. POST returned status: ' + queue[i].status });
errors++; errors++;
} }
} }
if (errors == 0) { if (errors === 0) {
finished(); finished();
} }
} }
}); });
if (selected.length > 0) { if (selected.length > 0) {
for (var j=0; j < selected.length; j++) { for (j = 0; j < selected.length; j++) {
Rest.post(selected[j]) postIt(selected[j]);
.success( function(data, status, headers, config) {
queue.push({ result: 'success', data: data, status: status });
scope.$emit('callFinished');
})
.error( function(data, status, headers, config) {
queue.push({ result: 'error', data: data, status: status, headers: headers });
scope.$emit('callFinished');
});
} }
} } else {
else {
finished(); finished();
} }
} };
scope.formModalAction = scope.finishSelection; scope.formModalAction = scope.finishSelection;
@@ -145,25 +149,26 @@ angular.module('SelectionHelper', ['Utilities', 'RestServices'])
scope.SelectPostRefreshRemove(); scope.SelectPostRefreshRemove();
} }
scope.SelectPostRefreshRemove = scope.$on('PostRefresh', function () { scope.SelectPostRefreshRemove = scope.$on('PostRefresh', function () {
var i, j, found;
if (scope[list.name]) { if (scope[list.name]) {
for (var i=0; i < scope[list.name].length; i++) { for (i = 0; i < scope[list.name].length; i++) {
var found = false; found = false;
for (var j=0; j < selected.length; j++) { for (j = 0; j < selected.length; j++) {
if (selected[j].id == scope[list.name][i].id) { if (selected[j].id === scope[list.name][i].id) {
found = true; found = true;
break; break;
} }
} }
if (found) { if (found) {
scope[list.name][i]['checked'] = '1'; scope[list.name][i].checked = '1';
scope[list.name][i]['success_class'] = 'success'; scope[list.name][i].success_class = 'success';
} } else {
else { scope[list.name][i].checked = '0';
scope[list.name][i]['checked'] = '0'; scope[list.name][i].success_class = '';
scope[list.name][i]['success_class'] = '';
} }
} }
} }
}); });
};
} }
}]); ]);

View File

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

@@ -6,21 +6,22 @@
* *
*/ */
'use strict';
angular.module('APIDefaults', ['RestServices', 'Utilities']) angular.module('APIDefaults', ['RestServices', 'Utilities'])
.factory('GetAPIDefaults', ['Alert', 'Rest', '$rootScope', function(Alert, Rest, $rootScope) { .factory('GetAPIDefaults', ['Alert', 'Rest', '$rootScope',
function (Alert, Rest, $rootScope) {
return function (key) { return function (key) {
//Reload a related collection on pagination or search change //Reload a related collection on pagination or search change
var answer; var result = {}, cnt = 0, url;
var result = {};
var cnt=0;
function lookup(key) { function lookup(key) {
var result = {}; var id, result = {};
for (id in $rootScope.apiDefaults) { for (id in $rootScope.apiDefaults) {
if (id == key || id.iterator == key) { if (id === key || id.iterator === key) {
result[id] = defaults[id]; result[id] = $rootScope.apiDefaults[id];
break; break;
} }
} }
@@ -28,29 +29,24 @@ angular.module('APIDefaults', ['RestServices', 'Utilities'])
} }
function wait() { function wait() {
var answer; if ($.isEmptyObject(result) && cnt < 5) {
if ( result == {} && cnt < 5) {
cnt++; cnt++;
setTimeout(1000, wait()); setTimeout(1000, wait());
} } else if (result.status === 'success') {
else {
if (result.status == 'success') {
return lookup(key); return lookup(key);
} }
} }
}
if ($rootScope.apiDefaults == null || $rootScope.apiDefaults == undefined) { if ($rootScope.apiDefaults === null || $rootScope.apiDefaults === undefined) {
var result = {}; url = '/api/v1/';
var url = '/api/v1';
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success( function(data, status, headers, config) { .success(function (data) {
defaults = data; var id, defaults = data;
for (var id in defaults) { for (id in defaults) {
switch (id) { switch (id) {
case 'organizations': case 'organizations':
dafaults[id].iterator = 'organization'; defaults[id].iterator = 'organization';
break; break;
case 'jobs': case 'jobs':
defaults[id].iterator = 'job'; defaults[id].iterator = 'job';
@@ -70,20 +66,26 @@ angular.module('APIDefaults', ['RestServices', 'Utilities'])
case 'projects': case 'projects':
defaults[id].iterator = 'project'; defaults[id].iterator = 'project';
break; break;
case 'inventories':
defaults[id].iterator = 'inventory';
break;
} }
} }
$rootScope.apiDefaults = defaults; $rootScope.apiDefaults = defaults;
result = {status: 'success'}; result = {
status: 'success'
};
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
result = {status: 'error', msg: 'Call to ' + url + ' failed. GET returned status: ' + status}; result = {
status: 'error',
msg: 'Call to ' + url + ' failed. GET returned status: ' + status
};
}); });
return wait(); return wait();
} } else {
else {
return lookup(key); return lookup(key);
} }
};
} }
]);
}]);

View File

@@ -8,11 +8,16 @@
* *
*/ */
/* globals console:false */
'use strict';
angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationListDefinition', 'ListGenerator', 'AuthService', angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationListDefinition', 'ListGenerator', 'AuthService',
'InventoryHelper', 'InventoryFormDefinition', 'ParseHelper', 'SearchHelper' 'InventoryHelper', 'InventoryFormDefinition', 'ParseHelper', 'SearchHelper'
]) ])
.factory('WatchInventoryWindowResize', ['ApplyEllipsis', function(ApplyEllipsis) { .factory('WatchInventoryWindowResize', ['ApplyEllipsis',
function (ApplyEllipsis) {
return function () { return function () {
// Call to set or restore window resize // Call to set or restore window resize
var timeOut; var timeOut;
@@ -21,19 +26,20 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
timeOut = setTimeout(function () { timeOut = setTimeout(function () {
// Hack to stop group-name div slipping to a new line // Hack to stop group-name div slipping to a new line
$('#groups_table .name-column').each(function () { $('#groups_table .name-column').each(function () {
var td_width = $(this).width(); var td_width = $(this).width(),
var level_width = $(this).find('.level').width(); level_width = $(this).find('.level').width(),
var level_padding = parseInt($(this).find('.level').css('padding-left').replace(/px/,'')); level_padding = parseInt($(this).find('.level').css('padding-left').replace(/px/, '')),
var level = level_width + level_padding; level = level_width + level_padding,
var pct = ( 100 - Math.ceil((level / td_width)*100) ) + '%'; pct = (100 - Math.ceil((level / td_width) * 100)) + '%';
$(this).find('.group-name').css({ width: pct }); $(this).find('.group-name').css({ width: pct });
}); });
ApplyEllipsis('#groups_table .group-name a'); ApplyEllipsis('#groups_table .group-name a');
ApplyEllipsis('#hosts_table .host-name a'); ApplyEllipsis('#hosts_table .host-name a');
}, 100); }, 100);
}); });
};
} }
}]) ])
.factory('SaveInventory', ['InventoryForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList', .factory('SaveInventory', ['InventoryForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList',
'GetBasePath', 'ParseTypeChange', 'Wait', 'GetBasePath', 'ParseTypeChange', 'Wait',
@@ -42,20 +48,19 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
// Save inventory property modifications // Save inventory property modifications
var scope = params.scope; var scope = params.scope,
form = InventoryForm,
var form = InventoryForm; defaultUrl = GetBasePath('inventory'),
var defaultUrl=GetBasePath('inventory'); fld, json_data, data;
Wait('start'); Wait('start');
try { try {
// Make sure we have valid variable data // Make sure we have valid variable data
if (scope.inventoryParseType == 'json') { if (scope.inventoryParseType === 'json') {
var json_data = JSON.parse(scope.inventory_variables); //make sure JSON parses json_data = JSON.parse(scope.inventory_variables); //make sure JSON parses
} } else {
else { json_data = jsyaml.load(scope.inventory_variables); //parse yaml
var json_data = jsyaml.load(scope.inventory_variables); //parse yaml
} }
// Make sure our JSON is actually an object // Make sure our JSON is actually an object
@@ -63,48 +68,47 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
throw "failed to return an object!"; throw "failed to return an object!";
} }
var data = {} data = {};
for (var fld in form.fields) { for (fld in form.fields) {
if (fld != 'inventory_variables') { if (fld !== 'inventory_variables') {
if (form.fields[fld].realName) { if (form.fields[fld].realName) {
data[form.fields[fld].realName] = scope[fld]; data[form.fields[fld].realName] = scope[fld];
} } else {
else {
data[fld] = scope[fld]; data[fld] = scope[fld];
} }
} }
} }
Rest.setUrl(defaultUrl + scope['inventory_id'] + '/'); Rest.setUrl(defaultUrl + scope.inventory_id + '/');
Rest.put(data) Rest.put(data)
.success( function(data, status, headers, config) { .success(function (data) {
if (scope.inventory_variables) { if (scope.inventory_variables) {
Rest.setUrl(data.related.variable_data); Rest.setUrl(data.related.variable_data);
Rest.put(json_data) Rest.put(json_data)
.success( function(data, status, headers, config) { .success(function () {
Wait('stop'); Wait('stop');
scope.$emit('InventorySaved'); scope.$emit('InventorySaved');
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
ProcessErrors(scope, data, status, form, ProcessErrors(scope, data, status, form, { hdr: 'Error!',
{ hdr: 'Error!', msg: 'Failed to update inventory varaibles. PUT returned status: ' + status }); msg: 'Failed to update inventory varaibles. PUT returned status: ' + status
}); });
} });
else { } else {
scope.$emit('InventorySaved'); scope.$emit('InventorySaved');
} }
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
ProcessErrors(scope, data, status, form, ProcessErrors(scope, data, status, form, { hdr: 'Error!',
{ hdr: 'Error!', msg: 'Failed to update inventory. POST returned status: ' + status }); msg: 'Failed to update inventory. POST returned status: ' + status });
}); });
} } catch (err) {
catch(err) {
Wait('stop'); Wait('stop');
Alert("Error", "Error parsing inventory variables. Parser returned: " + err); Alert("Error", "Error parsing inventory variables. Parser returned: " + err);
} }
};
} }
}]) ])
.factory('EditInventoryProperties', ['InventoryForm', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList', .factory('EditInventoryProperties', ['InventoryForm', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList',
@@ -113,20 +117,16 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
Wait, Store, SearchInit) { Wait, Store, SearchInit) {
return function (params) { return function (params) {
var parent_scope = params.scope var parent_scope = params.scope,
var inventory_id = params.inventory_id; inventory_id = params.inventory_id,
generator = GenerateForm,
var generator = GenerateForm; form = InventoryForm,
var form = InventoryForm; master = {},
var defaultUrl=GetBasePath('inventory'); PreviousSearchParams = Store('CurrentSearchParams'),
var master = {}; scope;
// Hang onto current search params
var PreviousSearchParams = Store('CurrentSearchParams');
form.well = false; form.well = false;
scope = generator.inject(form, { mode: 'edit', modal: true, related: false, modal_show: false });
var scope = generator.inject(form, {mode: 'edit', modal: true, related: false, modal_show: false });
/* Reset form properties. Otherwise it screws up future requests of the Inventories detail page */ /* Reset form properties. Otherwise it screws up future requests of the Inventories detail page */
form.well = true; form.well = true;
@@ -141,20 +141,19 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
Wait('start'); Wait('start');
Rest.setUrl(GetBasePath('inventory') + inventory_id + '/'); Rest.setUrl(GetBasePath('inventory') + inventory_id + '/');
Rest.get() Rest.get()
.success( function(data, status, headers, config) { .success(function (data) {
for (var fld in form.fields) { var fld, json_obj;
if (fld == 'inventory_variables') { for (fld in form.fields) {
if (fld === 'inventory_variables') {
// Parse variables, converting to YAML. // Parse variables, converting to YAML.
if ($.isEmptyObject(data.variables) || data.variables == "\{\}" || if ($.isEmptyObject(data.variables) || data.variables === "{}" ||
data.variables == "null" || data.variables == "") { data.variables === "null" || data.variables === "") {
scope.inventory_variables = "---"; scope.inventory_variables = "---";
} } else {
else {
try { try {
var json_obj = JSON.parse(data.variables); json_obj = JSON.parse(data.variables);
scope.inventory_variables = jsyaml.safeDump(json_obj); scope.inventory_variables = jsyaml.safeDump(json_obj);
} } catch (err) {
catch(err) {
Alert('Variable Parse Error', 'Attempted to parse variables for inventory: ' + inventory_id + Alert('Variable Parse Error', 'Attempted to parse variables for inventory: ' + inventory_id +
'. Parse returned: ' + err); '. Parse returned: ' + err);
if (console) { if (console) {
@@ -166,16 +165,13 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
} }
} }
master.inventory_variables = scope.variables; master.inventory_variables = scope.variables;
} } else if (fld === 'inventory_name') {
else if (fld == 'inventory_name') {
scope[fld] = data.name; scope[fld] = data.name;
master[fld] = scope[fld]; master[fld] = scope[fld];
} } else if (fld === 'inventory_description') {
else if (fld == 'inventory_description') {
scope[fld] = data.description; scope[fld] = data.description;
master[fld] = scope[fld]; master[fld] = scope[fld];
} } else if (data[fld]) {
else if (data[fld]) {
scope[fld] = data[fld]; scope[fld] = data[fld];
master[fld] = scope[fld]; master[fld] = scope[fld];
} }
@@ -201,9 +197,11 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
$('#form-modal').modal('show'); $('#form-modal').modal('show');
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, {
{ hdr: 'Error!', msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status }); hdr: 'Error!',
msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status
});
}); });
if (scope.removeInventorySaved) { if (scope.removeInventorySaved) {
@@ -241,14 +239,16 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
sort_order: PreviousSearchParams.sort_order, sort_order: PreviousSearchParams.sort_order,
setWidgets: false setWidgets: false
}); });
} };
scope.formModalAction = function () { scope.formModalAction = function () {
parent_scope.inventory_id = inventory_id; parent_scope.inventory_id = inventory_id;
parent_scope.inventory_name = scope.inventory_name; parent_scope.inventory_name = scope.inventory_name;
SaveInventory({ scope: scope }); SaveInventory({
} scope: scope
});
};
};
} }
}]); ]);

View File

@@ -8,15 +8,16 @@
* *
*/ */
'use strict';
angular.module('md5Helper', ['RestServices', 'Utilities']) angular.module('md5Helper', ['RestServices', 'Utilities'])
.factory('md5Setup', ['Alert', 'Rest', 'GetBasePath','ProcessErrors', .factory('md5Setup', [ function () {
function(Alert, Rest, GetBasePath, ProcessErrors) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var master = params.master; master = params.master,
var check_field = params.check_field; check_field = params.check_field,
var default_val = params.default_val; //default(true/false) for the checkbox default_val = params.default_val;
scope[check_field] = default_val; scope[check_field] = default_val;
master[check_field] = default_val; master[check_field] = default_val;
@@ -24,17 +25,16 @@ angular.module('md5Helper', ['RestServices', 'Utilities'])
scope.genMD5 = function (fld) { scope.genMD5 = function (fld) {
var now = new Date(); var now = new Date();
scope[fld] = $.md5('AnsibleWorks' + now.getTime()); scope[fld] = $.md5('AnsibleWorks' + now.getTime());
} };
scope.toggleCallback = function (fld) { scope.toggleCallback = function (fld) {
if (scope.allow_callbacks == 'false') { if (scope.allow_callbacks === 'false') {
scope[fld] = ''; scope[fld] = '';
} }
} };
scope.selectAll = function (fld) { scope.selectAll = function (fld) {
$('input[name="' + fld + '"]').focus().select(); $('input[name="' + fld + '"]').focus().select();
} };
};
}
}]); }]);

View File

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

View File

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

View File

@@ -15,24 +15,26 @@
* *
*/ */
'use strict';
angular.module('RelatedSearchHelper', ['RestServices', 'Utilities', 'RefreshRelatedHelper']) angular.module('RelatedSearchHelper', ['RestServices', 'Utilities', 'RefreshRelatedHelper'])
.factory('RelatedSearchInit', ['$timeout', 'Alert', 'Rest', 'RefreshRelated', 'Wait', .factory('RelatedSearchInit', ['$timeout', 'Alert', 'Rest', 'RefreshRelated', 'Wait',
function ($timeout, Alert, Rest, RefreshRelated, Wait) { function ($timeout, Alert, Rest, RefreshRelated, Wait) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var relatedSets = params.relatedSets; relatedSets = params.relatedSets,
var form = params.form; form = params.form, f;
// Set default values // Set default values
function setDefaults(inIterator) { function setDefaults(inIterator) {
var iterator, f; var iterator, f, fld, set;
for (var set in form.related) { for (set in form.related) {
if (form.related[set].type != 'tree' && (inIterator === undefined || inIterator == form.related[set].iterator)) { if (form.related[set].type !== 'tree' && (inIterator === undefined || inIterator === form.related[set].iterator)) {
iterator = form.related[set].iterator; iterator = form.related[set].iterator;
for (var fld in form.related[set].fields) { for (fld in form.related[set].fields) {
if (form.related[set].fields[fld].key) { if (form.related[set].fields[fld].key) {
scope[iterator + 'SearchField'] = fld scope[iterator + 'SearchField'] = fld;
scope[iterator + 'SearchFieldLabel'] = form.related[set].fields[fld].label; scope[iterator + 'SearchFieldLabel'] = form.related[set].fields[fld].label;
break; break;
} }
@@ -46,13 +48,13 @@ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelat
scope[iterator + 'ShowStartBtn'] = true; scope[iterator + 'ShowStartBtn'] = true;
scope[iterator + 'HideAllStartBtn'] = false; scope[iterator + 'HideAllStartBtn'] = false;
f = scope[iterator + 'SearchField'] f = scope[iterator + 'SearchField'];
if (form.related[set].fields[f].searchType && ( form.related[set].fields[f].searchType == 'boolean' if (form.related[set].fields[f].searchType &&
|| form.related[set].fields[f].searchType == 'select')) { (form.related[set].fields[f].searchType === 'boolean' || form.related[set].fields[f].searchType === 'select')) {
scope[iterator + 'SelectShow'] = true; scope[iterator + 'SelectShow'] = true;
scope[iterator + 'SearchSelectOpts'] = list.fields[f].searchOptions; scope[iterator + 'SearchSelectOpts'] = form.fields[f].searchOptions;
} }
if (form.related[set].fields[f].searchType && form.related[set].fields[f].searchType == 'gtzero') { if (form.related[set].fields[f].searchType && form.related[set].fields[f].searchType === 'gtzero') {
scope[iterator + "InputHide"] = true; scope[iterator + "InputHide"] = true;
} }
} }
@@ -64,14 +66,16 @@ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelat
scope.resetSearch = function (iterator) { scope.resetSearch = function (iterator) {
setDefaults(iterator); setDefaults(iterator);
scope.search(iterator); scope.search(iterator);
} };
// Functions to handle search widget changes // Functions to handle search widget changes
scope.setSearchField = function (iterator, fld, label) { scope.setSearchField = function (iterator, fld, label) {
for (var related in form.related) { var f, related;
if ( form.related[related].iterator == iterator ) {
var f = form.related[related].fields[fld]; for (related in form.related) {
if (form.related[related].iterator === iterator) {
f = form.related[related].fields[fld];
} }
} }
@@ -83,36 +87,35 @@ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelat
scope[iterator + 'InputHide'] = false; scope[iterator + 'InputHide'] = false;
scope[iterator + 'ShowStartBtn'] = true; scope[iterator + 'ShowStartBtn'] = true;
if (f.searchType !== undefined && f.searchType == 'gtzero') { if (f.searchType !== undefined && f.searchType === 'gtzero') {
scope[iterator + "InputHide"] = true; scope[iterator + "InputHide"] = true;
scope[iterator + 'ShowStartBtn'] = false; scope[iterator + 'ShowStartBtn'] = false;
} }
if (f.searchType !== undefined && (f.searchType == 'boolean' if (f.searchType !== undefined && (f.searchType === 'boolean' || f.searchType === 'select')) {
|| f.searchType == 'select')) {
scope[iterator + 'SelectShow'] = true; scope[iterator + 'SelectShow'] = true;
scope[iterator + 'SearchSelectOpts'] = f.searchOptions; scope[iterator + 'SearchSelectOpts'] = f.searchOptions;
} }
if (f.searchType !== undefined && f.searchType == 'int') { if (f.searchType !== undefined && f.searchType === 'int') {
//scope[iterator + 'HideSearchType'] = true; //scope[iterator + 'HideSearchType'] = true;
scope[model + 'SearchType'] = 'int'; scope[iterator + 'SearchType'] = 'int';
} }
scope.search(iterator); scope.search(iterator);
} };
scope.setSearchType = function (model, type, label) { scope.setSearchType = function (model, type, label) {
scope[model + 'SearchTypeLabel'] = label; scope[model + 'SearchTypeLabel'] = label;
scope[model + 'SearchType'] = type; scope[model + 'SearchType'] = type;
scope.search(model); scope.search(model);
} };
scope.startSearch = function (e, iterator) { scope.startSearch = function (e, iterator) {
// If use clicks enter while on input field, start the search // If use clicks enter while on input field, start the search
if (e.keyCode == 13) { if (e.keyCode === 13) {
scope.search(iterator); scope.search(iterator);
} }
} };
scope.search = function (iterator) { scope.search = function (iterator) {
//scope[iterator + 'SearchSpin'] = true; //scope[iterator + 'SearchSpin'] = true;
@@ -125,28 +128,26 @@ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelat
scope[iterator + 'ShowStartBtn'] = false; scope[iterator + 'ShowStartBtn'] = false;
} }
if (iterator == 'host') { if (iterator === 'host') {
if (scope['hostSearchField'] == 'has_active_failures') { if (scope.hostSearchField === 'has_active_failures') {
if (scope['hostSearchSelectValue'] && scope['hostSearchSelectValue'].value == 1) { if (scope.hostSearchSelectValue && scope.hostSearchSelectValue.value === 1) {
scope['hostFailureFilter'] = true; scope.hostFailureFilter = true;
} } else {
else { scope.hostFailureFilter = false;
scope['hostFailureFilter'] = false;
} }
} }
} }
var set, url, iterator, sort_order; var fld, key, set, url, sort_order;
for (var key in relatedSets) { for (key in relatedSets) {
if (relatedSets[key].iterator == iterator) { if (relatedSets[key].iterator === iterator) {
set = key; set = key;
url = relatedSets[key].url; url = relatedSets[key].url;
for (var fld in form.related[key].fields) { for (fld in form.related[key].fields) {
if (form.related[key].fields[fld].key) { if (form.related[key].fields[fld].key) {
if (form.related[key].fields[fld].desc) { if (form.related[key].fields[fld].desc) {
sort_order = '-' + fld; sort_order = '-' + fld;
} } else {
else {
sort_order = fld; sort_order = fld;
} }
} }
@@ -155,58 +156,53 @@ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelat
} }
} }
sort_order = (scope[iterator + 'SortOrder'] == null) ? sort_order : scope[iterator + 'SortOrder']; sort_order = (scope[iterator + 'SortOrder'] === null) ? sort_order : scope[iterator + 'SortOrder'];
var f = form.related[set].fields[scope[iterator + 'SearchField']]; f = form.related[set].fields[scope[iterator + 'SearchField']];
if ( (scope[iterator + 'SelectShow'] == false && scope[iterator + 'SearchValue'] != '' && scope[iterator + 'SearchValue'] != undefined) || if ((scope[iterator + 'SelectShow'] === false && scope[iterator + 'SearchValue'] !== '' &&
(scope[iterator + 'SelectShow'] && scope[iterator + 'SearchSelectValue']) || (f.searchType && f.searchType == 'gtzero') ) { scope[iterator + 'SearchValue'] !== undefined) || (scope[iterator + 'SelectShow'] && scope[iterator + 'SearchSelectValue']) ||
(f.searchType && f.searchType === 'gtzero')) {
if (f.sourceModel) { if (f.sourceModel) {
// handle fields whose source is a related model e.g. inventories.organization // handle fields whose source is a related model e.g. inventories.organization
scope[iterator + 'SearchParams'] = f.sourceModel + '__' + f.sourceField + '__'; scope[iterator + 'SearchParams'] = f.sourceModel + '__' + f.sourceField + '__';
} } else if (f.searchField) {
else if (f.searchField) {
scope[iterator + 'SearchParams'] = f.searchField + '__'; scope[iterator + 'SearchParams'] = f.searchField + '__';
} } else {
else {
scope[iterator + 'SearchParams'] = scope[iterator + 'SearchField'] + '__'; scope[iterator + 'SearchParams'] = scope[iterator + 'SearchField'] + '__';
} }
if ( f.searchType && (f.searchType == 'int' || f.searchType == 'boolean' ) ) { if (f.searchType && (f.searchType === 'int' || f.searchType === 'boolean')) {
scope[iterator + 'SearchParams'] += 'int='; scope[iterator + 'SearchParams'] += 'int=';
} } else if (f.searchType && f.searchType === 'gtzero') {
else if ( f.searchType && f.searchType == 'gtzero' ) {
scope[iterator + 'SearchParams'] += 'gt=0'; scope[iterator + 'SearchParams'] += 'gt=0';
} } else {
else {
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchType'] + '='; scope[iterator + 'SearchParams'] += scope[iterator + 'SearchType'] + '=';
} }
if ( f.searchType && (f.searchType == 'boolean' || f.searchType == 'select') ) { if (f.searchType && (f.searchType === 'boolean' || f.searchType === 'select')) {
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchSelectValue'].value; scope[iterator + 'SearchParams'] += scope[iterator + 'SearchSelectValue'].value;
} else if (f.searchType === undefined || f.searchType === 'gtzero') {
scope[iterator + 'SearchParams'] += encodeURI(scope[iterator + 'SearchValue']);
} }
else if ( f.searchType == undefined || f.searchType == 'gtzero' ) { scope[iterator + 'SearchParams'] += (sort_order) ? '&order_by=' + encodeURI(sort_order) : '';
scope[iterator + 'SearchParams'] += escape(scope[iterator + 'SearchValue']); } else {
} scope[iterator + 'SearchParams'] = (sort_order) ? 'order_by=' + encodeURI(sort_order) : '';
scope[iterator + 'SearchParams'] += (sort_order) ? '&order_by=' + escape(sort_order) : '';
}
else {
scope[iterator + 'SearchParams'] = (sort_order) ? 'order_by=' + escape(sort_order) : '';
} }
scope[iterator + 'Page'] = 0; scope[iterator + 'Page'] = 0;
url += (url.match(/\/$/)) ? '?' : '&'; url += (url.match(/\/$/)) ? '?' : '&';
url += scope[iterator + 'SearchParams']; url += scope[iterator + 'SearchParams'];
url += (scope[iterator + 'PageSize']) ? '&page_size=' + scope[iterator + 'PageSize'] : ""; url += (scope[iterator + 'PageSize']) ? '&page_size=' + scope[iterator + 'PageSize'] : "";
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: url }); RefreshRelated({ scope: scope, set: set, iterator: iterator, url: url });
} };
scope.sort = function (iterator, fld) { scope.sort = function (iterator, fld) {
var sort_order; var sort_order, icon, direction, set;
// reset sort icons back to 'icon-sort' on all columns // reset sort icons back to 'icon-sort' on all columns
// except the one clicked // except the one clicked
$('.' + iterator + ' .list-header').each(function(index) { $('.' + iterator + ' .list-header').each(function () {
if ($(this).attr('id') != iterator + '-' + fld + '-header') { if ($(this).attr('id') !== iterator + '-' + fld + '-header') {
var icon = $(this).find('i'); var icon = $(this).find('i');
icon.attr('class', 'icon-sort'); icon.attr('class', 'icon-sort');
} }
@@ -214,36 +210,34 @@ angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelat
// Toggle the icon for the clicked column // Toggle the icon for the clicked column
// and set the sort direction // and set the sort direction
var icon = $('#' + iterator + '-' + fld + '-header i'); icon = $('#' + iterator + '-' + fld + '-header i');
var direction = ''; direction = '';
if (icon.hasClass('icon-sort')) { if (icon.hasClass('icon-sort')) {
icon.removeClass('icon-sort'); icon.removeClass('icon-sort');
icon.addClass('icon-sort-up'); icon.addClass('icon-sort-up');
} } else if (icon.hasClass('icon-sort-up')) {
else if (icon.hasClass('icon-sort-up')) {
icon.removeClass('icon-sort-up'); icon.removeClass('icon-sort-up');
icon.addClass('icon-sort-down'); icon.addClass('icon-sort-down');
direction = '-'; direction = '-';
} } else if (icon.hasClass('icon-sort-down')) {
else if (icon.hasClass('icon-sort-down')) {
icon.removeClass('icon-sort-down'); icon.removeClass('icon-sort-down');
icon.addClass('icon-sort-up'); icon.addClass('icon-sort-up');
} }
// Set the sorder order value and call the API to refresh the list with the new order // Set the sorder order value and call the API to refresh the list with the new order
for (var set in form.related) { for (set in form.related) {
if (form.related[set].iterator == iterator) { if (form.related[set].iterator === iterator) {
if (form.related[set].fields[fld].sourceModel) { if (form.related[set].fields[fld].sourceModel) {
sort_order = direction + form.related[set].fields[fld].sourceModel + '__' + sort_order = direction + form.related[set].fields[fld].sourceModel + '__' +
form.related[set].fields[fld].sourceField; form.related[set].fields[fld].sourceField;
} } else {
else {
sort_order = direction + fld; sort_order = direction + fld;
} }
} }
} }
scope[iterator + 'SortOrder'] = sort_order; scope[iterator + 'SortOrder'] = sort_order;
scope.search(iterator); scope.search(iterator);
};
};
} }
} ]);
}]);

View File

@@ -15,6 +15,8 @@
* *
*/ */
'use strict';
angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper']) angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
.factory('SearchInit', ['Alert', 'Rest', 'Refresh', '$location', 'GetBasePath', 'Empty', '$timeout', 'Wait', 'Store', .factory('SearchInit', ['Alert', 'Rest', 'Refresh', '$location', 'GetBasePath', 'Empty', '$timeout', 'Wait', 'Store',
@@ -30,17 +32,6 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
sort_order = params.sort_order || '', sort_order = params.sort_order || '',
widgets, i, modifier, current_params; widgets, i, modifier, current_params;
/*
current_params = {
set: set,
defaultUrl: defaultUrl,
list: list,
iterator: iterator,
sort_order: sort_order
};
Store('CurrentSearchParams', current_params); // Save in case Activity Stream widget needs to restore */
function setDefaults(widget) { function setDefaults(widget) {
// Set default values // Set default values
var f, fld, fka, modifier; var f, fld, fka, modifier;
@@ -54,8 +45,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
if (list.fields[fld].sourceModel) { if (list.fields[fld].sourceModel) {
fka = list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField; fka = list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField;
sort_order = (list.fields[fld].desc) ? '-' + fka : fka; sort_order = (list.fields[fld].desc) ? '-' + fka : fka;
} } else {
else {
sort_order = (list.fields[fld].desc) ? '-' + fld : fld; sort_order = (list.fields[fld].desc) ? '-' + fld : fld;
} }
if (list.fields[fld].searchable === undefined || list.fields[fld].searchable === true) { if (list.fields[fld].searchable === undefined || list.fields[fld].searchable === true) {
@@ -97,13 +87,11 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
if (scope[list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder]) { if (scope[list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder]) {
// if set to a scope variable // if set to a scope variable
scope[iterator + 'SearchPlaceholder' + modifier] = scope[list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder]; scope[iterator + 'SearchPlaceholder' + modifier] = scope[list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder];
} } else {
else {
// Set to a string value in the list definition // Set to a string value in the list definition
scope[iterator + 'SearchPlaceholder' + modifier] = list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder; scope[iterator + 'SearchPlaceholder' + modifier] = list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder;
} }
} } else {
else {
// Default value // Default value
scope[iterator + 'SearchPlaceholder' + modifier] = 'Search'; scope[iterator + 'SearchPlaceholder' + modifier] = 'Search';
} }
@@ -168,14 +156,14 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder) { list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder) {
if (scope[list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder]) { if (scope[list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder]) {
// if set to a scope variable // if set to a scope variable
scope[iterator + 'SearchPlaceholder' + modifier] = scope[list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder]; scope[iterator + 'SearchPlaceholder' + modifier] = scope[list.fields[scope[iterator + 'SearchField' +
} modifier]].searchPlaceholder];
else { } else {
// Set to a string value in the list definition // Set to a string value in the list definition
scope[iterator + 'SearchPlaceholder' + modifier] = list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder; scope[iterator + 'SearchPlaceholder' + modifier] = list.fields[scope[iterator + 'SearchField' +
modifier]].searchPlaceholder;
} }
} } else {
else {
// Default value // Default value
scope[iterator + 'SearchPlaceholder' + modifier] = 'Search'; scope[iterator + 'SearchPlaceholder' + modifier] = 'Search';
} }
@@ -184,8 +172,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
scope[iterator + "InputDisable" + modifier] = true; scope[iterator + "InputDisable" + modifier] = true;
scope[iterator + 'ShowStartBtn' + modifier] = false; scope[iterator + 'ShowStartBtn' + modifier] = false;
scope.search(iterator); scope.search(iterator);
} } else if (list.fields[fld].searchSingleValue) {
else if (list.fields[fld].searchSingleValue){
// Query a specific attribute for one specific value // Query a specific attribute for one specific value
// searchSingleValue: true // searchSingleValue: true
// searchType: 'boolean|int|etc.' // searchType: 'boolean|int|etc.'
@@ -194,32 +181,32 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
scope[iterator + "SearchValue" + modifier] = list.fields[fld].searchValue; scope[iterator + "SearchValue" + modifier] = list.fields[fld].searchValue;
// For boolean type, SearchValue must be an object // For boolean type, SearchValue must be an object
if (list.fields[fld].searchType === 'boolean' && list.fields[fld].searchValue === 'true') { if (list.fields[fld].searchType === 'boolean' && list.fields[fld].searchValue === 'true') {
scope[iterator + "SearchSelectValue" + modifier] = { value: 1 }; scope[iterator + "SearchSelectValue" + modifier] = {
} value: 1
else if (list.fields[fld].searchType === 'boolean' && list.fields[fld].searchValue === 'false') { };
scope[iterator + "SearchSelectValue" + modifier] = { value: 0 }; } else if (list.fields[fld].searchType === 'boolean' && list.fields[fld].searchValue === 'false') {
} scope[iterator + "SearchSelectValue" + modifier] = {
else { value: 0
scope[iterator + "SearchSelectValue" + modifier] = { value: list.fields[fld].searchValue }; };
} else {
scope[iterator + "SearchSelectValue" + modifier] = {
value: list.fields[fld].searchValue
};
} }
scope[iterator + 'ShowStartBtn' + modifier] = false; scope[iterator + 'ShowStartBtn' + modifier] = false;
} } else if (list.fields[fld].searchType === 'in') {
else if (list.fields[fld].searchType === 'in') {
scope[iterator + "SearchType" + modifier] = 'in'; scope[iterator + "SearchType" + modifier] = 'in';
scope[iterator + "SearchValue" + modifier] = list.fields[fld].searchValue; scope[iterator + "SearchValue" + modifier] = list.fields[fld].searchValue;
scope[iterator + "InputDisable" + modifier] = true; scope[iterator + "InputDisable" + modifier] = true;
scope[iterator + 'ShowStartBtn' + modifier] = false; scope[iterator + 'ShowStartBtn' + modifier] = false;
} } else if (list.fields[fld].searchType && (list.fields[fld].searchType === 'boolean' ||
else if (list.fields[fld].searchType && (list.fields[fld].searchType === 'boolean' ||
list.fields[fld].searchType === 'select' || list.fields[fld].searchType === 'select_or')) { list.fields[fld].searchType === 'select' || list.fields[fld].searchType === 'select_or')) {
scope[iterator + 'SelectShow' + modifier] = true; scope[iterator + 'SelectShow' + modifier] = true;
scope[iterator + 'SearchSelectOpts' + modifier] = list.fields[fld].searchOptions; scope[iterator + 'SearchSelectOpts' + modifier] = list.fields[fld].searchOptions;
} } else if (list.fields[fld].searchType && list.fields[fld].searchType === 'int') {
else if (list.fields[fld].searchType && list.fields[fld].searchType === 'int') {
//scope[iterator + 'HideSearchType' + modifier] = true; //scope[iterator + 'HideSearchType' + modifier] = true;
scope[iterator + 'SearchType' + modifier] = 'int'; scope[iterator + 'SearchType' + modifier] = 'int';
} } else if (list.fields[fld].searchType && list.fields[fld].searchType === 'isnull') {
else if (list.fields[fld].searchType && list.fields[fld].searchType === 'isnull') {
scope[iterator + 'SearchType' + modifier] = 'isnull'; scope[iterator + 'SearchType' + modifier] = 'isnull';
scope[iterator + 'InputDisable' + modifier] = true; scope[iterator + 'InputDisable' + modifier] = true;
scope[iterator + 'SearchValue' + modifier] = 'true'; scope[iterator + 'SearchValue' + modifier] = 'true';
@@ -252,15 +239,15 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
// Execute the search // Execute the search
// //
scope[iterator + 'Loading'] = (load === undefined || load === true) ? true : false; scope[iterator + 'Loading'] = (load === undefined || load === true) ? true : false;
var url = defaultUrl, connect; var url = defaultUrl,
connect;
//finalize and execute the query //finalize and execute the query
scope[iterator + 'Page'] = (page) ? parseInt(page) - 1 : 0; scope[iterator + 'Page'] = (page) ? parseInt(page) - 1 : 0;
if (scope[iterator + 'SearchParams']) { if (scope[iterator + 'SearchParams']) {
if (/\/$/.test(url)) { if (/\/$/.test(url)) {
url += '?' + scope[iterator + 'SearchParams']; url += '?' + scope[iterator + 'SearchParams'];
} } else {
else {
url += '&' + scope[iterator + 'SearchParams']; url += '&' + scope[iterator + 'SearchParams'];
} }
} }
@@ -275,7 +262,12 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
url += connect + scope[iterator + 'ExtraParms']; url += connect + scope[iterator + 'ExtraParms'];
} }
url = url.replace(/\&\&/, '&'); url = url.replace(/\&\&/, '&');
Refresh({ scope: scope, set: set, iterator: iterator, url: url }); Refresh({
scope: scope,
set: set,
iterator: iterator,
url: url
});
}); });
@@ -308,23 +300,20 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchParams'] += '&' +
list.fields[scope[iterator + 'SearchField' + modifier]].searchObject + list.fields[scope[iterator + 'SearchField' + modifier]].searchObject +
'__id=' + scope[iterator + 'SearchValue' + modifier]; '__id=' + scope[iterator + 'SearchValue' + modifier];
} } else {
else {
scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchParams'] += '&' +
list.fields[scope[iterator + 'SearchField' + modifier]].searchObject + list.fields[scope[iterator + 'SearchField' + modifier]].searchObject +
'__name__icontains=' + '__name__icontains=' +
scope[iterator + 'SearchValue' + modifier]; scope[iterator + 'SearchValue' + modifier];
} }
} } else {
else {
// Search value is empty // Search value is empty
scope[iterator + 'ShowStartBtn' + modifier] = true; scope[iterator + 'ShowStartBtn' + modifier] = true;
scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchParams'] += '&' +
list.fields[scope[iterator + 'SearchField' + modifier]].searchField + list.fields[scope[iterator + 'SearchField' + modifier]].searchField +
'=' + list.fields[scope[iterator + 'SearchField' + modifier]].searchObject; '=' + list.fields[scope[iterator + 'SearchField' + modifier]].searchObject;
} }
} } else {
else {
// Object Type set to All // Object Type set to All
scope[iterator + 'HideAllStartBtn' + modifier] = true; scope[iterator + 'HideAllStartBtn' + modifier] = true;
} }
@@ -347,16 +336,14 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
modifier = (i === 1) ? '' : i; modifier = (i === 1) ? '' : i;
scope[iterator + 'HoldInput' + modifier] = true; scope[iterator + 'HoldInput' + modifier] = true;
if ($('#search-widget-container' + modifier) && if ($('#search-widget-container' + modifier) &&
list.fields[scope[iterator + 'SearchField' + modifier]] && list.fields[scope[iterator + 'SearchField' + modifier]] && !list.fields[scope[iterator + 'SearchField' + modifier]].searchObject) {
!list.fields[scope[iterator + 'SearchField' + modifier]].searchObject) {
// if the search widget exists and its value is not an object, add its parameters to the query // if the search widget exists and its value is not an object, add its parameters to the query
if (scope[iterator + 'SearchValue' + modifier]) { if (scope[iterator + 'SearchValue' + modifier]) {
// if user typed a value in the input box, show the reset link // if user typed a value in the input box, show the reset link
scope[iterator + 'ShowStartBtn' + modifier] = false; scope[iterator + 'ShowStartBtn' + modifier] = false;
} } else {
else {
scope[iterator + 'ShowStartBtn' + modifier] = true; scope[iterator + 'ShowStartBtn' + modifier] = true;
} }
@@ -366,18 +353,15 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'gtzero')) { list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'gtzero')) {
if (list.fields[scope[iterator + 'SearchField' + modifier]].searchField) { if (list.fields[scope[iterator + 'SearchField' + modifier]].searchField) {
scope[iterator + 'SearchParams'] += '&' + list.fields[scope[iterator + 'SearchField' + modifier]].searchField + '__'; scope[iterator + 'SearchParams'] += '&' + list.fields[scope[iterator + 'SearchField' + modifier]].searchField + '__';
} } else if (list.fields[scope[iterator + 'SearchField' + modifier]].sourceModel) {
else if (list.fields[scope[iterator + 'SearchField' + modifier]].sourceModel) {
// handle fields whose source is a related model e.g. inventories.organization // handle fields whose source is a related model e.g. inventories.organization
scope[iterator + 'SearchParams'] += '&' + list.fields[scope[iterator + 'SearchField' + modifier]].sourceModel + '__' + scope[iterator + 'SearchParams'] += '&' + list.fields[scope[iterator + 'SearchField' + modifier]].sourceModel + '__' +
list.fields[scope[iterator + 'SearchField' + modifier]].sourceField + '__'; list.fields[scope[iterator + 'SearchField' + modifier]].sourceField + '__';
} } else if ((list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'select') &&
else if ( (list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'select') &&
(scope[iterator + 'SearchSelectValue' + modifier].value === '' || (scope[iterator + 'SearchSelectValue' + modifier].value === '' ||
scope[iterator + 'SearchSelectValue' + modifier].value === null)) { scope[iterator + 'SearchSelectValue' + modifier].value === null)) {
scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchField' + modifier] + '__'; scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchField' + modifier] + '__';
} } else {
else {
scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchField' + modifier] + '__'; scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchField' + modifier] + '__';
} }
@@ -385,17 +369,14 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
(list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'int' || (list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'int' ||
list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'boolean')) { list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'boolean')) {
scope[iterator + 'SearchParams'] += 'int='; scope[iterator + 'SearchParams'] += 'int=';
} } else if (list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
else if ( list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'gtzero') { list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'gtzero') {
scope[iterator + 'SearchParams'] += 'gt=0'; scope[iterator + 'SearchParams'] += 'gt=0';
} } else if ((list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'select') &&
else if ( (list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'select') &&
(scope[iterator + 'SearchSelectValue' + modifier].value === '' || (scope[iterator + 'SearchSelectValue' + modifier].value === '' ||
scope[iterator + 'SearchSelectValue' + modifier].value === null)) { scope[iterator + 'SearchSelectValue' + modifier].value === null)) {
scope[iterator + 'SearchParams'] += 'iexact='; scope[iterator + 'SearchParams'] += 'iexact=';
} } else {
else {
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchType' + modifier] + '='; scope[iterator + 'SearchParams'] += scope[iterator + 'SearchType' + modifier] + '=';
} }
@@ -403,8 +384,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
(list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'boolean' || (list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'boolean' ||
list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'select')) { list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'select')) {
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchSelectValue' + modifier].value; scope[iterator + 'SearchParams'] += scope[iterator + 'SearchSelectValue' + modifier].value;
} } else {
else {
if ((!list.fields[scope[iterator + 'SearchField' + modifier]].searchType) || if ((!list.fields[scope[iterator + 'SearchField' + modifier]].searchType) ||
(list.fields[scope[iterator + 'SearchField' + modifier]].searchType && (list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
list.fields[scope[iterator + 'SearchField' + modifier]].searchType !== 'or' && list.fields[scope[iterator + 'SearchField' + modifier]].searchType !== 'or' &&
@@ -468,13 +448,11 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
if (icon.hasClass('fa-sort')) { if (icon.hasClass('fa-sort')) {
icon.removeClass('fa-sort'); icon.removeClass('fa-sort');
icon.addClass('fa-sort-up'); icon.addClass('fa-sort-up');
} } else if (icon.hasClass('fa-sort-up')) {
else if (icon.hasClass('fa-sort-up')) {
icon.removeClass('fa-sort-up'); icon.removeClass('fa-sort-up');
icon.addClass('fa-sort-down'); icon.addClass('fa-sort-down');
direction = '-'; direction = '-';
} } else if (icon.hasClass('fa-sort-down')) {
else if (icon.hasClass('fa-sort-down')) {
icon.removeClass('fa-sort-down'); icon.removeClass('fa-sort-down');
icon.addClass('fa-sort-up'); icon.addClass('fa-sort-up');
} }
@@ -482,15 +460,12 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
// Set the sorder order value and call the API to refresh the list with the new order // Set the sorder order value and call the API to refresh the list with the new order
if (list.fields[fld].searchField) { if (list.fields[fld].searchField) {
sort_order = direction + list.fields[fld].searchField; sort_order = direction + list.fields[fld].searchField;
} } else if (list.fields[fld].sortField) {
else if (list.fields[fld].sortField) {
sort_order = direction + list.fields[fld].sortField; sort_order = direction + list.fields[fld].sortField;
} } else {
else {
if (list.fields[fld].sourceModel) { if (list.fields[fld].sourceModel) {
sort_order = direction + list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField; sort_order = direction + list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField;
} } else {
else {
sort_order = direction + fld; sort_order = direction + fld;
} }
} }
@@ -505,4 +480,5 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
}; };
}; };
}]); }
]);

View File

@@ -5,24 +5,29 @@
* Routines shared amongst the team controllers * Routines shared amongst the team controllers
*/ */
angular.module('TeamHelper', [ 'RestServices', 'Utilities', 'OrganizationListDefinition', 'use strict';
'SearchHelper', 'PaginationHelpers', 'ListGenerator' ])
.factory('SetTeamListeners', ['Alert', 'Rest', function(Alert, Rest) { angular.module('TeamHelper', ['RestServices', 'Utilities', 'OrganizationListDefinition', 'SearchHelper',
'PaginationHelpers', 'ListGenerator'
])
.factory('SetTeamListeners', ['Alert', 'Rest',
function (Alert, Rest) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var set = params.set; set = params.set,
var iterator = params.iterator; iterator = params.iterator;
// Listeners to perform lookups after main inventory list loads // Listeners to perform lookups after main inventory list loads
scope.$on('TeamResultFound', function (e, results, lookup_results) { scope.$on('TeamResultFound', function (e, results, lookup_results) {
if ( lookup_results.length == results.length ) { var i, j, key, property;
if (lookup_results.length === results.length) {
key = 'organization'; key = 'organization';
property = 'organization_name'; property = 'organization_name';
for (var i=0; i < results.length; i++) { for (i = 0; i < results.length; i++) {
for (var j=0; j < lookup_results.length; j++) { for (j = 0; j < lookup_results.length; j++) {
if (results[i][key] == lookup_results[j].id) { if (results[i][key] === lookup_results[j].id) {
results[i][property] = lookup_results[j].value; results[i][property] = lookup_results[j].value;
} }
} }
@@ -37,23 +42,29 @@ angular.module('TeamHelper', [ 'RestServices', 'Utilities', 'OrganizationListDef
// lookup the id and name of each organization. After each lookup // lookup the id and name of each organization. After each lookup
// completes, call resultFound. // completes, call resultFound.
var lookup_results = []; var i, lookup_results = [], url;
for (var i = 0; i < results.length; i++) { function getOrganization(url) {
Rest.setUrl('/api/v1/organizations/' + results[i].organization + '/'); Rest.setUrl(url);
Rest.get() Rest.get()
.success( function( data, status, headers, config) { .success(function (data) {
lookup_results.push({ id: data.id, value: data.name }); lookup_results.push({ id: data.id, value: data.name });
scope.$emit('TeamResultFound', results, lookup_results); scope.$emit('TeamResultFound', results, lookup_results);
}) })
.error( function( data, status, headers, config) { .error(function () {
lookup_results.push({ id: 'error' }); lookup_results.push({ id: 'error' });
scope.$emit('TeamResultFound', results, lookup_results); scope.$emit('TeamResultFound', results, lookup_results);
}); });
} }
});
for (i = 0; i < results.length; i++) {
url = '/api/v1/organizations/' + results[i].organization + '/';
getOrganization(url);
} }
}]) });
};
}
])
.factory('TeamLookUpOrganizationInit', ['Alert', 'Rest', 'OrganizationList', 'GenerateList', 'SearchInit', 'PaginateInit', .factory('TeamLookUpOrganizationInit', ['Alert', 'Rest', 'OrganizationList', 'GenerateList', 'SearchInit', 'PaginateInit',
function (Alert, Rest, OrganizationList, GenerateList, SearchInit, PaginateInit) { function (Alert, Rest, OrganizationList, GenerateList, SearchInit, PaginateInit) {
@@ -63,26 +74,26 @@ angular.module('TeamHelper', [ 'RestServices', 'Utilities', 'OrganizationListDef
// Show pop-up to select organization // Show pop-up to select organization
scope.lookUpOrganization = function () { scope.lookUpOrganization = function () {
var list = OrganizationList; var list = OrganizationList,
var listGenerator = GenerateList; listGenerator = GenerateList,
var listScope = listGenerator.inject(list, { mode: 'lookup', hdr: 'Select Organization' }); listScope = listGenerator.inject(list, { mode: 'lookup', hdr: 'Select Organization' }),
var defaultUrl = '/api/v1/organizations/'; defaultUrl = '/api/v1/organizations/';
listScope.selectAction = function () { listScope.selectAction = function () {
var found = false; var i, found = false;
for (var i=0; i < listScope[list.name].length; i++) { for (i = 0; i < listScope[list.name].length; i++) {
if (listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] == "success") { if (listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] === "success") {
found = true; found = true;
scope['organization'] = listScope[list.name][i].id; scope.organization = listScope[list.name][i].id;
scope['organization_name'] = listScope[list.name][i].name; scope.organization_name = listScope[list.name][i].name;
scope['team_form'].$setDirty(); scope.team_form.$setDirty();
listGenerator.hide(); listGenerator.hide();
} }
} }
if (found == false) { if (found === false) {
Alert('No Selection', 'Click on a row to select an Organization before clicking the Select button.'); Alert('No Selection', 'Click on a row to select an Organization before clicking the Select button.');
} }
} };
listScope.toggle_organization = function (id) { listScope.toggle_organization = function (id) {
// when user clicks a row, remove 'success' class from all rows except clicked-on row // when user clicks a row, remove 'success' class from all rows except clicked-on row
@@ -91,17 +102,26 @@ angular.module('TeamHelper', [ 'RestServices', 'Utilities', 'OrganizationListDef
listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] = ""; listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] = "";
} }
} }
if (id != null && id != undefined) { if (id !== null && id !== undefined) {
listScope[list.iterator + "_" + id + "_class"] = "success"; listScope[list.iterator + "_" + id + "_class"] = "success";
} }
} };
SearchInit({ scope: listScope, set: list.name, list: list, url: defaultUrl }); SearchInit({
PaginateInit({ scope: listScope, list: list, url: defaultUrl, mode: 'lookup' }); scope: listScope,
set: list.name,
list: list,
url: defaultUrl
});
PaginateInit({
scope: listScope,
list: list,
url: defaultUrl,
mode: 'lookup'
});
scope.search(list.iterator); scope.search(list.iterator);
listScope.toggle_organization(scope.organization); listScope.toggle_organization(scope.organization);
};
};
} }
} ]);
}]);

View File

@@ -6,9 +6,11 @@
* *
* @dict * @dict
*/ */
'use strict';
angular.module('AdminListDefinition', []) angular.module('AdminListDefinition', [])
.value( .value('AdminList', {
'AdminList', {
name: 'admins', name: 'admins',
iterator: 'admin', iterator: 'admin',
@@ -33,9 +35,7 @@ angular.module('AdminListDefinition', [])
} }
}, },
actions: { actions: {},
},
fieldActions: { fieldActions: {}
}
}); });

View File

@@ -6,9 +6,11 @@
* *
* @dict * @dict
*/ */
'use strict';
angular.module('CloudCredentialsListDefinition', []) angular.module('CloudCredentialsListDefinition', [])
.value( .value('CloudCredentialList', {
'CloudCredentialList', {
name: 'cloudcredentials', name: 'cloudcredentials',
iterator: 'cloudcredential', iterator: 'cloudcredential',
@@ -55,7 +57,7 @@ angular.module('CloudCredentialsListDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
ngClick: "editCredential(\{\{ credential.id \}\})", ngClick: "editCredential(credential.id)",
icon: 'fa-edit', icon: 'fa-edit',
label: 'Edit', label: 'Edit',
"class": 'btn-sm', "class": 'btn-sm',
@@ -64,7 +66,7 @@ angular.module('CloudCredentialsListDefinition', [])
}, },
"delete": { "delete": {
ngClick: "deleteCredential(\{\{ credential.id \}\},'\{\{ credential.name \}\}')", ngClick: "deleteCredential(credential.id, credential.name)",
icon: 'fa-trash-o', icon: 'fa-trash-o',
label: 'Delete', label: 'Delete',
"class": 'btn-sm', "class": 'btn-sm',

View File

@@ -6,16 +6,19 @@
* *
* @dict * @dict
*/ */
'use strict';
angular.module('CredentialsListDefinition', []) angular.module('CredentialsListDefinition', [])
.value( .value('CredentialList', {
'CredentialList', {
name: 'credentials', name: 'credentials',
iterator: 'credential', iterator: 'credential',
selectTitle: 'Add Credentials', selectTitle: 'Add Credentials',
editTitle: 'Credentials', editTitle: 'Credentials',
selectInstructions: '<p>Select existing credentials by clicking each credential or checking the related checkbox. When finished, click the blue ' + selectInstructions: "<p>Select existing credentials by clicking each credential or checking the related checkbox. When " +
'<em>Select</em> button, located bottom right.</p> <p>Create a brand new credential by clicking the green <em>Create New</em> button.</p>', "finished, click the blue <em>Select</em> button, located bottom right.</p> <p>Create a brand new credential by clicking " +
"the green <em>Create New</em> button.</p>",
index: true, index: true,
hover: true, hover: true,
@@ -35,22 +38,6 @@ angular.module('CredentialsListDefinition', [])
excludeModal: true, excludeModal: true,
nosort: true nosort: true
} }
/*
team: {
label: 'Team',
ngBind: 'credential.team_name',
sourceModel: 'team',
sourceField: 'name',
excludeModal: true
},
user: {
label: 'User',
ngBind: 'credential.user_username',
sourceModel: 'user',
sourceField: 'username',
excludeModal: true
}
*/
}, },
actions: { actions: {
@@ -68,7 +55,7 @@ angular.module('CredentialsListDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
ngClick: "editCredential(\{\{ credential.id \}\})", ngClick: "editCredential(credential.id)",
icon: 'fa-edit', icon: 'fa-edit',
label: 'Edit', label: 'Edit',
"class": 'btn-sm', "class": 'btn-sm',
@@ -77,7 +64,7 @@ angular.module('CredentialsListDefinition', [])
}, },
"delete": { "delete": {
ngClick: "deleteCredential(\{\{ credential.id \}\},'\{\{ credential.name \}\}')", ngClick: "deleteCredential(credential.id, credential.name)",
icon: 'fa-trash', icon: 'fa-trash',
label: 'Delete', label: 'Delete',
"class": 'btn-sm', "class": 'btn-sm',

View File

@@ -6,9 +6,11 @@
* *
* *
*/ */
'use strict';
angular.module('GroupListDefinition', []) angular.module('GroupListDefinition', [])
.value( .value('GroupList', {
'GroupList', {
name: 'groups', name: 'groups',
iterator: 'group', iterator: 'group',
@@ -41,7 +43,7 @@ angular.module('GroupListDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "editGroup(\{\{ group.id \}\})", ngClick: "editGroup(group.id)",
icon: 'icon-edit', icon: 'icon-edit',
"class": 'btn-xs', "class": 'btn-xs',
awToolTip: 'Edit group', awToolTip: 'Edit group',
@@ -50,7 +52,7 @@ angular.module('GroupListDefinition', [])
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "deleteGroup(\{\{ group.id \}\},'\{\{ group.name \}\}')", ngClick: "deleteGroup(group.id, group.name)",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-xs', "class": 'btn-xs',
awToolTip: 'Delete group', awToolTip: 'Delete group',

View File

@@ -7,9 +7,11 @@
* on the home tab. * on the home tab.
* *
*/ */
'use strict';
angular.module('HomeGroupListDefinition', []) angular.module('HomeGroupListDefinition', [])
.value( .value('HomeGroupList', {
'HomeGroupList', {
name: 'home_groups', name: 'home_groups',
iterator: 'group', iterator: 'group',
@@ -30,15 +32,21 @@ angular.module('HomeGroupListDefinition', [])
sourceModel: 'inventory', sourceModel: 'inventory',
sourceField: 'name', sourceField: 'name',
columnClass: 'col-lg-3 col-md2 col-sm-2 hidden-xs elllipsis', columnClass: 'col-lg-3 col-md2 col-sm-2 hidden-xs elllipsis',
linkTo: "\{\{ '/#/inventories/' + group.inventory + '/' \}\}" linkTo: "{{ /#/inventories/' + group.inventory + '/' }}"
}, },
source: { source: {
label: 'Source', label: 'Source',
searchType: 'select', searchType: 'select',
searchOptions: [ searchOptions: [{
{ name: "ec2", value: "ec2" }, name: "ec2",
{ name: "none", value: "" }, value: "ec2"
{ name: "rax", value: "rax" }], }, {
name: "none",
value: ""
}, {
name: "rax",
value: "rax"
}],
sourceModel: 'inventory_source', sourceModel: 'inventory_source',
sourceField: 'source', sourceField: 'source',
searchOnly: true searchOnly: true
@@ -77,7 +85,7 @@ angular.module('HomeGroupListDefinition', [])
sync_status: { sync_status: {
mode: 'all', mode: 'all',
ngClick: "viewUpdateStatus(group.id, group.group_id)", ngClick: "viewUpdateStatus(group.id, group.group_id)",
awToolTip: "\{\{ group.status_tooltip \}\}", awToolTip: "{{ group.status_tooltip }}",
ngClass: "group.status_class", ngClass: "group.status_class",
dataPlacement: "top" dataPlacement: "top"
}, },
@@ -91,8 +99,8 @@ angular.module('HomeGroupListDefinition', [])
group_update: { group_update: {
//label: 'Sync', //label: 'Sync',
mode: 'all', mode: 'all',
ngClick: 'updateGroup(\{\{ group.id \}\})', ngClick: 'updateGroup(group.id)',
awToolTip: "\{\{ group.launch_tooltip \}\}", awToolTip: "{{ group.launch_tooltip }}",
ngShow: "(group.status !== 'running' && group.status !== 'pending' && group.status !== 'updating')", ngShow: "(group.status !== 'running' && group.status !== 'pending' && group.status !== 'updating')",
ngClass: "group.launch_class", ngClass: "group.launch_class",
dataPlacement: "top" dataPlacement: "top"
@@ -100,7 +108,7 @@ angular.module('HomeGroupListDefinition', [])
cancel: { cancel: {
//label: 'Cancel', //label: 'Cancel',
mode: 'all', mode: 'all',
ngClick: "cancelUpdate(\{\{ group.id \}\})", ngClick: "cancelUpdate(group.id)",
awToolTip: "Cancel sync process", awToolTip: "Cancel sync process",
'class': 'red-txt', 'class': 'red-txt',
ngShow: "(group.status == 'running' || group.status == 'pending' || group.status == 'updating')", ngShow: "(group.status == 'running' || group.status == 'pending' || group.status == 'updating')",

View File

@@ -7,9 +7,11 @@
* on the home tab. * on the home tab.
* *
*/ */
'use strict';
angular.module('HomeHostListDefinition', []) angular.module('HomeHostListDefinition', [])
.value( .value('HomeHostList', {
'HomeHostList', {
name: 'hosts', name: 'hosts',
iterator: 'host', iterator: 'host',
@@ -24,14 +26,14 @@ angular.module('HomeHostListDefinition', [])
key: true, key: true,
label: 'Name', label: 'Name',
columnClass: 'col-lg-4 col-md3 col-sm-3 col-xs-7 ellipsis', columnClass: 'col-lg-4 col-md3 col-sm-3 col-xs-7 ellipsis',
ngClick: "editHost(\{\{ host.id \}\}, '\{\{ host.name \}\}')" ngClick: "editHost(host.id, host.name)"
}, },
inventory_name: { inventory_name: {
label: 'Inventory', label: 'Inventory',
sourceModel: 'inventory', sourceModel: 'inventory',
sourceField: 'name', sourceField: 'name',
columnClass: 'col-lg-3 col-md2 col-sm-2 hidden-xs elllipsis', columnClass: 'col-lg-3 col-md2 col-sm-2 hidden-xs elllipsis',
linkTo: "\{\{ '/#/inventories/' + host.inventory \}\}" linkTo: "{{ '/#/inventories/' + host.inventory }}"
}, },
enabled: { enabled: {
label: 'Disabled?', label: 'Disabled?',

View File

@@ -6,9 +6,11 @@
* *
* *
*/ */
'use strict';
angular.module('HostListDefinition', []) angular.module('HostListDefinition', [])
.value( .value('HostList', {
'HostList', {
name: 'hosts', name: 'hosts',
iterator: 'host', iterator: 'host',
@@ -21,7 +23,7 @@ angular.module('HostListDefinition', [])
name: { name: {
key: true, key: true,
label: 'Host Name', label: 'Host Name',
linkTo: "/inventories/\{\{ inventory_id \}\}/hosts/\{\{ host.id \}\}" linkTo: "/inventories/{{ inventory_id }}/hosts/{{ host.id }}"
}, },
description: { description: {
label: 'Description' label: 'Description'
@@ -41,7 +43,7 @@ angular.module('HostListDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "editHost(\{\{ host.id \}\})", ngClick: "editHost({{ host.id }})",
icon: 'icon-edit', icon: 'icon-edit',
"class": 'btn-xs', "class": 'btn-xs',
awToolTip: 'Edit host', awToolTip: 'Edit host',
@@ -50,7 +52,7 @@ angular.module('HostListDefinition', [])
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "deleteHost(\{\{ host.id \}\},'\{\{ host.name \}\}')", ngClick: "deleteHost(host.id, host.name)",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-xs', "class": 'btn-xs',
awToolTip: 'Delete host', awToolTip: 'Delete host',

View File

@@ -5,15 +5,18 @@
* List view object for Inventories data model. * List view object for Inventories data model.
* *
*/ */
'use strict';
angular.module('InventoriesListDefinition', []) angular.module('InventoriesListDefinition', [])
.value( .value('InventoryList', {
'InventoryList', {
name: 'inventories', name: 'inventories',
iterator: 'inventory', iterator: 'inventory',
selectTitle: 'Add Inventories', selectTitle: 'Add Inventories',
editTitle: 'Inventories', editTitle: 'Inventories',
selectInstructions: 'Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new row.', selectInstructions: "Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> " +
"button to create a new row.",
index: true, index: true,
hover: true, hover: true,
@@ -69,16 +72,16 @@ angular.module('InventoriesListDefinition', [])
fieldActions: { fieldActions: {
status: { status: {
//label: 'Status', //label: 'Status',
ngHref: "\{\{ inventory.status_link \}\}", ngHref: "inventory.status_link",
iconClass: "\{\{ 'fa fa-cloud icon-cloud-' + inventory.status_class \}\}", iconClass: "{{ 'fa fa-cloud icon-cloud-' + inventory.status_class }}",
awToolTip: "\{\{ inventory.status_tip \}\}", awToolTip: "{{ inventory.status_tip }}",
dataPlacement: "top" dataPlacement: "top"
}, },
failed_hosts: { failed_hosts: {
//label: 'Failures', //label: 'Failures',
ngHref: "\{\{ inventory.failed_hosts_link \}\}", ngHref: "inventory.failed_hosts_link",
iconClass: "\{\{ 'fa icon-failures-' + inventory.failed_hosts_class \}\}", iconClass: "{{ 'fa icon-failures-' + inventory.failed_hosts_class }}",
awToolTip: "\{\{ inventory.failed_hosts_tip \}\}", awToolTip: "{{ inventory.failed_hosts_tip }}",
dataPlacement: "top" dataPlacement: "top"
}, },
edit: { edit: {
@@ -89,7 +92,7 @@ angular.module('InventoriesListDefinition', [])
}, },
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "deleteInventory(\{\{ inventory.id \}\},'\{\{ inventory.name \}\}')", ngClick: "deleteInventory(inventory.id, inventory.names')",
awToolTip: 'Delete inventory', awToolTip: 'Delete inventory',
dataPlacement: 'top' dataPlacement: 'top'
} }

View File

@@ -6,9 +6,11 @@
* Right side of /inventories/N page, showing hosts in the selected group. * Right side of /inventories/N page, showing hosts in the selected group.
* *
*/ */
'use strict';
angular.module('InventoryHostsDefinition', []) angular.module('InventoryHostsDefinition', [])
.value( .value('InventoryHosts', {
'InventoryHosts', {
name: 'hosts', name: 'hosts',
iterator: 'host', iterator: 'host',
@@ -24,10 +26,10 @@ angular.module('InventoryHostsDefinition', [])
name: { name: {
key: true, key: true,
label: 'Hosts', label: 'Hosts',
ngClick: "editHost(\{\{ host.id \}\})", ngClick: "editHost(host.id)",
searchPlaceholder: "search_place_holder", searchPlaceholder: "search_place_holder",
columnClass: 'col-lg-9 col-md-9 col-sm-7 col-xs-7', columnClass: 'col-lg-9 col-md-9 col-sm-7 col-xs-7',
dataHostId: "\{\{ host.id \}\}", dataHostId: "{{ host.id }}",
dataType: "host", dataType: "host",
awDraggable: "true" awDraggable: "true"
}, },
@@ -65,14 +67,14 @@ angular.module('InventoryHostsDefinition', [])
}, },
edit: { edit: {
//label: 'Edit', //label: 'Edit',
ngClick: "editHost(\{\{ host.id \}\})", ngClick: "editHost(host.id)",
icon: 'icon-edit', icon: 'icon-edit',
awToolTip: 'Edit host', awToolTip: 'Edit host',
dataPlacement: 'top' dataPlacement: 'top'
}, },
"delete": { "delete": {
//label: 'Delete', //label: 'Delete',
ngClick: "deleteHost(\{\{ host.id \}\},'\{\{ host.name \}\}')", ngClick: "deleteHost(host.id, host.name)",
icon: 'icon-trash', icon: 'icon-trash',
awToolTip: 'Delete host', awToolTip: 'Delete host',
dataPlacement: 'top' dataPlacement: 'top'
@@ -97,4 +99,3 @@ angular.module('InventoryHostsDefinition', [])
} }
}); });

View File

@@ -6,9 +6,11 @@
* *
* *
*/ */
'use strict';
angular.module('JobEventsListDefinition', []) angular.module('JobEventsListDefinition', [])
.value( .value('JobEventList', {
'JobEventList', {
name: 'jobevents', name: 'jobevents',
iterator: 'jobevent', iterator: 'jobevent',
@@ -53,7 +55,13 @@ angular.module('JobEventsListDefinition', [])
columnClass: 'col-sm-1 col-xs-2 text-center', columnClass: 'col-sm-1 col-xs-2 text-center',
searchField: 'failed', searchField: 'failed',
searchType: 'boolean', searchType: 'boolean',
searchOptions: [{ name: 'success', value: 0 }, { name: 'error', value: 1 }], searchOptions: [{
name: 'success',
value: 0
}, {
name: 'error',
value: 1
}],
nosort: true, nosort: true,
searchable: false, searchable: false,
ngClick: 'viewJobEvent({{ jobevent.id }})', ngClick: 'viewJobEvent({{ jobevent.id }})',

View File

@@ -6,6 +6,9 @@
* *
* *
*/ */
'use strict';
angular.module('JobHostDefinition', []) angular.module('JobHostDefinition', [])
.value('JobHostList', { .value('JobHostList', {
@@ -64,7 +67,13 @@ angular.module('JobHostDefinition', [])
dataPlacement: 'top', dataPlacement: 'top',
searchField: 'failed', searchField: 'failed',
searchType: 'boolean', searchType: 'boolean',
searchOptions: [{ name: "success", value: 0 }, { name: "error", value: 1 }] searchOptions: [{
name: "success",
value: 0
}, {
name: "error",
value: 1
}]
}, },
failed: { failed: {
label: 'Job failed?', label: 'Job failed?',

View File

@@ -6,15 +6,18 @@
* *
* *
*/ */
'use strict';
angular.module('JobTemplatesListDefinition', []) angular.module('JobTemplatesListDefinition', [])
.value( .value('JobTemplateList', {
'JobTemplateList', {
name: 'job_templates', name: 'job_templates',
iterator: 'job_template', iterator: 'job_template',
selectTitle: 'Add Job Template', selectTitle: 'Add Job Template',
editTitle: 'Job Templates', editTitle: 'Job Templates',
selectInstructions: 'Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new row.', selectInstructions: "Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> " +
"button to create a new row.",
index: true, index: true,
hover: true, hover: true,
@@ -46,7 +49,7 @@ angular.module('JobTemplatesListDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "editJobTemplate(\{\{ job_template.id \}\})", ngClick: "editJobTemplate(job_template.id)",
icon: 'icon-edit', icon: 'icon-edit',
awToolTip: 'Edit template', awToolTip: 'Edit template',
"class": 'btn-default btn-xs', "class": 'btn-default btn-xs',
@@ -57,13 +60,13 @@ angular.module('JobTemplatesListDefinition', [])
icon: 'icon-rocket', icon: 'icon-rocket',
mode: 'all', mode: 'all',
"class": 'btn-xs btn-success', "class": 'btn-xs btn-success',
ngClick: 'submitJob(\{\{ job_template.id \}\})', ngClick: 'submitJob(job_template.id)',
awToolTip: 'Start a job using this template', awToolTip: 'Start a job using this template',
dataPlacement: 'top' dataPlacement: 'top'
}, },
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "deleteJobTemplate(\{\{ job_template.id \}\},'\{\{ job_template.name \}\}')", ngClick: "deleteJobTemplate(job_template.id, job_template.name)",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-danger btn-xs', "class": 'btn-danger btn-xs',
awToolTip: 'Delete template', awToolTip: 'Delete template',

View File

@@ -6,6 +6,9 @@
* *
* *
*/ */
'use strict';
angular.module('JobsListDefinition', []) angular.module('JobsListDefinition', [])
.value( 'JobList', { .value( 'JobList', {

View File

@@ -6,9 +6,11 @@
* *
* *
*/ */
'use strict';
angular.module('OrganizationListDefinition', []) angular.module('OrganizationListDefinition', [])
.value( .value('OrganizationList', {
'OrganizationList', {
name: 'organizations', name: 'organizations',
iterator: 'organization', iterator: 'organization',

View File

@@ -6,14 +6,17 @@
* *
* *
*/ */
'use strict';
angular.module('PermissionListDefinition', []) angular.module('PermissionListDefinition', [])
.value( .value('PermissionList', {
'PermissionList', {
name: 'permissions', name: 'permissions',
iterator: 'permission', iterator: 'permission',
selectTitle: 'Add Permission', selectTitle: 'Add Permission',
selectInstructions: 'Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new row.', selectInstructions: "Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> " +
"button to create a new row.",
editTitle: 'Permissions', editTitle: 'Permissions',
index: true, index: true,
well: true, well: true,
@@ -22,7 +25,7 @@ angular.module('PermissionListDefinition', [])
name: { name: {
key: true, key: true,
label: 'Name', label: 'Name',
ngClick: 'editPermission(\{\{ permission.id \}\})' ngClick: 'editPermission(permission.id)'
}, },
inventory: { inventory: {
label: 'Inventory', label: 'Inventory',
@@ -58,7 +61,7 @@ angular.module('PermissionListDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "editPermission(\{\{ permission.id \}\})", ngClick: "editPermission(permission.id)",
icon: 'icon-edit', icon: 'icon-edit',
"class": 'btn-xs btn-default', "class": 'btn-xs btn-default',
awToolTip: 'Edit permission', awToolTip: 'Edit permission',
@@ -67,7 +70,7 @@ angular.module('PermissionListDefinition', [])
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "deletePermission(\{\{ permission.id \}\},'\{\{ permission.name \}\}')", ngClick: "deletePermission(permission.id, permission.name)",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-xs btn-danger', "class": 'btn-xs btn-danger',
awToolTip: 'Delete permission', awToolTip: 'Delete permission',

View File

@@ -6,9 +6,11 @@
* *
* *
*/ */
'use strict';
angular.module('ProjectsListDefinition', []) angular.module('ProjectsListDefinition', [])
.value( .value('ProjectList', {
'ProjectList', {
name: 'projects', name: 'projects',
iterator: 'project', iterator: 'project',
@@ -38,10 +40,10 @@ angular.module('ProjectsListDefinition', [])
}, },
status: { status: {
label: 'Status', label: 'Status',
ngClick: 'showSCMStatus(\{\{ project.id \}\})', ngClick: 'showSCMStatus(project.id)',
awToolTip: 'View details of last SCM Update', awToolTip: 'View details of last SCM Update',
dataPlacement: 'top', dataPlacement: 'top',
badgeIcon: "\{\{ 'fa icon-failures-' + project.badge \}\}", badgeIcon: "{{ 'fa icon-failures-' + project.badge }}",
badgePlacement: 'left', badgePlacement: 'left',
searchType: 'select', searchType: 'select',
searchOptions: [], // will be set by Options call to projects resource searchOptions: [], // will be set by Options call to projects resource
@@ -91,27 +93,27 @@ angular.module('ProjectsListDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "editProject(\{\{ project.id \}\})", ngClick: "editProject(project.id)",
awToolTip: 'Edit project properties', awToolTip: 'Edit project properties',
dataPlacement: 'top' dataPlacement: 'top'
}, },
scm_update: { scm_update: {
label: 'Update', label: 'Update',
ngClick: 'SCMUpdate(\{\{ project.id \}\})', ngClick: 'SCMUpdate(project.id)',
awToolTip: "\{\{ project.scm_update_tooltip \}\}", awToolTip: "{{ project.scm_update_tooltip }}",
ngClass: "project.scm_type_class", ngClass: "project.scm_type_class",
dataPlacement: 'top' dataPlacement: 'top'
}, },
cancel: { cancel: {
label: 'Stop', label: 'Stop',
ngClick: "cancelUpdate(\{\{ project.id \}\}, '\{\{ project.name \}\}')", ngClick: "cancelUpdate(project.id, project.name)",
awToolTip: 'Cancel a running SCM update process', awToolTip: 'Cancel a running SCM update process',
ngShow: "project.status == 'updating'", ngShow: "project.status == 'updating'",
dataPlacement: 'top' dataPlacement: 'top'
}, },
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "deleteProject(\{\{ project.id \}\},'\{\{ project.name \}\}')", ngClick: "deleteProject(project.id, project.name)",
awToolTip: 'Permanently remove project from the database', awToolTip: 'Permanently remove project from the database',
ngShow: "project.status !== 'updating'", ngShow: "project.status !== 'updating'",
dataPlacement: 'top' dataPlacement: 'top'

View File

@@ -6,9 +6,11 @@
* *
* *
*/ */
'use strict';
angular.module('StreamListDefinition', []) angular.module('StreamListDefinition', [])
.value( .value('StreamList', {
'StreamList', {
name: 'activities', name: 'activities',
iterator: 'activity', iterator: 'activity',
@@ -238,7 +240,7 @@ angular.module('StreamListDefinition', [])
fieldActions: { fieldActions: {
view: { view: {
label: 'View', label: 'View',
ngClick: "showDetail(\{\{ activity.id \}\})", ngClick: "showDetail(activity.id)",
icon: 'fa-zoom-in', icon: 'fa-zoom-in',
"class": 'btn-default btn-xs', "class": 'btn-default btn-xs',
awToolTip: 'View event details', awToolTip: 'View event details',

View File

@@ -4,17 +4,19 @@
* Teams.js * Teams.js
* List view object for Team data model. * List view object for Team data model.
* *
*
*/ */
'use strict';
angular.module('TeamsListDefinition', []) angular.module('TeamsListDefinition', [])
.value( .value('TeamList', {
'TeamList', {
name: 'teams', name: 'teams',
iterator: 'team', iterator: 'team',
selectTitle: 'Add Team', selectTitle: 'Add Team',
editTitle: 'Teams', editTitle: 'Teams',
selectInstructions: 'Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new row.', selectInstructions: "Click on a row to select it, and click Finished when done. Use the green <i class=\"icon-plus\"></i> " +
"button to create a new row.",
index: true, index: true,
hover: true, hover: true,
@@ -50,7 +52,7 @@ angular.module('TeamsListDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "editTeam(\{\{ team.id \}\})", ngClick: "editTeam(team.id)",
icon: 'icon-edit', icon: 'icon-edit',
"class": 'btn-xs btn-default', "class": 'btn-xs btn-default',
awToolTip: 'Edit team', awToolTip: 'Edit team',
@@ -59,7 +61,7 @@ angular.module('TeamsListDefinition', [])
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "deleteTeam(\{\{ team.id \}\},'\{\{ team.name \}\}')", ngClick: "deleteTeam(team.id, team.name)",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-xs btn-danger', "class": 'btn-xs btn-danger',
awToolTip: 'Delete team', awToolTip: 'Delete team',

View File

@@ -4,11 +4,12 @@
* Users.js * Users.js
* List view object for Users data model. * List view object for Users data model.
* *
*
*/ */
'use strict';
angular.module('UserListDefinition', []) angular.module('UserListDefinition', [])
.value( .value('UserList', {
'UserList', {
name: 'users', name: 'users',
iterator: 'user', iterator: 'user',
@@ -52,7 +53,7 @@ angular.module('UserListDefinition', [])
fieldActions: { fieldActions: {
edit: { edit: {
label: 'Edit', label: 'Edit',
ngClick: "editUser(\{\{ user.id \}\})", ngClick: "editUser(user.id)",
icon: 'icon-edit', icon: 'icon-edit',
"class": 'btn-xs btn-default', "class": 'btn-xs btn-default',
awToolTip: 'Edit user', awToolTip: 'Edit user',
@@ -61,7 +62,7 @@ angular.module('UserListDefinition', [])
"delete": { "delete": {
label: 'Delete', label: 'Delete',
ngClick: "deleteUser(\{\{ user.id \}\},'\{\{ user.username \}\}')", ngClick: "deleteUser(user.id, user.username)",
icon: 'icon-trash', icon: 'icon-trash',
"class": 'btn-xs btn-danger', "class": 'btn-xs btn-danger',
awToolTip: 'Delete user', awToolTip: 'Delete user',

View File

@@ -10,15 +10,15 @@
'use strict'; 'use strict';
angular.module('InventorySyncStatusWidget', ['RestServices', 'Utilities']) angular.module('InventorySyncStatusWidget', ['RestServices', 'Utilities'])
.factory('InventorySyncStatus', ['$rootScope', '$compile', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait', 'GetChoices', .factory('InventorySyncStatus', ['$rootScope', '$compile', function ($rootScope, $compile) {
function($rootScope, $compile, Rest, GetBasePath, ProcessErrors, Wait, GetChoices) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var target = params.target; target = params.target,
var dashboard = params.dashboard; dashboard = params.dashboard,
html, group_total, group_fail, element, src;
var html = "<div class=\"panel panel-default\">\n"; html = "<div class=\"panel panel-default\">\n";
html += "<div class=\"panel-heading\">Inventory Sync Status</div>\n"; html += "<div class=\"panel-heading\">Inventory Sync Status</div>\n";
html += "<div class=\"panel-body\">\n"; html += "<div class=\"panel-body\">\n";
html += "<table class=\"table table-condensed table-hover\">\n"; html += "<table class=\"table table-condensed table-hover\">\n";
@@ -32,14 +32,14 @@ angular.module('InventorySyncStatusWidget', ['RestServices', 'Utilities'])
html += "<tbody>\n"; html += "<tbody>\n";
function makeRow(params) { function makeRow(params) {
var label = params.label; var label = params.label,
var count = params.count; count = params.count,
var fail = params.fail; fail = params.fail,
var link = params.link; link = params.link,
var fail_link = params.fail_link; fail_link = params.fail_link,
var html = "<tr>\n"; html = "<tr>\n";
html += "<td><a href=\"" + link + "\""; html += "<td><a href=\"" + link + "\"";
html += (label == 'Hosts' || label == 'Groups') ? " class=\"pad-left-sm\" " : ""; html += (label === 'Hosts' || label === 'Groups') ? " class=\"pad-left-sm\" " : "";
html += ">" + label + "</a></td>\n"; html += ">" + label + "</a></td>\n";
html += "<td class=\""; html += "<td class=\"";
html += (fail > 0) ? 'failed-column' : 'zero-column'; html += (fail > 0) ? 'failed-column' : 'zero-column';
@@ -52,7 +52,8 @@ angular.module('InventorySyncStatusWidget', ['RestServices', 'Utilities'])
return html; return html;
} }
html += makeRow({ label: 'Inventories', html += makeRow({
label: 'Inventories',
count: (dashboard.inventories && dashboard.inventories.total_with_inventory_source) ? count: (dashboard.inventories && dashboard.inventories.total_with_inventory_source) ?
dashboard.inventories.total_with_inventory_source : 0, dashboard.inventories.total_with_inventory_source : 0,
fail: (dashboard.inventories && dashboard.inventories.inventory_failed) ? dashboard.inventories.inventory_failed : 0, fail: (dashboard.inventories && dashboard.inventories.inventory_failed) ? dashboard.inventories.inventory_failed : 0,
@@ -60,16 +61,17 @@ angular.module('InventorySyncStatusWidget', ['RestServices', 'Utilities'])
fail_link: '/#/inventories/?inventory_sources_with_failures=true' fail_link: '/#/inventories/?inventory_sources_with_failures=true'
}); });
var group_total = 0; group_total = 0;
var group_fail = 0; group_fail = 0;
if (dashboard.inventory_sources) { if (dashboard.inventory_sources) {
for (var src in dashboard.inventory_sources) { for (src in dashboard.inventory_sources) {
group_total += (dashboard.inventory_sources[src].total) ? dashboard.inventory_sources[src].total : 0; group_total += (dashboard.inventory_sources[src].total) ? dashboard.inventory_sources[src].total : 0;
group_fail += (dashboard.inventory_sources[src].failed) ? dashboard.inventory_sources[src].failed : 0; group_fail += (dashboard.inventory_sources[src].failed) ? dashboard.inventory_sources[src].failed : 0;
} }
} }
html += makeRow({ label: 'Groups', html += makeRow({
label: 'Groups',
count: group_total, count: group_total,
fail: group_fail, fail: group_fail,
link: '/#/home/groups/?has_external_source=true', link: '/#/home/groups/?has_external_source=true',
@@ -77,9 +79,10 @@ angular.module('InventorySyncStatusWidget', ['RestServices', 'Utilities'])
}); });
// Each inventory source // Each inventory source
for (var src in dashboard.inventory_sources) { for (src in dashboard.inventory_sources) {
if (dashboard.inventory_sources[src].total) { if (dashboard.inventory_sources[src].total) {
html += makeRow({ label: dashboard.inventory_sources[src].label, html += makeRow({
label: dashboard.inventory_sources[src].label,
count: (dashboard.inventory_sources[src].total) ? dashboard.inventory_sources[src].total : 0, count: (dashboard.inventory_sources[src].total) ? dashboard.inventory_sources[src].total : 0,
fail: (dashboard.inventory_sources[src].failed) ? dashboard.inventory_sources[src].failed : 0, fail: (dashboard.inventory_sources[src].failed) ? dashboard.inventory_sources[src].failed : 0,
link: '/#/home/groups/?source=' + src, link: '/#/home/groups/?source=' + src,
@@ -94,10 +97,11 @@ angular.module('InventorySyncStatusWidget', ['RestServices', 'Utilities'])
html += "</div>\n"; html += "</div>\n";
html += "</div>\n"; html += "</div>\n";
var element = angular.element(document.getElementById(target)); element = angular.element(document.getElementById(target));
element.html(html); element.html(html);
$compile(element)(scope); $compile(element)(scope);
scope.$emit('WidgetLoaded'); scope.$emit('WidgetLoaded');
};
} }
}]); ]);

View File

@@ -11,15 +11,15 @@
angular.module('JobStatusWidget', ['RestServices', 'Utilities']) angular.module('JobStatusWidget', ['RestServices', 'Utilities'])
.factory('JobStatus', ['$rootScope', '$compile', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait', .factory('JobStatus', ['$rootScope', '$compile', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait',
function($rootScope, $compile, Rest, GetBasePath, ProcessErrors, Wait) { function ($rootScope, $compile) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var target = params.target; target = params.target,
var dashboard = params.dashboard; dashboard = params.dashboard,
html = '', element;
var html = ''; html = "<div class=\"panel panel-default\">\n";
var html = "<div class=\"panel panel-default\">\n";
html += "<div class=\"panel-heading\">Job Status</div>\n"; html += "<div class=\"panel-heading\">Job Status</div>\n";
html += "<div class=\"panel-body\">\n"; html += "<div class=\"panel-body\">\n";
html += "<table class=\"table table-condensed table-hover\">\n"; html += "<table class=\"table table-condensed table-hover\">\n";
@@ -33,22 +33,22 @@ angular.module('JobStatusWidget', ['RestServices', 'Utilities'])
html += "<tbody>\n"; html += "<tbody>\n";
function makeRow(params) { function makeRow(params) {
var html = ''; var html = '',
var label = params.label; label = params.label,
var link = params.link; link = params.link,
var fail_link = params.fail_link; fail_link = params.fail_link,
var count = params.count; count = params.count,
var fail = params.fail; fail = params.fail;
html += "<tr>\n"; html += "<tr>\n";
html += "<td><a href=\"" + link + "\""; html += "<td><a href=\"" + link + "\"";
html += (label == 'Hosts' || label == 'Groups') ? " class=\"pad-left-sm\" " : ""; html += (label === 'Hosts' || label === 'Groups') ? " class=\"pad-left-sm\" " : "";
html += ">" + label + "</a></td>\n"; html += ">" + label + "</a></td>\n";
html += "<td class=\""; html += "<td class=\"";
html += (fail > 0) ? 'failed-column' : 'zero-column'; html += (fail > 0) ? 'failed-column' : 'zero-column';
html += " text-right\">"; html += " text-right\">";
html += "<a href=\"" + fail_link + "\">" + fail + "</a>"; html += "<a href=\"" + fail_link + "\">" + fail + "</a>";
html += "</td>\n"; html += "</td>\n";
html += "<td class=\"text-right\">" html += "<td class=\"text-right\">";
html += "<a href=\"" + link + "\" >" + count + "</a>"; html += "<a href=\"" + link + "\" >" + count + "</a>";
html += "</td></tr>\n"; html += "</td></tr>\n";
return html; return html;
@@ -89,10 +89,11 @@ angular.module('JobStatusWidget', ['RestServices', 'Utilities'])
html += "</div>\n"; html += "</div>\n";
html += "</div>\n"; html += "</div>\n";
var element = angular.element(document.getElementById(target)); element = angular.element(document.getElementById(target));
element.html(html); element.html(html);
$compile(element)(scope); $compile(element)(scope);
scope.$emit('WidgetLoaded'); scope.$emit('WidgetLoaded');
};
} }
}]); ]);

View File

@@ -11,18 +11,18 @@
angular.module('ObjectCountWidget', ['RestServices', 'Utilities']) angular.module('ObjectCountWidget', ['RestServices', 'Utilities'])
.factory('ObjectCount', ['$rootScope', '$compile', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait', .factory('ObjectCount', ['$rootScope', '$compile', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait',
function($rootScope, $compile, Rest, GetBasePath, ProcessErrors, Wait) { function ($rootScope, $compile) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var target = params.target; target = params.target,
var dashboard = params.dashboard; dashboard = params.dashboard,
keys = ['organizations', 'users', 'teams', 'credentials', 'projects', 'inventories', 'groups', 'hosts',
'job_templates', 'jobs'
],
i, html, element;
html = "<div class=\"panel panel-default\">\n";
var keys=[ 'organizations', 'users', 'teams', 'credentials', 'projects', 'inventories', 'groups', 'hosts',
'job_templates', 'jobs' ];
var html = "<div class=\"panel panel-default\">\n";
html += "<div class=\"panel-heading\">System Summary</div>\n"; html += "<div class=\"panel-heading\">System Summary</div>\n";
html += "<div class=\"panel-body\">\n"; html += "<div class=\"panel-body\">\n";
html += "<table class=\"table table-condensed table-hover\">\n"; html += "<table class=\"table table-condensed table-hover\">\n";
@@ -35,24 +35,24 @@ angular.module('ObjectCountWidget', ['RestServices', 'Utilities'])
html += "<tbody>\n"; html += "<tbody>\n";
function makeRow(params) { function makeRow(params) {
var html = ''; var html = '',
var label = params.label; label = params.label,
var link = params.link; link = params.link,
var count = params.count; count = params.count;
html += "<tr>\n"; html += "<tr>\n";
html += "<td class=\"capitalize\"><a href=\"" + link + "\""; html += "<td class=\"capitalize\"><a href=\"" + link + "\"";
html += (label == 'hosts' || label == 'groups') ? " class=\"pad-left-sm\" " : ""; html += (label === 'hosts' || label === 'groups') ? " class=\"pad-left-sm\" " : "";
html += ">" + label.replace(/\_/g, ' ') + "</a></td>\n"; html += ">" + label.replace(/\_/g, ' ') + "</a></td>\n";
html += "<td class=\"text-right\">" html += "<td class=\"text-right\">";
html += "<a href=\"" + link + "\" >" + count + "</a>"; html += "<a href=\"" + link + "\" >" + count + "</a>";
html += "</td></tr>\n"; html += "</td></tr>\n";
return html; return html;
} }
for (var i=0; i < keys.length; i++) { for (i = 0; i < keys.length; i++) {
html += makeRow({ html += makeRow({
label: keys[i], label: keys[i],
link: '/#/' + ( (keys[i] == 'hosts' || keys[i] == 'groups') ? 'home/' + keys[i] : keys[i] ), link: '/#/' + ((keys[i] === 'hosts' || keys[i] === 'groups') ? 'home/' + keys[i] : keys[i]),
count: (dashboard[keys[i]] && dashboard[keys[i]].total) ? dashboard[keys[i]].total : 0 count: (dashboard[keys[i]] && dashboard[keys[i]].total) ? dashboard[keys[i]].total : 0
}); });
} }
@@ -60,11 +60,11 @@ angular.module('ObjectCountWidget', ['RestServices', 'Utilities'])
html += "</tbody>\n"; html += "</tbody>\n";
html += "</table>\n"; html += "</table>\n";
html += "</div>\n"; html += "</div>\n";
html += "</div>\n" html += "</div>\n";
var element = angular.element(document.getElementById(target)); element = angular.element(document.getElementById(target));
element.html(html); element.html(html);
$compile(element)(scope); $compile(element)(scope);
scope.$emit('WidgetLoaded'); scope.$emit('WidgetLoaded');
};
} }
}]); ]);

View File

@@ -6,19 +6,19 @@
* Dashboard widget showing object counts and license availability. * Dashboard widget showing object counts and license availability.
* *
*/ */
'use strict'; 'use strict';
angular.module('SCMSyncStatusWidget', ['RestServices', 'Utilities']) angular.module('SCMSyncStatusWidget', ['RestServices', 'Utilities'])
.factory('SCMSyncStatus', ['$rootScope', '$compile', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait', 'GetChoices', .factory('SCMSyncStatus', ['$rootScope', '$compile',
function($rootScope, $compile, Rest, GetBasePath, ProcessErrors, Wait, GetChoices) { function ($rootScope, $compile) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var target = params.target; target = params.target,
var dashboard = params.dashboard; dashboard = params.dashboard,
i, html, total_count, element, type, labelList;
var html = "<div class=\"panel panel-default\">\n"; html = "<div class=\"panel panel-default\">\n";
html += "<div class=\"panel-heading\">Project SCM Status</div>\n"; html += "<div class=\"panel-heading\">Project SCM Status</div>\n";
html += "<div class=\"panel-body\">\n"; html += "<div class=\"panel-body\">\n";
html += "<table class=\"table table-condensed table-hover\">\n"; html += "<table class=\"table table-condensed table-hover\">\n";
@@ -32,12 +32,12 @@ angular.module('SCMSyncStatusWidget', ['RestServices', 'Utilities'])
html += "<tbody>\n"; html += "<tbody>\n";
function makeRow(params) { function makeRow(params) {
var html = ''; var html = '',
var label = params.label; label = params.label,
var link = params.link; link = params.link,
var fail_link = params.fail_link; fail_link = params.fail_link,
var count = params.count; count = params.count,
var fail = params.fail; fail = params.fail;
html += "<tr>\n"; html += "<tr>\n";
html += "<td><a href=\"" + link + "\">" + label + "</a></td>\n"; html += "<td><a href=\"" + link + "\">" + label + "</a></td>\n";
html += "<td class=\""; html += "<td class=\"";
@@ -45,33 +45,33 @@ angular.module('SCMSyncStatusWidget', ['RestServices', 'Utilities'])
html += " text-right\">"; html += " text-right\">";
html += "<a href=\"" + fail_link + "\">" + fail + "</a>"; html += "<a href=\"" + fail_link + "\">" + fail + "</a>";
html += "</td>\n"; html += "</td>\n";
html += "<td class=\"text-right\">" html += "<td class=\"text-right\">";
html += "<a href=\"" + link + "\" >" + count + "</a>"; html += "<a href=\"" + link + "\" >" + count + "</a>";
html += "</td></tr>\n"; html += "</td></tr>\n";
return html; return html;
} }
var total_count = 0; total_count = 0;
if (dashboard.scm_types) { if (dashboard.scm_types) {
for (var type in dashboard.scm_types) { for (type in dashboard.scm_types) {
total_count += (dashboard.scm_types[type].total) ? dashboard.scm_types[type].total : 0; total_count += (dashboard.scm_types[type].total) ? dashboard.scm_types[type].total : 0;
} }
} }
html += makeRow({ label: 'Projects', html += makeRow({
label: 'Projects',
link: '/#/projects', link: '/#/projects',
count: total_count, count: total_count,
fail: (dashboard.projects && dashboard.projects.failed) ? dashboard.projects.failed : 0, fail: (dashboard.projects && dashboard.projects.failed) ? dashboard.projects.failed : 0,
fail_link: '/#/projects/?status=failed' fail_link: '/#/projects/?status=failed'
}); });
var labelList = []; labelList = [];
for (var type in dashboard.scm_types) { for (type in dashboard.scm_types) {
labelList.push(type); labelList.push(type);
} }
labelList.sort(); labelList.sort();
var type; for (i = 0; i < labelList.length; i++) {
for (var i=0; i < labelList.length; i++) {
type = labelList[i]; type = labelList[i];
if (dashboard.scm_types[type].total) { if (dashboard.scm_types[type].total) {
html += makeRow({ html += makeRow({
@@ -90,10 +90,11 @@ angular.module('SCMSyncStatusWidget', ['RestServices', 'Utilities'])
html += "</div>\n"; html += "</div>\n";
html += "</div>\n"; html += "</div>\n";
var element = angular.element(document.getElementById(target)); element = angular.element(document.getElementById(target));
element.html(html); element.html(html);
$compile(element)(scope); $compile(element)(scope);
scope.$emit('WidgetLoaded'); scope.$emit('WidgetLoaded');
};
} }
}]); ]);

View File

@@ -10,20 +10,26 @@
'use strict'; 'use strict';
angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefinition', 'SearchHelper', 'PaginationHelpers', angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefinition', 'SearchHelper', 'PaginationHelpers',
'RefreshHelper', 'ListGenerator', 'StreamWidget', 'AuthService']) 'RefreshHelper', 'ListGenerator', 'StreamWidget', 'AuthService'
])
.factory('setStreamHeight', [ function() { .factory('setStreamHeight', [
function () {
return function () { return function () {
// Try not to overlap footer. Because stream is positioned absolute, the parent // Try not to overlap footer. Because stream is positioned absolute, the parent
// doesn't resize correctly when stream is loaded. // doesn't resize correctly when stream is loaded.
var sheight = $('#stream-content').height(); var sheight = $('#stream-content').height(),
var theight = parseInt($('#tab-content-container').css('min-height').replace(/px/,'')); theight = parseInt($('#tab-content-container').css('min-height').replace(/px/, '')),
var height = (theight < sheight) ? sheight : theight; height = (theight < sheight) ? sheight : theight;
$('#tab-content-container').css({ "min-height": height }); $('#tab-content-container').css({
"min-height": height
});
};
} }
}]) ])
.factory('ShowStream', [ 'setStreamHeight', 'Authorization', function(setStreamHeight, Authorization) { .factory('ShowStream', ['setStreamHeight', 'Authorization',
function (setStreamHeight) {
return function () { return function () {
// Slide in the Stream widget // Slide in the Stream widget
@@ -41,17 +47,29 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
setStreamHeight(); setStreamHeight();
// Slide in stream // Slide in stream
stream.show('slide', {'direction': 'left'}, {'duration': 500, 'queue': false }); stream.show('slide', {
'direction': 'left'
}, {
'duration': 500,
'queue': false
});
};
} }
}]) ])
.factory('HideStream', [ 'LoadBreadCrumbs', function(LoadBreadCrumbs) { .factory('HideStream', ['LoadBreadCrumbs',
function (LoadBreadCrumbs) {
return function () { return function () {
// Remove the stream widget // Remove the stream widget
var stream = $('#stream-container'); var stream = $('#stream-container');
stream.hide('slide', {'direction': 'left'}, {'duration': 500, 'queue': false }); stream.hide('slide', {
'direction': 'left'
}, {
'duration': 500,
'queue': false
});
// Completely destroy the container so we don't experience random flashes of it later. // Completely destroy the container so we don't experience random flashes of it later.
// There was some sort of weirdness with the tab 'show' causing the stream to slide in when // There was some sort of weirdness with the tab 'show' causing the stream to slide in when
@@ -61,21 +79,24 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
stream.detach(); stream.detach();
stream.empty(); stream.empty();
stream.unbind(); stream.unbind();
$('#tab-content-container').css({ 'min-height': 0 }); //let the parent height go back to normal $('#tab-content-container').css({
'min-height': 0
}); //let the parent height go back to normal
}, 500); }, 500);
LoadBreadCrumbs(); LoadBreadCrumbs();
};
} }
}]) ])
.factory('StreamBreadCrumbs', ['$rootScope', '$location', function($rootScope, $location) { .factory('StreamBreadCrumbs', ['$rootScope', '$location',
function ($rootScope, $location) {
return function () { return function () {
// Load the breadcrumbs array. We have to do things a bit different than Utilities.LoadBreadcrumbs. // Load the breadcrumbs array. We have to do things a bit different than Utilities.LoadBreadcrumbs.
// Rather than botch that all up, we'll do our own thing here. // Rather than botch that all up, we'll do our own thing here.
$rootScope.breadcrumbs = []; $rootScope.breadcrumbs = [];
var paths = $location.path().split('/'); var path, title, i, j, paths = $location.path().split('/');
paths.splice(0, 1); paths.splice(0, 1);
var path, title, i, j;
for (i = 0; i < paths.length; i++) { for (i = 0; i < paths.length; i++) {
if (/^\d+/.test(paths[i])) { if (/^\d+/.test(paths[i])) {
path = ''; path = '';
@@ -84,7 +105,7 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
path += '/' + paths[j]; path += '/' + paths[j];
} }
for (j = 0; j < $rootScope.crumbCache.length; j++) { for (j = 0; j < $rootScope.crumbCache.length; j++) {
if ($rootScope.crumbCache[j].path == path) { if ($rootScope.crumbCache[j].path === path) {
title = $rootScope.crumbCache[j].title; title = $rootScope.crumbCache[j].title;
break; break;
} }
@@ -92,35 +113,41 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
if (!title) { if (!title) {
title = paths[i - 1].substr(0, paths[i - 1].length - 1); title = paths[i - 1].substr(0, paths[i - 1].length - 1);
title = title.charAt(0).toUpperCase() + title.slice(1); title = title.charAt(0).toUpperCase() + title.slice(1);
title = (title == 'Inventorie') ? 'Inventory' : title; title = (title === 'Inventorie') ? 'Inventory' : title;
} }
} } else {
else {
path = ''; path = '';
title = ''; title = '';
if (i > 0) { if (i > 0) {
for (j = 0; j <= i; j++) { for (j = 0; j <= i; j++) {
path += '/' + paths[j]; path += '/' + paths[j];
} }
} } else {
else {
path = '/' + paths[i]; path = '/' + paths[i];
} }
title = paths[i]; title = paths[i];
title = title.charAt(0).toUpperCase() + title.slice(1); title = title.charAt(0).toUpperCase() + title.slice(1);
} }
$rootScope.breadcrumbs.push({ path: path, title: title, ngClick: "closeStream('" + path + "')" }); $rootScope.breadcrumbs.push({
path: path,
title: title,
ngClick: "closeStream('" + path + "')"
});
} }
};
} }
}]) ])
.factory('FixUrl', [ function() { .factory('FixUrl', [
function () {
return function (u) { return function (u) {
return u.replace(/\/api\/v1\//, '/#/'); return u.replace(/\/api\/v1\//, '/#/');
};
} }
}]) ])
.factory('BuildUrl', [ function() { .factory('BuildUrl', [
function () {
return function (obj) { return function (obj) {
var url = '/#/'; var url = '/#/';
switch (obj.base) { switch (obj.base) {
@@ -135,146 +162,137 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
url += obj.base + 's/' + obj.id + '/'; url += obj.base + 's/' + obj.id + '/';
} }
return url; return url;
};
} }
}]) ])
.factory('BuildDescription', ['FixUrl', 'BuildUrl', function(FixUrl, BuildUrl) { .factory('BuildDescription', ['FixUrl', 'BuildUrl',
function (FixUrl, BuildUrl) {
return function (activity) { return function (activity) {
function stripDeleted(s) { function stripDeleted(s) {
return s.replace(/^_deleted_\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+\+\d+:\d+_/, ''); return s.replace(/^_deleted_\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+\+\d+:\d+_/, '');
} }
var descr = ''; var descr, descr_nolink, obj1, obj2, obj1_obj, obj2_obj, name, name_nolink;
var descr_nolink;
descr += activity.operation; descr = activity.operation;
descr += (/e$/.test(activity.operation)) ? 'd ' : 'ed '; descr += (/e$/.test(activity.operation)) ? 'd ' : 'ed ';
descr_nolink = descr; descr_nolink = descr;
// labels // labels
var obj1 = activity.object1; obj1 = activity.object1;
var obj2 = activity.object2; obj2 = activity.object2;
// objects // objects
var obj1_obj = (activity.summary_fields[obj1]) ? activity.summary_fields[obj1][0] : null; obj1_obj = (activity.summary_fields[obj1]) ? activity.summary_fields[obj1][0] : null;
if (obj1 == obj2) { if (obj1 === obj2) {
var obj2_obj = activity.summary_fields[obj1][1]; obj2_obj = activity.summary_fields[obj1][1];
} } else if (activity.summary_fields[obj2]) {
else if (activity.summary_fields[obj2]) { obj2_obj = activity.summary_fields[obj2][0];
var obj2_obj = activity.summary_fields[obj2][0]; } else {
} obj2_obj = null;
else {
var obj2_obj = null;
} }
if (obj1 == 'user' || obj2 == 'user') { if (obj1 === 'user' || obj2 === 'user') {
activity.summary_fields['user'][0].name = activity.summary_fields['user'][0].username; activity.summary_fields.user[0].name = activity.summary_fields.user[0].username;
} }
var name;
if (obj2_obj && obj2_obj.name && !/^_delete/.test(obj2_obj.name)) { if (obj2_obj && obj2_obj.name && !/^_delete/.test(obj2_obj.name)) {
obj2_obj['base'] = obj2; obj2_obj.base = obj2;
descr += obj2 + ' <a href=\"' + BuildUrl(obj2_obj) + '\">' descr += obj2 + ' <a href=\"' + BuildUrl(obj2_obj) + '\">' + obj2_obj.name + '</a>' + ((activity.operation === 'disassociate') ? ' from ' : ' to ');
+ obj2_obj.name + '</a>' + ( (activity.operation == 'disassociate') ? ' from ' : ' to ' ); descr_nolink += obj2 + ' ' + obj2_obj.name + ((activity.operation === 'disassociate') ? ' from ' : ' to ');
descr_nolink += obj2 + ' ' + obj2_obj.name + ( (activity.operation == 'disassociate') ? ' from ' : ' to ' ); } else if (obj2) {
}
else if (obj2) {
name = ''; name = '';
if (obj2_obj && obj2_obj.name) { if (obj2_obj && obj2_obj.name) {
name = ' ' + stripDeleted(obj2_obj.name); name = ' ' + stripDeleted(obj2_obj.name);
} }
descr += obj2 + name + ( (activity.operation == 'disassociate') ? ' from ' : ' to ' ); descr += obj2 + name + ((activity.operation === 'disassociate') ? ' from ' : ' to ');
descr_nolink += obj2 + name + ( (activity.operation == 'disassociate') ? ' from ' : ' to ' ); descr_nolink += obj2 + name + ((activity.operation === 'disassociate') ? ' from ' : ' to ');
} }
if (obj1_obj && obj1_obj.name && !/^\_delete/.test(obj1_obj.name)) { if (obj1_obj && obj1_obj.name && !/^\_delete/.test(obj1_obj.name)) {
obj1_obj['base'] = obj1; obj1_obj.base = obj1;
descr += obj1 + ' <a href=\"' + BuildUrl(obj1_obj) + '\">' + obj1_obj.name + '</a>'; descr += obj1 + ' <a href=\"' + BuildUrl(obj1_obj) + '\">' + obj1_obj.name + '</a>';
descr_nolink += obj1 + ' ' + obj1_obj.name; descr_nolink += obj1 + ' ' + obj1_obj.name;
} } else if (obj1) {
else if (obj1) {
name = ''; name = '';
var name_nolink = ''; name_nolink = '';
// find the name in changes, if needed // find the name in changes, if needed
if (!(obj1_obj && obj1_obj.name) || obj1_obj && obj1_obj.name && /^_delete/.test(obj1_obj.name)) { if (!(obj1_obj && obj1_obj.name) || obj1_obj && obj1_obj.name && /^_delete/.test(obj1_obj.name)) {
if (activity.changes && activity.changes.name) { if (activity.changes && activity.changes.name) {
if (typeof activity.changes.name == 'string') { if (typeof activity.changes.name === 'string') {
name = ' ' + activity.changes.name; name = ' ' + activity.changes.name;
name_nolink = name; name_nolink = name;
} } else if (typeof activity.changes.name === 'object' && Array.isArray(activity.changes.name)) {
else if (typeof activity.changes.name == 'object' && Array.isArray(activity.changes.name)) {
name = ' ' + activity.changes.name[0]; name = ' ' + activity.changes.name[0];
name_nolink = name; name_nolink = name;
} }
} } else if (obj1 === 'job' && obj1_obj && activity.changes && activity.changes.job_template) {
else if (obj1 == 'job' && obj1_obj && activity.changes && activity.changes.job_template) {
// Hack for job activity where the template name is known // Hack for job activity where the template name is known
if (activity.operation != 'delete') { if (activity.operation !== 'delete') {
obj1_obj['base'] = obj1; obj1_obj.base = obj1;
name = ' ' + '<a href=\"' + BuildUrl(obj1_obj) + '\">' + obj1_obj.id + ' ' + activity.changes.job_template + '</a>'; name = ' ' + '<a href=\"' + BuildUrl(obj1_obj) + '\">' + obj1_obj.id + ' ' + activity.changes.job_template + '</a>';
name_nolink = ' ' + obj1_obj.id + ' ' + activity.changes.job_template; name_nolink = ' ' + obj1_obj.id + ' ' + activity.changes.job_template;
} } else {
else {
name = ' ' + obj1_obj.id + ' ' + activity.changes.job_template; name = ' ' + obj1_obj.id + ' ' + activity.changes.job_template;
name_nolink = name; name_nolink = name;
} }
} } else if (obj1 === 'job' && obj1_obj) {
else if (obj1 == 'job' && obj1_obj) {
// Hack for job activity where template name not known // Hack for job activity where template name not known
if (activity.operation != 'delete') { if (activity.operation !== 'delete') {
obj1_obj['base'] = obj1; obj1_obj.base = obj1;
name = ' ' + '<a href=\"' + BuildUrl(obj1_obj) + '\">' + obj1_obj.id + '</a>'; name = ' ' + '<a href=\"' + BuildUrl(obj1_obj) + '\">' + obj1_obj.id + '</a>';
name_nolink = ' ' + obj1_obj.id; name_nolink = ' ' + obj1_obj.id;
} } else {
else {
name = ' ' + obj1_obj.id; name = ' ' + obj1_obj.id;
name_nolink = name; name_nolink = name;
} }
} }
} } else if (obj1_obj && obj1_obj.name) {
else if (obj1_obj && obj1_obj.name) {
name = ' ' + stripDeleted(obj1_obj.name); name = ' ' + stripDeleted(obj1_obj.name);
name_nolink = name; name_nolink = name;
} }
descr += obj1 + name; descr += obj1 + name;
descr_nolink += obj1 + name_nolink; descr_nolink += obj1 + name_nolink;
} }
activity['description'] = descr; activity.description = descr;
activity['description_nolink'] = descr_nolink; activity.description_nolink = descr_nolink;
};
} }
}]) ])
.factory('ShowDetail', ['$rootScope', 'Rest', 'Alert', 'GenerateForm', 'ProcessErrors', 'GetBasePath', 'FormatDate', .factory('ShowDetail', ['$rootScope', 'Rest', 'Alert', 'GenerateForm', 'ProcessErrors', 'GetBasePath', 'FormatDate',
'ActivityDetailForm', 'Empty', 'Find', 'ActivityDetailForm', 'Empty', 'Find',
function ($rootScope, Rest, Alert, GenerateForm, ProcessErrors, GetBasePath, FormatDate, ActivityDetailForm, Empty, Find) { function ($rootScope, Rest, Alert, GenerateForm, ProcessErrors, GetBasePath, FormatDate, ActivityDetailForm, Empty, Find) {
return function (params) { return function (params) {
var activity_id = params.activity_id; var activity_id = params.activity_id,
var parent_scope = params.scope; parent_scope = params.scope,
generator = GenerateForm,
var generator = GenerateForm; form = ActivityDetailForm,
var form = ActivityDetailForm; activity = Find({ list: parent_scope.activities, key: 'id', val: activity_id }),
var activity = Find({list: parent_scope.activities, key: 'id', val: activity_id }); n, rows, scope;
if (activity) { if (activity) {
// Setup changes field // Setup changes field
activity['changes_stringified'] = JSON.stringify(activity['changes'], null, '\t'); activity.changes_stringified = JSON.stringify(activity.changes, null, '\t');
var n = activity['changes_stringified'].match(/\n/g); n = activity.changes_stringified.match(/\n/g);
var rows = (n) ? n.length : 1; rows = (n) ? n.length : 1;
rows = (rows < 1) ? 3 : 10; rows = (rows < 1) ? 3 : 10;
form.fields['changes'].rows = 10; form.fields.changes.rows = 10;
// Load the form // Load the form
var scope = generator.inject(form, { mode: 'edit', modal: true, related: false }); scope = generator.inject(form, { mode: 'edit', modal: true, related: false });
scope['changes'] = activity['changes_stringified']; scope.changes = activity.changes_stringified;
scope['user'] = ( (activity.summary_fields.actor) ? activity.summary_fields.actor.username : 'system' ) + scope.user = ((activity.summary_fields.actor) ? activity.summary_fields.actor.username : 'system') +
' on ' + FormatDate(new Date(activity['timestamp'])); ' on ' + FormatDate(new Date(activity.timestamps));
scope['operation'] = activity['description_nolink']; scope.operation = activity.description_nolink;
scope.formModalAction = function () { scope.formModalAction = function () {
$('#form-modal').modal("hide"); $('#form-modal').modal("hide");
} };
$('#form-modal').on('show.bs.modal', function (e) { $('#form-modal').on('show.bs.modal', function () {
$('#form-modal-body').css({ $('#form-modal-body').css({
width: 'auto', //probably not needed width: 'auto', //probably not needed
height: 'auto', //probably not needed height: 'auto', //probably not needed
@@ -291,9 +309,9 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
scope.$digest(); scope.$digest();
} }
} }
};
} }
}]) ])
.factory('Stream', ['$rootScope', '$location', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait', 'StreamList', 'SearchInit', .factory('Stream', ['$rootScope', '$location', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait', 'StreamList', 'SearchInit',
'PaginateInit', 'GenerateList', 'FormatDate', 'ShowStream', 'HideStream', 'BuildDescription', 'FixUrl', 'BuildUrl', 'PaginateInit', 'GenerateList', 'FormatDate', 'ShowStream', 'HideStream', 'BuildDescription', 'FixUrl', 'BuildUrl',
@@ -303,44 +321,36 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
Find, Store) { Find, Store) {
return function (params) { return function (params) {
var list = StreamList; var list = StreamList,
var defaultUrl = GetBasePath('activity_stream'); defaultUrl = GetBasePath('activity_stream'),
var view = GenerateList; view = GenerateList,
var base = $location.path().replace(/^\//,'').split('/')[0]; base = $location.path().replace(/^\//, '').split('/')[0],
var parent_scope = params.scope; parent_scope = params.scope,
PreviousSearchParams = Store('CurrentSearchParams'),
// Hang onto current search params inventory_name = (params && params.inventory_name) ? params.inventory_name : null,
var PreviousSearchParams = Store('CurrentSearchParams'); url = (params && params.url) ? params.url : null,
type, paths, itm, scope;
// pass in an inventory name to fix breadcrumb display
var inventory_name = (params && params.inventory_name) ? params.inventory_name : null;
// url will override the attempt to compute an activity_stream query
var url = (params && params.url) ? params.url : null;
$rootScope.flashMessage = null; $rootScope.flashMessage = null;
if (url) { if (url) {
defaultUrl = url; defaultUrl = url;
} } else {
else {
if ($location.path() !== '/home') { if ($location.path() !== '/home') {
// Restrict what we're looking at based on the path // Restrict what we're looking at based on the path
var type = (base == 'inventories') ? 'inventory' : base.replace(/s$/,''); type = (base === 'inventories') ? 'inventory' : base.replace(/s$/, '');
var paths = $location.path().split('/'); paths = $location.path().split('/');
paths.splice(0, 1); paths.splice(0, 1);
if (paths.length > 1 && /^\d+/.test(paths[paths.length - 1])) { if (paths.length > 1 && /^\d+/.test(paths[paths.length - 1])) {
type = paths[paths.length - 2]; type = paths[paths.length - 2];
type = (type == 'inventories') ? 'inventory' : type.replace(/s$/,''); type = (type === 'inventories') ? 'inventory' : type.replace(/s$/, '');
//defaultUrl += '?object1=' + type + '&object1__id=' + //defaultUrl += '?object1=' + type + '&object1__id=' +
defaultUrl += '?' + type + '__id=' + paths[paths.length - 1]; defaultUrl += '?' + type + '__id=' + paths[paths.length - 1];
} } else if (paths.length > 1) {
else if (paths.length > 1) {
type = paths[paths.length - 1]; type = paths[paths.length - 1];
type = (type == 'inventories') ? 'inventory' : type.replace(/s$/,''); type = (type === 'inventories') ? 'inventory' : type.replace(/s$/, '');
defaultUrl += '?or__object1=' + type + '&or__object2=' + type; defaultUrl += '?or__object1=' + type + '&or__object2=' + type;
} } else {
else {
defaultUrl += '?or__object1=' + type + '&or__object2=' + type; defaultUrl += '?or__object1=' + type + '&or__object2=' + type;
} }
} }
@@ -353,7 +363,7 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
// Fix inventory name. The way we're doing breadcrumbs doesn't support bind variables. // Fix inventory name. The way we're doing breadcrumbs doesn't support bind variables.
if (inventory_name) { if (inventory_name) {
var itm = Find({ list: $rootScope.breadcrumbs, key: 'title', val: '{{ inventory_name }}' }); itm = Find({ list: $rootScope.breadcrumbs, key: 'title', val: '{{ inventory_name }}' });
if (itm) { if (itm) {
itm.title = inventory_name; itm.title = inventory_name;
} }
@@ -362,13 +372,7 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
ShowStream(); ShowStream();
// Generate the list // Generate the list
var scope = view.inject(list, { scope = view.inject(list, { mode: 'edit', id: 'stream-content', searchSize: 'col-lg-3', secondWidget: true, activityStream: true });
mode: 'edit',
id: 'stream-content',
searchSize: 'col-lg-3',
secondWidget: true,
activityStream: true
});
// descriptive title describing what AS is showing // descriptive title describing what AS is showing
scope.streamTitle = (params && params.title) ? params.title : null; scope.streamTitle = (params && params.title) ? params.title : null;
@@ -387,80 +391,89 @@ angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefiniti
url: PreviousSearchParams.defaultUrl, url: PreviousSearchParams.defaultUrl,
iterator: PreviousSearchParams.iterator, iterator: PreviousSearchParams.iterator,
sort_order: PreviousSearchParams.sort_order, sort_order: PreviousSearchParams.sort_order,
setWidgets: false }); setWidgets: false
});
} }
if (inUrl) { if (inUrl) {
$location.path(inUrl); $location.path(inUrl);
} }
} };
scope.refreshStream = function () { scope.refreshStream = function () {
scope.search(list.iterator); scope.search(list.iterator);
} };
scope.showDetail = function (id) { scope.showDetail = function (id) {
ShowDetail({ scope: scope, activity_id: id }); ShowDetail({
} scope: scope,
activity_id: id
});
};
if (scope.removeStreamPostRefresh) { if (scope.removeStreamPostRefresh) {
scope.removeStreamPostRefresh(); scope.removeStreamPostRefresh();
} }
scope.removeStreamPostRefresh = scope.$on('PostRefresh', function () { scope.removeStreamPostRefresh = scope.$on('PostRefresh', function () {
var cDate, href, deleted, obj1, obj2; var i, cDate, href, deleted, obj1, obj2;
for (var i=0; i < scope['activities'].length; i++) { for (i = 0; i < scope.activities.length; i++) {
// Convert event_time date to local time zone // Convert event_time date to local time zone
cDate = new Date(scope['activities'][i].timestamp); cDate = new Date(scope.activities[i].timestamp);
scope['activities'][i].timestamp = FormatDate(cDate); scope.activities[i].timestamp = FormatDate(cDate);
if (scope['activities'][i]['summary_fields']['actor']) { if (scope.activities[i].summary_fields.actor) {
scope['activities'][i]['user'] = "<a href=\"/#/users/" + scope['activities'][i]['summary_fields']['actor']['id'] + "\">" + scope.activities[i].user = "<a href=\"/#/users/" + scope.activities[i].summary_fields.actor.id + "\">" +
scope['activities'][i]['summary_fields']['actor']['username'] + "</a>"; scope.activities[i].summary_fields.actor.username + "</a>";
} } else {
else { scope.activities[i].user = 'system';
scope['activities'][i]['user'] = 'system';
} }
// Objects // Objects
deleted = /^\_delete/; deleted = /^\_delete/;
obj1 = scope['activities'][i].object1; obj1 = scope.activities[i].object1;
obj2 = scope['activities'][i].object2; obj2 = scope.activities[i].object2;
if ( obj1 && scope['activities'][i].summary_fields[obj1] && scope['activities'][i].summary_fields[obj1].name) { if (obj1 && scope.activities[i].summary_fields[obj1] && scope.activities[i].summary_fields[obj1].name) {
if ( !deleted.test(scope['activities'][i].summary_fields[obj1].name) ) { if (!deleted.test(scope.activities[i].summary_fields[obj1].name)) {
href = BuildUrl(scope['activities'][i].summary_fields.object1); href = BuildUrl(scope.activities[i].summary_fields.object1);
scope['activities'][i].objects = "<a href=\"" + href + "\">" + scope['activities'][i].summary_fields[obj1].name + "</a>"; scope.activities[i].objects = "<a href=\"" + href + "\">" + scope.activities[i].summary_fields[obj1].name + "</a>";
} else {
scope.activities[i].objects = scope.activities[i].summary_fields[obj1].name;
} }
else { } else if (scope.activities[i].object1) {
scope['activities'][i].objects = scope['activities'][i].summary_fields[obj1].name; scope.activities[i].objects = scope.activities[i].object1;
} }
if (obj2 && scope.activities[i].summary_fields[obj2] && scope.activities[i].summary_fields[obj2].name) {
if (!deleted.test(scope.activities[i].summary_fields.object2.name)) {
href = BuildUrl(scope.activities[i].summary_fields.object2);
scope.activities[i].objects += ", <a href=\"" + href + "\">" + scope.activities[i].summary_fields[obj2].name + "</a>";
} else {
scope.activities[i].objects += "," + scope.activities[i].summary_fields[obj2].name;
} }
else if (scope['activities'][i].object1) { } else if (scope.activities[i].object2) {
scope['activities'][i].objects = scope['activities'][i].object1; scope.activities[i].objects += ", " + scope.activities[i].object2;
}
if (obj2 && scope['activities'][i].summary_fields[obj2] && scope['activities'][i].summary_fields[obj2].name) {
if ( !deleted.test(scope['activities'][i].summary_fields.object2.name) ) {
href = BuildUrl(scope['activities'][i].summary_fields.object2);
scope['activities'][i].objects += ", <a href=\"" + href + "\">" + scope['activities'][i].summary_fields[obj2].name + "</a>";
}
else {
scope['activities'][i].objects += "," + scope['activities'][i].summary_fields[obj2].name;
}
}
else if (scope['activities'][i].object2) {
scope['activities'][i].objects += ", " + scope['activities'][i].object2;
} }
BuildDescription(scope['activities'][i]); BuildDescription(scope.activities[i]);
} }
// Give ng-repeate a chance to show the data before adjusting the page size. // Give ng-repeate a chance to show the data before adjusting the page size.
setTimeout(function() { setStreamHeight(); }, 500); setTimeout(function () {
setStreamHeight();
}, 500);
}); });
// Initialize search and paginate pieces and load data // Initialize search and paginate pieces and load data
SearchInit({ scope: scope, set: list.name, list: list, url: defaultUrl }); SearchInit({
PaginateInit({ scope: scope, list: list, url: defaultUrl }); scope: scope,
set: list.name,
list: list,
url: defaultUrl
});
PaginateInit({
scope: scope,
list: list,
url: defaultUrl
});
scope.search(list.iterator); scope.search(list.iterator);
};
} }
}]); ]);

View File

@@ -4,6 +4,7 @@
* AuthService.js * AuthService.js
* *
* User authentication functions * User authentication functions
*
*/ */
'use strict'; 'use strict';
@@ -42,8 +43,14 @@ function($http, $rootScope, $location, $cookieStore, GetBasePath) {
}, },
retrieveToken: function (username, password) { retrieveToken: function (username, password) {
return $http({ method: 'POST', url: GetBasePath('authtoken'), return $http({
data: {"username": username, "password": password} }); method: 'POST',
url: GetBasePath('authtoken'),
data: {
"username": username,
"password": password
}
});
}, },
logout: function () { logout: function () {
@@ -73,7 +80,9 @@ function($http, $rootScope, $location, $cookieStore, GetBasePath) {
return $http({ return $http({
method: 'GET', method: 'GET',
url: GetBasePath('config'), url: GetBasePath('config'),
headers: { 'Authorization': 'Token ' + this.getToken() } headers: {
'Authorization': 'Token ' + this.getToken()
}
}); });
}, },
@@ -86,13 +95,11 @@ function($http, $rootScope, $location, $cookieStore, GetBasePath) {
var license, result; var license, result;
if ($rootScope.license_tested !== undefined) { if ($rootScope.license_tested !== undefined) {
result = $rootScope.license_tested; result = $rootScope.license_tested;
} } else {
else {
license = $cookieStore.get('license'); license = $cookieStore.get('license');
if (license && license.tested !== undefined) { if (license && license.tested !== undefined) {
result = license.tested; result = license.tested;
} } else {
else {
result = false; result = false;
} }
} }
@@ -103,7 +110,9 @@ function($http, $rootScope, $location, $cookieStore, GetBasePath) {
return $http({ return $http({
method: 'GET', method: 'GET',
url: '/api/v1/me/', url: '/api/v1/me/',
headers: { 'Authorization': 'Token ' + this.getToken() } headers: {
'Authorization': 'Token ' + this.getToken()
}
}); });
}, },
@@ -128,5 +137,5 @@ function($http, $rootScope, $location, $cookieStore, GetBasePath) {
return cu[key]; return cu[key];
} }
}; };
}]); }
]);

View File

@@ -1,4 +1,3 @@
/************************************ /************************************
* *
* Copyright (c) 2014 AnsibleWorks, Inc. * Copyright (c) 2014 AnsibleWorks, Inc.
@@ -13,74 +12,92 @@
angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'PromptDialog']) angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'PromptDialog'])
.factory('SortNodes', [ function() { .factory('SortNodes', [
function () {
return function (data) { return function (data) {
//Sort nodes by name //Sort nodes by name
var names = []; var i, j, names = [], newData = [];
var newData = []; for (i = 0; i < data.length; i++) {
for (var i=0; i < data.length; i++) {
names.push(data[i].name); names.push(data[i].name);
} }
names.sort(); names.sort();
for (var j=0; j < names.length; j++) { for (j = 0; j < names.length; j++) {
for (i = 0; i < data.length; i++) { for (i = 0; i < data.length; i++) {
if (data[i].name == names[j]) { if (data[i].name === names[j]) {
newData.push(data[i]); newData.push(data[i]);
} }
} }
} }
return newData; return newData;
};
} }
}]) ])
.factory('BuildTree', ['Rest', 'GetBasePath', 'ProcessErrors', 'SortNodes', 'Wait', 'GetSyncStatusMsg', 'GetHostsStatusMsg', .factory('BuildTree', ['Rest', 'GetBasePath', 'ProcessErrors', 'SortNodes', 'Wait', 'GetSyncStatusMsg', 'GetHostsStatusMsg',
function (Rest, GetBasePath, ProcessErrors, SortNodes, Wait, GetSyncStatusMsg, GetHostsStatusMsg) { function (Rest, GetBasePath, ProcessErrors, SortNodes, Wait, GetSyncStatusMsg, GetHostsStatusMsg) {
return function (params) { return function (params) {
var inventory_id = params.inventory_id; var inventory_id = params.inventory_id,
var scope = params.scope; scope = params.scope,
var refresh = params.refresh; refresh = params.refresh,
var emit = params.emit; emit = params.emit,
var new_group_id = params.new_group_id; new_group_id = params.new_group_id,
var groups = []; groups = [],
var id = 1; id = 1;
function buildAllHosts(tree_data) { function buildAllHosts(tree_data) {
// Start our tree object with All Hosts // Start our tree object with All Hosts
var children = []; var children = [],
var sorted = SortNodes(tree_data); sorted = SortNodes(tree_data),
for (var j=0; j < sorted.length; j++) { j, all_hosts;
for (j = 0; j < sorted.length; j++) {
children.push(sorted[j].id); children.push(sorted[j].id);
} }
var all_hosts = {
name: 'All Hosts', id: 1, group_id: null, parent: 0, description: '', show: true, ngicon: null, all_hosts = {
has_children: false, related: {}, selected_class: '', show_failures: false, isDraggable: false, name: 'All Hosts',
isDroppable: true, children: children }; id: 1,
group_id: null,
parent: 0,
description: '',
show: true,
ngicon: null,
has_children: false,
related: {},
selected_class: '',
show_failures: false,
isDraggable: false,
isDroppable: true,
children: children
};
groups.push(all_hosts); groups.push(all_hosts);
} }
function buildGroups(tree_data, parent, level) { function buildGroups(tree_data, parent, level) {
var sorted = SortNodes(tree_data);
for (var i=0; i < sorted.length; i++) {
id++;
var stat = GetSyncStatusMsg({ var i, j, children, stat, hosts_status, group,
sorted = SortNodes(tree_data);
for (i = 0; i < sorted.length; i++) {
id++;
stat = GetSyncStatusMsg({
status: sorted[i].summary_fields.inventory_source.status status: sorted[i].summary_fields.inventory_source.status
}); // from helpers/Groups.js }); // from helpers/Groups.js
var hosts_status = GetHostsStatusMsg({ hosts_status = GetHostsStatusMsg({
active_failures: sorted[i].hosts_with_active_failures, active_failures: sorted[i].hosts_with_active_failures,
total_hosts: sorted[i].total_hosts, total_hosts: sorted[i].total_hosts,
inventory_id: inventory_id, inventory_id: inventory_id,
group_id: sorted[i].id group_id: sorted[i].id
}); // from helpers/Groups.js }); // from helpers/Groups.js
var children = []; children = [];
for (var j=0; j < sorted[i].children.length; j++) { for (j = 0; j < sorted[i].children.length; j++) {
children.push(sorted[i].children[j].id); children.push(sorted[i].children[j].id);
} }
var group = { group = {
name: sorted[i].name, name: sorted[i].name,
has_active_failures: sorted[i].has_active_failures, has_active_failures: sorted[i].has_active_failures,
total_hosts: sorted[i].total_hosts, total_hosts: sorted[i].total_hosts,
@@ -103,19 +120,19 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
}, },
status: sorted[i].summary_fields.inventory_source.status, status: sorted[i].summary_fields.inventory_source.status,
status_class: stat['class'], status_class: stat['class'],
status_tooltip: stat['tooltip'], status_tooltip: stat.tooltip,
launch_tooltip: stat['launch_tip'], launch_tooltip: stat.launch_tip,
launch_class: stat['launch_class'], launch_class: stat.launch_class,
hosts_status_tip: hosts_status['tooltip'], hosts_status_tip: hosts_status.tooltip,
show_failures: hosts_status['failures'], show_failures: hosts_status.failures,
hosts_status_class: hosts_status['class'], hosts_status_class: hosts_status['class'],
selected_class: '', selected_class: '',
show: true, show: true,
isDraggable: true, isDraggable: true,
isDroppable: true isDroppable: true
} };
groups.push(group); groups.push(group);
if (new_group_id && group.group_id == new_group_id) { if (new_group_id && group.group_id === new_group_id) {
// For new group // For new group
scope.selected_tree_id = id; scope.selected_tree_id = id;
scope.selected_group_id = group.group_id; scope.selected_group_id = group.group_id;
@@ -133,22 +150,23 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
scope.buildAllGroupsRemove = scope.$on('buildAllGroups', function (e, inventory_name, inventory_tree) { scope.buildAllGroupsRemove = scope.$on('buildAllGroups', function (e, inventory_name, inventory_tree) {
Rest.setUrl(inventory_tree); Rest.setUrl(inventory_tree);
Rest.get() Rest.get()
.success( function(data, status, headers, config) { .success(function (data) {
buildAllHosts(data); buildAllHosts(data);
buildGroups(data, 0, 0); buildGroups(data, 0, 0);
scope.autoShowGroupHelp = (data.length == 0) ? true : false; scope.autoShowGroupHelp = (data.length === 0) ? true : false;
if (refresh) { if (refresh) {
scope.groups = groups; scope.groups = groups;
scope.$emit('GroupTreeRefreshed', inventory_name, groups, emit); scope.$emit('GroupTreeRefreshed', inventory_name, groups, emit);
} } else {
else {
scope.$emit('GroupTreeLoaded', inventory_name, groups, emit); scope.$emit('GroupTreeLoaded', inventory_name, groups, emit);
} }
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
Wait('stop'); Wait('stop');
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, {
{ hdr: 'Error!', msg: 'Failed to get inventory tree for: ' + inventory_id + '. GET returned: ' + status }); hdr: 'Error!',
msg: 'Failed to get inventory tree for: ' + inventory_id + '. GET returned: ' + status
});
}); });
}); });
@@ -158,19 +176,22 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
Wait('start'); Wait('start');
Rest.setUrl(GetBasePath('inventory') + inventory_id + '/'); Rest.setUrl(GetBasePath('inventory') + inventory_id + '/');
Rest.get() Rest.get()
.success( function(data, status, headers, config) { .success(function (data) {
scope.$emit('buildAllGroups', data.name, data.related.tree, data.related.groups); scope.$emit('buildAllGroups', data.name, data.related.tree, data.related.groups);
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
Wait('stop'); Wait('stop');
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, {
{ hdr: 'Error!', msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status }); hdr: 'Error!',
msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status
});
}); });
} }
loadTreeData(); loadTreeData();
};
} }
}]) ])
// Update a group with a set of properties // Update a group with a set of properties
@@ -178,14 +199,14 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
function (ApplyEllipsis, GetSyncStatusMsg, Empty) { function (ApplyEllipsis, GetSyncStatusMsg, Empty) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var group_id = params.group_id; group_id = params.group_id,
var properties = params.properties; // object of key:value pairs to update properties = params.properties,
var old_name, stat; i, p, grp, old_name, stat;
for (var i=0; i < scope.groups.length; i++) { for (i = 0; i < scope.groups.length; i++) {
if (scope.groups[i].group_id === group_id) { if (scope.groups[i].group_id === group_id) {
var grp = scope.groups[i]; grp = scope.groups[i];
for (var p in properties) { for (p in properties) {
if (p === 'name') { if (p === 'name') {
old_name = scope.groups[i].name; old_name = scope.groups[i].name;
} }
@@ -195,13 +216,14 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
if (!Empty(properties[p]) && (scope.groups[i].status === 'none' || Empty(scope.groups[i].status))) { if (!Empty(properties[p]) && (scope.groups[i].status === 'none' || Empty(scope.groups[i].status))) {
// We have a source but no status, seed the status with 'never' to enable sync button // We have a source but no status, seed the status with 'never' to enable sync button
scope.groups[i].status = 'never updated'; scope.groups[i].status = 'never updated';
} } else if (!properties[p]) {
else if (!properties[p]) {
// User removed source // User removed source
scope.groups[i].status = 'none'; scope.groups[i].status = 'none';
} }
// Update date sync status links/icons // Update date sync status links/icons
stat = GetSyncStatusMsg({ status: scope.groups[i].status }); stat = GetSyncStatusMsg({
status: scope.groups[i].status
});
scope.groups[i].status_class = stat['class']; scope.groups[i].status_class = stat['class'];
scope.groups[i].status_tooltip = stat.tooltip; scope.groups[i].status_tooltip = stat.tooltip;
scope.groups[i].launch_tooltip = stat.launch_tip; scope.groups[i].launch_tooltip = stat.launch_tip;
@@ -211,7 +233,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
scope.groups[i][p] = properties[p]; scope.groups[i][p] = properties[p];
} }
} }
if (scope.groups[i].id == scope.selected_tree_id) { if (scope.groups[i].id === scope.selected_tree_id) {
//Make sure potential group name change gets reflected throughout the page //Make sure potential group name change gets reflected throughout the page
scope.selected_group_name = scope.groups[i].name; scope.selected_group_name = scope.groups[i].name;
scope.search_place_holder = 'Search ' + scope.groups[i].name; scope.search_place_holder = 'Search ' + scope.groups[i].name;
@@ -227,21 +249,22 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
}, 2500); }, 2500);
} }
};
} }
}]) ])
// Set node name and description after an update to Group properties. // Set node name and description after an update to Group properties.
.factory('SetNodeName', [ function() { .factory('SetNodeName', [
function () {
return function (params) { return function (params) {
var scope = params.scope; var name = params.name,
var name = params.name; descr = params.description,
var descr = params.description; group_id = (params.group_id !== undefined) ? params.group_id : null,
var group_id = (params.group_id !== undefined) ? params.group_id : null; inventory_id = (params.inventory_id !== undefined) ? params.inventory_id : null;
var inventory_id = (params.inventory_id != undefined) ? params.inventory_id : null;
if (group_id !== null) { if (group_id !== null) {
$('#inventory-tree').find('li [data-group-id="' + group_id + '"]').each(function(idx) { $('#inventory-tree').find('li [data-group-id="' + group_id + '"]').each(function () {
$(this).attr('data-name', name); $(this).attr('data-name', name);
$(this).attr('data-description', descr); $(this).attr('data-description', descr);
$(this).find('.activate').first().text(name); $(this).find('.activate').first().text(name);
@@ -251,8 +274,9 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
if (inventory_id !== null) { if (inventory_id !== null) {
$('#inventory-root-node').attr('data-name', name).attr('data-description', descr).find('.activate').first().text(name); $('#inventory-root-node').attr('data-name', name).attr('data-description', descr).find('.activate').first().text(name);
} }
};
} }
}]) ])
// Copy or Move a group on the tree after drag-n-drop // Copy or Move a group on the tree after drag-n-drop
@@ -260,12 +284,12 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
function ($compile, Alert, ProcessErrors, Find, Wait, Rest, Empty, GetBasePath) { function ($compile, Alert, ProcessErrors, Find, Wait, Rest, Empty, GetBasePath) {
return function (params) { return function (params) {
var scope = params.scope; var scope = params.scope,
var target = Find({ list: scope.groups, key: 'id', val: params.target_tree_id }); target = Find({ list: scope.groups, key: 'id', val: params.target_tree_id }),
var inbound = Find({ list: scope.groups, key: 'id', val: params.inbound_tree_id }); inbound = Find({ list: scope.groups, key: 'id', val: params.inbound_tree_id }),
e, html = '';
// Build the html for our prompt dialog // Build the html for our prompt dialog
var html = '';
html += "<div id=\"copy-prompt-modal\" class=\"modal fade\">\n"; html += "<div id=\"copy-prompt-modal\" class=\"modal fade\">\n";
html += "<div class=\"modal-dialog\">\n"; html += "<div class=\"modal-dialog\">\n";
html += "<div class=\"modal-content\">\n"; html += "<div class=\"modal-content\">\n";
@@ -273,25 +297,22 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
html += "<button type=\"button\" class=\"close\" data-target=\"#copy-prompt-modal\" " + html += "<button type=\"button\" class=\"close\" data-target=\"#copy-prompt-modal\" " +
"data-dismiss=\"modal\" aria-hidden=\"true\">&times;</button>\n"; "data-dismiss=\"modal\" aria-hidden=\"true\">&times;</button>\n";
if (target.id == 1 || inbound.parent == 0) { if (target.id === 1 || inbound.parent === 0) {
// We're moving the group to the top level, or we're moving a top level group down // We're moving the group to the top level, or we're moving a top level group down
html += "<h3>Move Group</h3>\n"; html += "<h3>Move Group</h3>\n";
} } else {
else {
html += "<h3>Copy or Move?</h3>\n"; html += "<h3>Copy or Move?</h3>\n";
} }
html += "</div>\n"; html += "</div>\n";
html += "<div class=\"modal-body\">\n"; html += "<div class=\"modal-body\">\n";
if (target.id == 1) { if (target.id === 1) {
html += "<p>Are you sure you want to move group " + inbound.name + " to the top level?</p>"; html += "<p>Are you sure you want to move group " + inbound.name + " to the top level?</p>";
} } else if (inbound.parent === 0) {
else if (inbound.parent == 0) {
html += "<p>Are you sure you want to move group " + inbound.name + " from the top level and make it a child of " + html += "<p>Are you sure you want to move group " + inbound.name + " from the top level and make it a child of " +
target.name + "?</p>"; target.name + "?</p>";
} } else {
else {
html += "<div class=\"text-center\">\n"; html += "<div class=\"text-center\">\n";
html += "<p>Would you like to copy or move group <em>" + inbound.name + "</em> to group <em>" + target.name + "</em>?</p>\n"; html += "<p>Would you like to copy or move group <em>" + inbound.name + "</em> to group <em>" + target.name + "</em>?</p>\n";
html += "<div style=\"margin-top: 30px;\">\n"; html += "<div style=\"margin-top: 30px;\">\n";
@@ -305,7 +326,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
html += "<div class=\"modal-footer\">\n"; html += "<div class=\"modal-footer\">\n";
html += "<a href=\"#\" data-target=\"#prompt-modal\" data-dismiss=\"modal\" class=\"btn btn-default\">Cancel</a>\n"; html += "<a href=\"#\" data-target=\"#prompt-modal\" data-dismiss=\"modal\" class=\"btn btn-default\">Cancel</a>\n";
if (target.id == 1 || inbound.parent == 0) { if (target.id === 1 || inbound.parent === 0) {
// We're moving the group to the top level, or we're moving a top level group down // We're moving the group to the top level, or we're moving a top level group down
html += "<a href=\"\" data-target=\"#prompt-modal\" ng-click=\"moveGroup()\" class=\"btn btn-primary\">Yes</a>\n"; html += "<a href=\"\" data-target=\"#prompt-modal\" ng-click=\"moveGroup()\" class=\"btn btn-primary\">Yes</a>\n";
} }
@@ -316,7 +337,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
html += "</div><!-- modal -->\n"; html += "</div><!-- modal -->\n";
// Inject our custom dialog // Inject our custom dialog
var e = angular.element(document.getElementById('inventory-modal-container')); e= angular.element(document.getElementById('inventory-modal-container'));
e.empty().append(html); e.empty().append(html);
$compile(e)(scope); $compile(e)(scope);
@@ -329,7 +350,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
// Respond to move // Respond to move
scope.moveGroup = function () { scope.moveGroup = function () {
var url, group, parent;
$('#copy-prompt-modal').modal('hide'); $('#copy-prompt-modal').modal('hide');
Wait('start'); Wait('start');
@@ -340,50 +361,50 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
scope.removeGroupRemove = scope.$on('removeGroup', function () { scope.removeGroupRemove = scope.$on('removeGroup', function () {
if (inbound.parent > 0) { if (inbound.parent > 0) {
// Only remove a group from a parent when the parent is a group and not the inventory root // Only remove a group from a parent when the parent is a group and not the inventory root
var parent = Find({ list: scope.groups, key: 'id', val: inbound.parent }) parent = Find({ list: scope.groups, key: 'id', val: inbound.parent });
var url = GetBasePath('base') + 'groups/' + parent.group_id + '/children/'; url = GetBasePath('base') + 'groups/' + parent.group_id + '/children/';
Rest.setUrl(url); Rest.setUrl(url);
Rest.post({ id: inbound.group_id, disassociate: 1 }) Rest.post({ id: inbound.group_id, disassociate: 1 })
.success( function(data, status, headers, config) { .success(function () {
//Triggers refresh of group list in inventory controller //Triggers refresh of group list in inventory controller
scope.$emit('GroupDeleteCompleted'); scope.$emit('GroupDeleteCompleted');
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
Wait('stop'); Wait('stop');
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, {
{ hdr: 'Error!', msg: 'Failed to remove ' + inbound.name + hdr: 'Error!',
' from ' + parent.name + '. POST returned status: ' + status }); msg: 'Failed to remove ' + inbound.name +
' from ' + parent.name + '. POST returned status: ' + status
}); });
} });
else { } else {
//Triggers refresh of group list in inventory controller //Triggers refresh of group list in inventory controller
scope.$emit('GroupDeleteCompleted'); scope.$emit('GroupDeleteCompleted');
} }
}); });
// add the new group to the target parent // add the new group to the target parent
var url = (!Empty(target.group_id)) ? url = (!Empty(target.group_id)) ?
GetBasePath('base') + 'groups/' + target.group_id + '/children/' : GetBasePath('base') + 'groups/' + target.group_id + '/children/' :
GetBasePath('inventory') + scope.inventory_id + '/groups/'; GetBasePath('inventory') + scope.inventory_id + '/groups/';
var group = { group = {
id: inbound.group_id, id: inbound.group_id,
name: inbound.name, name: inbound.name,
description: inbound.description, description: inbound.description,
inventory: scope.inventory_id inventory: scope.inventory_id
} };
Rest.setUrl(url); Rest.setUrl(url);
Rest.post(group) Rest.post(group)
.success( function(data, status, headers, config) { .success(function () {
scope.$emit('removeGroup'); scope.$emit('removeGroup');
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
var target_name = (Empty(target.group_id)) ? 'inventory' : target.name; var target_name = (Empty(target.group_id)) ? 'inventory' : target.name;
Wait('stop'); Wait('stop');
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, { hdr: 'Error!',
{ hdr: 'Error!', msg: 'Failed to add ' + node.attr('name') + ' to ' + msg: 'Failed to add ' + inbound.name + ' to ' + target_name + '. POST returned status: ' + status });
target_name + '. POST returned status: ' + status });
}); });
} };
scope.copyGroup = function () { scope.copyGroup = function () {
@@ -392,30 +413,32 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
// add the new group to the target parent // add the new group to the target parent
var url = (!Empty(target.group_id)) ? var url = (!Empty(target.group_id)) ?
GetBasePath('base') + 'groups/' + target.group_id + '/children/' : GetBasePath('base') + 'groups/' + target.group_id + '/children/' :
GetBasePath('inventory') + scope.inventory_id + '/groups/'; GetBasePath('inventory') + scope.inventory_id + '/groups/',
var group = { group = {
id: inbound.group_id, id: inbound.group_id,
name: inbound.name, name: inbound.name,
description: inbound.description, description: inbound.description,
inventory: scope.inventory_id inventory: scope.inventory_id
} };
Rest.setUrl(url); Rest.setUrl(url);
Rest.post(group) Rest.post(group)
.success( function(data, status, headers, config) { .success(function () {
//Triggers refresh of group list in inventory controller //Triggers refresh of group list in inventory controller
scope.$emit('GroupDeleteCompleted'); scope.$emit('GroupDeleteCompleted');
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
var target_name = (Empty(target.group_id)) ? 'inventory' : target.name; var target_name = (Empty(target.group_id)) ? 'inventory' : target.name;
Wait('stop'); Wait('stop');
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, { hdr: 'Error!',
{ hdr: 'Error!', msg: 'Failed to add ' + inbound.name + ' to ' + msg: 'Failed to add ' + inbound.name + ' to ' + target_name + '. POST returned status: ' + status
target_name + '. POST returned status: ' + status });
}); });
} });
};
};
} }
}]) ])
// Copy a host after drag-n-drop // Copy a host after drag-n-drop
.factory('CopyMoveHost', ['$compile', 'Alert', 'ProcessErrors', 'Find', 'Wait', 'Rest', 'Empty', 'GetBasePath', .factory('CopyMoveHost', ['$compile', 'Alert', 'ProcessErrors', 'Find', 'Wait', 'Rest', 'Empty', 'GetBasePath',
@@ -425,18 +448,17 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
var scope = params.scope, var scope = params.scope,
target = Find({ list: scope.groups, key: 'id', val: params.target_tree_id }), target = Find({ list: scope.groups, key: 'id', val: params.target_tree_id }),
host = Find({ list: scope.hosts, key: 'id', val: params.host_id }), host = Find({ list: scope.hosts, key: 'id', val: params.host_id }),
found = false, i; found = false, e, i, html = '';
if (host.summary_fields.all_groups) { if (host.summary_fields.all_groups) {
for (i = 0; i < host.summary_fields.all_groups.length; i++) { for (i = 0; i < host.summary_fields.all_groups.length; i++) {
if (host.summary_fields.all_groups[i].id == target.group_id) { if (host.summary_fields.all_groups[i].id === target.group_id) {
found = true; found = true;
break; break;
} }
} }
} }
if (found) { if (found) {
var html = '';
html += "<div id=\"copy-alert-modal\" class=\"modal fade\">\n"; html += "<div id=\"copy-alert-modal\" class=\"modal fade\">\n";
html += "<div class=\"modal-dialog\">\n"; html += "<div class=\"modal-dialog\">\n";
html += "<div class=\"modal-content\">\n"; html += "<div class=\"modal-content\">\n";
@@ -456,7 +478,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
html += "</div>\n"; html += "</div>\n";
// Inject our custom dialog // Inject our custom dialog
var e = angular.element(document.getElementById('inventory-modal-container')); e = angular.element(document.getElementById('inventory-modal-container'));
e.empty().append(html); e.empty().append(html);
$compile(e)(scope); $compile(e)(scope);
@@ -467,10 +489,9 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
show: true show: true
}); });
} } else {
else {
// Build the html for our prompt dialog // Build the html for our prompt dialog
var html = ''; html = '';
html += "<div id=\"copy-prompt-modal\" class=\"modal fade\">\n"; html += "<div id=\"copy-prompt-modal\" class=\"modal fade\">\n";
html += "<div class=\"modal-dialog\">\n"; html += "<div class=\"modal-dialog\">\n";
html += "<div class=\"modal-content\">\n"; html += "<div class=\"modal-content\">\n";
@@ -491,7 +512,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
html += "</div><!-- modal -->\n"; html += "</div><!-- modal -->\n";
// Inject our custom dialog // Inject our custom dialog
var e = angular.element(document.getElementById('inventory-modal-container')); e = angular.element(document.getElementById('inventory-modal-container'));
e.empty().append(html); e.empty().append(html);
$compile(e)(scope); $compile(e)(scope);
@@ -507,17 +528,17 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
Wait('start'); Wait('start');
Rest.setUrl(GetBasePath('groups') + target.group_id + '/hosts/'); Rest.setUrl(GetBasePath('groups') + target.group_id + '/hosts/');
Rest.post(host) Rest.post(host)
.success(function(data, status, headers, config) { .success(function () {
// Signal the controller to refresh the hosts view // Signal the controller to refresh the hosts view
scope.$emit('GroupTreeRefreshed'); scope.$emit('GroupTreeRefreshed');
}) })
.error(function(data, status, headers, config) { .error(function (data, status) {
Wait('stop'); Wait('stop');
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to add ' + host.name + ' to ' +
{ hdr: 'Error!', msg: 'Failed to add ' + host.name + ' to ' +
target.name + '. POST returned status: ' + status }); target.name + '. POST returned status: ' + status });
}); });
};
} }
};
} }
} ]);
}]);

View File

@@ -4,7 +4,6 @@
* Generic accessor for Ansible Commander services * Generic accessor for Ansible Commander services
* *
*/ */
'use strict'; 'use strict';
angular.module('RestServices', ['ngCookies', 'AuthService']) angular.module('RestServices', ['ngCookies', 'AuthService'])
@@ -36,13 +35,20 @@ function($http, $rootScope, $cookieStore, $q, Authorization) {
// Simulate an http response when a token error occurs // Simulate an http response when a token error occurs
// http://stackoverflow.com/questions/18243286/angularjs-promises-simulate-http-promises // http://stackoverflow.com/questions/18243286/angularjs-promises-simulate-http-promises
var promise = $q.reject({ data: data, status: status }); var promise = $q.reject({
data: data,
status: status
});
promise.success = function (fn) { promise.success = function (fn) {
promise.then(function(response){ fn(response.data, response.status) }, null); promise.then(function (response) {
return promise fn(response.data, response.status);
}, null);
return promise;
}; };
promise.error = function (fn) { promise.error = function (fn) {
promise.then(null, function(response){ fn(response.data, response.status) }); promise.then(null, function (response) {
fn(response.data, response.status);
});
return promise; return promise;
}; };
return promise; return promise;
@@ -58,100 +64,134 @@ function($http, $rootScope, $cookieStore, $q, Authorization) {
args = (args) ? args : {}; args = (args) ? args : {};
this.params = (args.params) ? args.params : null; this.params = (args.params) ? args.params : null;
this.pReplace(); this.pReplace();
var expired = this.checkExpired(); var expired = this.checkExpired(),
var token = Authorization.getToken(); token = Authorization.getToken();
if (expired) { if (expired) {
return this.createResponse({ detail: 'Token is expired' }, 401); return this.createResponse({
} detail: 'Token is expired'
else if (token) { }, 401);
this.setHeader({ Authorization: 'Token ' + token }); } else if (token) {
this.setHeader({ "X-Auth-Token": 'Token ' + token }); this.setHeader({
return $http({method: 'GET', Authorization: 'Token ' + token
});
this.setHeader({
"X-Auth-Token": 'Token ' + token
});
return $http({
method: 'GET',
url: this.url, url: this.url,
headers: this.headers, headers: this.headers,
params: this.params params: this.params
}); });
} } else {
else { return this.createResponse({
return this.createResponse({ detail: 'Invalid token' }, 401); detail: 'Invalid token'
}, 401);
} }
}, },
post: function (data) { post: function (data) {
var token = Authorization.getToken(); var token = Authorization.getToken(),
var expired = this.checkExpired(); expired = this.checkExpired();
if (expired) { if (expired) {
return this.createResponse({ detail: 'Token is expired' }, 401); return this.createResponse({
} detail: 'Token is expired'
else if (token) { }, 401);
this.setHeader({ Authorization: 'Token ' + token }); } else if (token) {
this.setHeader({ "X-Auth-Token": 'Token ' + token }); this.setHeader({
Authorization: 'Token ' + token
});
this.setHeader({
"X-Auth-Token": 'Token ' + token
});
return $http({ return $http({
method: 'POST', method: 'POST',
url: this.url, url: this.url,
headers: this.headers, headers: this.headers,
data: data }); data: data
} });
else { } else {
return this.createResponse({ detail: 'Invalid token' }, 401); return this.createResponse({
detail: 'Invalid token'
}, 401);
} }
}, },
put: function (data) { put: function (data) {
var token = Authorization.getToken(); var token = Authorization.getToken(),
var expired = this.checkExpired(); expired = this.checkExpired();
if (expired) { if (expired) {
return this.createResponse({ detail: 'Token is expired' }, 401); return this.createResponse({
} detail: 'Token is expired'
else if (token) { }, 401);
this.setHeader({ Authorization: 'Token ' + token }); } else if (token) {
this.setHeader({ "X-Auth-Token": 'Token ' + token }); this.setHeader({
Authorization: 'Token ' + token
});
this.setHeader({
"X-Auth-Token": 'Token ' + token
});
return $http({ return $http({
method: 'PUT', method: 'PUT',
url: this.url, url: this.url,
headers: this.headers, headers: this.headers,
data: data }); data: data
} });
else { } else {
return this.createResponse({ detail: 'Invalid token' }, 401); return this.createResponse({
detail: 'Invalid token'
}, 401);
} }
}, },
destroy: function (data) { destroy: function (data) {
var token = Authorization.getToken(); var token = Authorization.getToken(),
var expired = this.checkExpired(); expired = this.checkExpired();
if (expired) { if (expired) {
return this.createResponse({ detail: 'Token is expired' }, 401); return this.createResponse({
} detail: 'Token is expired'
else if (token) { }, 401);
this.setHeader({ Authorization: 'Token ' + token }); } else if (token) {
this.setHeader({ "X-Auth-Token": 'Token ' + token }); this.setHeader({
Authorization: 'Token ' + token
});
this.setHeader({
"X-Auth-Token": 'Token ' + token
});
return $http({ return $http({
method: 'DELETE', method: 'DELETE',
url: this.url, url: this.url,
headers: this.headers, headers: this.headers,
data: data }); data: data
} });
else { } else {
return this.createResponse({ detail: 'Invalid token' }, 401); return this.createResponse({
detail: 'Invalid token'
}, 401);
} }
}, },
options: function () { options: function () {
var token = Authorization.getToken(); var token = Authorization.getToken(),
var expired = this.checkExpired(); expired = this.checkExpired();
if (expired) { if (expired) {
return this.createResponse({ detail: 'Token is expired' }, 401); return this.createResponse({
} detail: 'Token is expired'
else if (token) { }, 401);
this.setHeader({ Authorization: 'Token ' + token }); } else if (token) {
this.setHeader({ "X-Auth-Token": 'Token ' + token }); this.setHeader({
Authorization: 'Token ' + token
});
this.setHeader({
"X-Auth-Token": 'Token ' + token
});
return $http({ return $http({
method: 'OPTIONS', method: 'OPTIONS',
url: this.url, url: this.url,
headers: this.headers headers: this.headers
}); });
} } else {
else { return this.createResponse({
return this.createResponse({ detail: 'Invalid token' }, 401); detail: 'Invalid token'
}, 401);
} }
} }
};
} }
}]); ]);

View File

@@ -7,12 +7,11 @@
* duration set in config.js * duration set in config.js
* *
*/ */
'use strict'; 'use strict';
angular.module('TimerService', ['ngCookies', 'Utilities']) angular.module('TimerService', ['ngCookies', 'Utilities'])
.factory('Timer', ['$rootScope', '$cookieStore', '$location', 'GetBasePath', 'Empty', .factory('Timer', ['$rootScope', '$cookieStore', '$location', 'GetBasePath', 'Empty',
function($rootScope, $cookieStore, $location, GetBasePath, Empty) { function ($rootScope, $cookieStore) {
return { return {
sessionTime: null, sessionTime: null,
@@ -23,13 +22,12 @@ angular.module('TimerService', ['ngCookies', 'Utilities'])
}, },
isExpired: function () { isExpired: function () {
var stime = this.getSessionTime(); var stime = this.getSessionTime(),
var now = new Date().getTime(); now = new Date().getTime();
if ((stime - now) <= 0) { if ((stime - now) <= 0) {
//expired //expired
return true; return true;
} } else {
else {
// not expired. move timer forward. // not expired. move timer forward.
this.moveForward(); this.moveForward();
return false; return false;
@@ -54,5 +52,6 @@ angular.module('TimerService', ['ngCookies', 'Utilities'])
this.moveForward(); this.moveForward();
return this; return this;
} }
};
} }
}]); ]);

View File

@@ -1,693 +0,0 @@
/************************************
*
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* TreeSelector.js
*
*/
angular.module('TreeSelector', ['Utilities', 'RestServices', 'TreeSelector', 'GroupsHelper'])
.factory('SortNodes', [ function() {
return function(data) {
//Sort nodes by name
var names = [];
var newData = [];
for (var i=0; i < data.length; i++) {
names.push(data[i].name);
}
names.sort();
for (var j=0; j < names.length; j++) {
for (i=0; i < data.length; i++) {
if (data[i].name == names[j]) {
newData.push(data[i]);
}
}
}
return newData;
}
}])
// Figure out the group level tool tip
.factory('GetToolTip', [ 'FormatDate', function(FormatDate) {
return function(params) {
var node = params.node;
var tip = '';
var link = '';
var html_class = '';
var active_failures = node.hosts_with_active_failures;
var total_hosts = node.total_hosts;
var source = node.summary_fields.inventory_source.source;
var status = node.summary_fields.inventory_source.status;
// Return values for the status indicator
var status_date = node.summary_fields.inventory_source.last_updated
var last_update = ( status_date == "" || status_date == null ) ? null : FormatDate(new Date(status_date));
switch (status) {
case 'never updated':
html_class = 'na';
tip = '<p>Inventory update has not been performed.</p>';
link = '';
break;
case 'failed':
tip = '<p>Inventory update failed! Click to view process output.</p>';
link = '/#/inventories/' + node.inventory + '/groups?name=' + node.name;
html_class = true;
break;
case 'successful':
tip = '<p>Inventory update completed on ' + last_update + '.</p>';
html_class = false;
link = '';
break;
case 'updating':
tip = '<p>Inventory update process running now. Click to view status.</p>';
link = '/#/inventories/' + node.inventory + '/groups?name=' + node.name;
html_class = false;
break;
}
if (status !== 'failed' && status !== 'updating') {
// update status will not override job status
if (active_failures > 0) {
tip += "<p>Contains " + active_failures +
[ (active_failures == 1) ? ' host' : ' hosts' ] + ' with failed jobs. Click to view the offending ' +
[ (active_failures == 1) ? ' host' : ' hosts' ] + '.</p>';
link = '/#/inventories/' + node.inventory + '/hosts?has_active_failures=true';
html_class = 'true';
}
else {
if (total_hosts == 0) {
// no hosts
tip += "<p>There are no hosts in this group. It's a sad empty shell.</p>";
html_class = (html_class == '') ? 'na' : html_class;
}
else if (total_hosts == 1) {
// on host with 0 failures
tip += "<p>The 1 host in this group is happy! It does not have a job failure.</p>";
html_class = 'false';
}
else {
// many hosts with 0 failures
tip += "<p>All " + total_hosts + " hosts in this group are happy! None of them have " +
" job failures.</p>";
html_class = 'false';
}
}
}
return { tooltip: tip, url: link, 'class': html_class };
}
}])
.factory('GetInventoryToolTip', [ 'FormatDate', function(FormatDate) {
return function(params) {
var node = params.node;
var tip = '';
var link = '';
var html_class = '';
var active_failures = node.hosts_with_active_failures;
var total_hosts = node.total_hosts;
var group_failures = node.groups_with_active_failures;
var total_groups = node.total_groups;
var inventory_sources = node.total_inventory_sources;
if (group_failures > 0) {
tip += "Has " + group_failures +
[ (group_failures == 1) ? ' group' : ' groups' ] + ' with failed inventory updates. ' +
'Click to view the offending ' +
[ (group_failures == 1) ? ' group.' : ' groups.' ];
link = '/#/inventories/' + node.id + '/groups?status=failed';
html_class = 'true';
}
else if (inventory_sources == 1) {
// on host with 0 failures
tip += "<p>1 group with an inventory source is happy! No updates have failed.</p>";
link = '';
html_class = 'false';
}
else if (inventory_sources > 0) {
tip += "<p>" + inventory_sources + " groups with an inventory source are happy! No updates have failed.</p>";
link = 0;
html_class = 'false';
}
if (html_class !== 'true') {
// Add job status
if (active_failures > 0) {
tip += "<p>Contains " + scope.inventories[i].hosts_with_active_failures +
[ (active_failures == 1) ? ' host' : ' hosts' ] + ' with job failures. Click to view the offending ' +
[ (active_failures == 1) ? ' host' : ' hosts' ] + '.</p>';
link = '/#/inventories/' + node.id + '/hosts?has_active_failures=true';
html_class = 'true';
}
else if (total_hosts == 0) {
tip += "<p>There are no hosts in this inventory. It's a sad empty shell.</p>";
link = "";
html_class = (html_class == '') ? 'na' : html_class;
}
else if (total_hosts == 1) {
tip += "<p>The 1 host found in this inventory is happy! There are no job failures.</p>";
link = "";
html_class = "false";
}
else if (total_hosts > 0) {
tip += "<p>All " + total_hosts + " hosts are happy! There are no job failures.";
link = "";
html_class = "false";
}
}
return { tooltip: tip, url: link, 'class': html_class };
}
}])
.factory('BuildTree', ['Rest', 'GetBasePath', 'ProcessErrors', '$compile', '$rootScope', 'Wait', 'SortNodes', 'GetToolTip',
'GetInventoryToolTip',
function(Rest, GetBasePath, ProcessErrors, $compile, $rootScope, Wait, SortNodes, GetToolTip, GetInventoryToolTip) {
return function(params) {
var scope = params.scope;
var inventory_id = params.inventory_id;
var emit_on_select = params.emit_on_select;
var target_id = params.target_id;
var refresh_tree = (params.refresh == undefined || params.refresh == false) ? false : true;
var moveable = (params.moveable == undefined || params.moveable == false) ? false : true;
var group_id = params.group_id;
var id = params.id;
var html = '';
var toolTip = 'Hosts have failed jobs?';
var idx = 0;
function refresh(parent) {
var group, title;
var id = parent.attr('id');
if (parent.attr('data-group-id')) {
group = parent.attr('data-group-id');
title = parent.attr('data-name');
}
else {
group = null;
title = 'All Hosts'
}
// The following will trigger the host list to load. See Inventory.js controller.
scope.$emit(emit_on_select, id, group, title);
}
function activate(e) {
/* Set the clicked node as active */
var elm = angular.element(e.target); //<a>
var parent = angular.element(e.target.parentNode.parentNode); //<li>
$('.search-tree .active').removeClass('active');
elm.parent().addClass('active'); // add active class to <div>
refresh(parent);
}
function toggle(e) {
var id, parent, elm, icon;
if (e.target.tagName == 'I') {
id = e.target.parentNode.parentNode.parentNode.attributes.id.value;
parent = angular.element(e.target.parentNode.parentNode.parentNode); //<li>
elm = angular.element(e.target.parentNode); // <a>
}
else {
id = e.target.parentNode.parentNode.attributes.id.value;
parent = angular.element(e.target.parentNode.parentNode);
elm = angular.element(e.target);
}
var sibling = angular.element(parent.children()[2]); // <a>
var state = parent.attr('data-state');
var icon = angular.element(elm.children()[0]);
if (state == 'closed') {
// expand the elment
var childlists = parent.find('ul');
if (childlists && childlists.length > 0) {
// has childen
for (var i=0; i < childlists.length; i++) {
var listChild = angular.element(childlists[i]);
var listParent = angular.element(listChild.parent());
if (listParent.attr('id') == id) {
angular.element(childlists[i]).removeClass('hidden');
}
}
}
parent.attr('data-state','open');
icon.removeClass('icon-caret-right').addClass('icon-caret-down');
}
else {
// close the element
parent.attr('data-state','closed');
icon.removeClass('icon-caret-down').addClass('icon-caret-right');
var childlists = parent.find('ul');
var sublist, subicon;
if (childlists && childlists.length > 0) {
// has childen
childlists.each(function(idx) {
$(this).addClass('hidden');
subicon = $(this).find('li').first().find('.expand-container i');
subicon.removeClass('icon-caret-down').addClass('icon-caret-right');
});
}
/* When the active node's parent is closed, activate the parent */
if ($(parent).find('.active').length > 0) {
$(parent).find('.active').removeClass('active');
sibling.addClass('active');
refresh(parent);
}
}
}
if (scope.moveNodeRemove) {
scope.moveNodeRemove();
}
scope.moveNodeRemove = scope.$on('MoveNode', function(e, node, parent, target) {
var inv_id = scope['inventory_id'];
var variables;
function cleanUp(state) {
/*
if (state !== 'fail') {
// Visually move the element. Elment will be appended to the
// end of target element list
var elm = $('#' + node.attr('id')).detach();
if (target.find('ul').length > 0) {
// parent has children
target.find('ul').first().append(elm);
}
else {
target.append('<ul></ul>');
target.find('ul').first().append(elm);
}
// Remove any styling that might be left on the target
// and put the expander icon back the way it should be
target.find('div').each(function(idx) {
if (idx > 0 && idx < 3) {
$(this).css({ 'border-bottom': '2px solid #f5f5f5' });
}
});
// Make sure the parent and target have the correct expander class/icon.
function setExpander(n) {
var c = n.find('.expand-container');
var icon;
c.first().empty();
if (n.attr('id') == 'inventory-root-node') {
c.first().html('<i class=\"icon-sitemap\"></i>');
}
else if (c.length > 1) {
// not root and has children, put expander icon back
icon = (n.attr('data-state') == 'opened') ? 'icon-caret-down' : 'icon-caret-right';
c.first().html('<a class="expand"><i class="' + icon + '"></i></a>');
c.first().find('a').first().bind('click', toggle);
}
}
setExpander(target);
setExpander(parent);
}
Wait('stop');
*/
// Reload the tree
html = '';
idx = 0;
loadTreeData();
}
// disassociate the group from the original parent
if (scope.removeGroupRemove) {
scope.removeGroupRemove();
}
scope.removeGroupRemove = scope.$on('removeGroup', function() {
if (parent.attr('data-group-id')) {
// Only remove a group from a parent when the parent is a group and not the inventory root
var url = GetBasePath('base') + 'groups/' + parent.attr('data-group-id') + '/children/';
Rest.setUrl(url);
Rest.post({ id: node.attr('data-group-id'), disassociate: 1 })
.success( function(data, status, headers, config) {
cleanUp('success');
})
.error( function(data, status, headers, config) {
cleanUp('fail');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to remove ' + node.attr('name') + ' from ' +
parent.attr('name') + '. POST returned status: ' + status });
});
}
else {
cleanUp('success');
}
});
if (scope['addToTargetRemove']) {
scope.addToTargetRemove();
}
scope.addToTargetRemove = scope.$on('addToTarget', function() {
// add the new group to the target parent
var url = (target.attr('data-group-id')) ? GetBasePath('base') + 'groups/' + target.attr('data-group-id') + '/children/' :
GetBasePath('inventory') + inv_id + '/groups/';
var group = {
id: node.attr('data-group-id'),
name: node.attr('data-name'),
description: node.attr('data-description'),
inventory: inv_id
}
Rest.setUrl(url);
Rest.post(group)
.success( function(data, status, headers, config) {
scope.$emit('removeGroup');
})
.error( function(data, status, headers, config) {
cleanUp('fail');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to add ' + node.attr('name') + ' to ' +
target.attr('name') + '. POST returned status: ' + status });
});
});
Wait('start');
// Lookup the inventory. We already have what we need except for variables.
var url = GetBasePath('base') + 'groups/' + node.attr('data-group-id') + '/';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
variables = (data.variables) ? JSON.parse(data.variables) : "";
scope.$emit('addToTarget');
})
.error( function(data, status, headers, config) {
cleanUp('fail');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to lookup group ' + node.attr('name') +
'. GET returned status: ' + status });
});
});
// The HTML is ready. Insert it into the view.
if (scope.searchTreeReadyRemove) {
scope.searchTreeReadyRemove();
}
scope.searchTreeReadyRemove = scope.$on('searchTreeReady', function(e, html) {
var container = angular.element(document.getElementById(target_id));
container.empty();
var compiled = $compile(html)(scope);
container.append(compiled);
function setTitleWidth(elm) {
// Fix for overflowing title text
var container = $('#search-tree-target');
var container_offset = container.offset();
var parent = elm.parent(); // <li>
var parent_offset = parent.offset();
var expander = parent.find('.expand-container').first();
var badge = parent.find('.badge-container').first();
var width = container.width() - parent_offset.left + container_offset.left -
badge.width() - expander.width() - 10;
elm.css('width', width + 'px');
}
// Fix overflowing title text now
$('#' + target_id).find('.title-container').each(function(idx) {
setTitleWidth($(this));
});
// Fix overflowing title text on screen resize
var timeout;
$(window).resize(function() {
clearTimeout(timeout); //remove prior timer so we don't resize a million times
timeout = setTimeout(function() {
$('#' + target_id).find('.title-container').each(function(idx) {
setTitleWidth($(this));
});
}, 500);
});
var links = container.find('a');
for (var i=0; i < links.length; i++) {
var link = angular.element(links[i]);
if (link.hasClass('expand')) {
link.unbind('click', toggle);
link.bind('click', toggle);
}
if (link.hasClass('activate')) {
link.unbind('click', activate);
link.bind('click', activate);
}
}
if (refresh_tree && group_id !== undefined) {
// pick a node by group_id
$('li[data-group-id="' + group_id + '"] .activate').first().click();
}
else if (refresh_tree && id !== undefined) {
// pick a node by id
$('#' + id + ' .activate').first().click();
}
else if (!refresh_tree) {
// default to the root node
$('#inventory-root-node .activate').first().click();
}
// Make the tree drag-n-droppable
if (moveable) {
$('#selector-tree .activate').draggable({
cursor: "pointer",
cursorAt: { top: -16, left: -10 },
revert: 'invalid',
helper: 'clone',
start: function (e, ui) {
var txt = '[ ' + ui.helper.text() + ' ]';
ui.helper.css({ 'display': 'inline-block', 'font-weight': 'normal', 'color': '#171717',
'background-color': '#f5f5f5', 'overflow': 'visible', 'white-space': 'normal',
'z-index': 5000 }).text(txt);
}
})
.droppable({
//hoverClass: 'droppable-hover',
tolerance: 'pointer',
over: function (e, ui) {
var p = $(this).parent().parent();
p.find('div').each(function(idx) {
if (idx > 0 && idx < 3) {
$(this).css({ 'border-bottom': '2px solid #171717' });
}
});
var c = p.find('.expand-container').first();
c.empty().html('<i class="icon-circle-arrow-right" style="color: #171717;"></i>');
},
out: function (e, ui) {
var p = $(this).parent().parent();
p.find('div').each(function(idx) {
if (idx > 0 && idx < 3) {
$(this).css({ 'border-bottom': '2px solid #f5f5f5' });
}
});
var c = p.find('.expand-container');
var icon;
c.first().empty();
if (c.length > 1) {
// has children, put expander icon back
icon = (p.attr('data-state') == 'opened') ? 'icon-caret-down' : 'icon-caret-right';
c.first().html('<a class="expand"><i class="' + icon + '"></i></a>');
c.first().find('a').first().bind('click', toggle);
}
},
drop: function (e,ui) {
var variables;
var node = ui.draggable.parent().parent(); // node being moved
var parent = node.parent().parent(); // node from
var target = $(this).parent().parent(); // node to
scope.$emit('MoveNode', node, parent, target);
// Make sure angular picks up changes and jQuery doesn't
// leave us in limbo...
if (!scope.$$phase) {
scope.$digest();
}
e.preventDefault();
}
});
} // if moveable
Wait('stop');
});
function buildHTML(tree_data) {
var sorted = SortNodes(tree_data);
var toolTip;
html += (sorted.length > 0) ? "<ul>\n" : "";
for(var i=0; i < sorted.length; i++) {
html += "<li id=\"search-node-0" + idx + "\" data-state=\"opened\" data-hosts=\"" + sorted[i].related.hosts + "\" " +
"data-description=\"" + sorted[i].description + "\" " +
"data-failures=\"" + sorted[i].has_active_failures + "\" " +
"data-groups=\"" + sorted[i].related.groups + "\" " +
"data-name=\"" + sorted[i].name + "\" " +
"data-group-id=\"" + sorted[i].id + "\" " +
"><div class=\"expand-container\">";
if (sorted[i].children.length > 0) {
html += "<a href=\"\" class=\"expand\"><i class=\"icon-caret-down\"></i></a>";
}
else {
html += " ";
}
html += "</div>";
toolTip = GetToolTip({ node: sorted[i] });
html += "<div class=\"badge-container\">";
html += "<a aw-tool-tip=\"" + toolTip.tooltip + "\" data-placement=\"top\"";
html += (toolTip.url !== '') ? " href=\"" + toolTip.url + "\"": "";
html += ">";
html += "<i class=\"field-badge icon-failures-" + toolTip['class'] + "\" ></i>";
html += "</a>";
html += "</div> ";
html += "<div class=\"title-container\"><a class=\"activate\">" + sorted[i].name + "</a></div>";
idx++;
if (sorted[i].children.length > 0) {
buildHTML(sorted[i].children);
}
else {
//html += "<ul></ul>\n";
html += "</li>\n";
}
}
html += "</ul>\n";
}
// Build the HTML for our tree
if (scope.buildAllGroupsRemove) {
scope.buildAllGroupsRemove();
}
scope.buildAllGroupsRemove = scope.$on('buildAllGroups', function(e, inventory_name, inventory_tree) {
Rest.setUrl(inventory_tree);
Rest.get()
.success( function(data, status, headers, config) {
buildHTML(data);
scope.$emit('searchTreeReady', html + "</li>\n</ul>\n</div>\n");
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get inventory tree for: ' + inventory_id + '. GET returned: ' + status });
});
});
// Builds scope.inventory_groups, used by the group picker on Hosts view to build the list of potential groups
// that can be added to a host. <<<< Should probably be moved to /helpers/Hosts.js
if (scope.buildGroupListRemove) {
scope.buildGroupListRemove();
}
scope.buildGroupListRemove = scope.$on('buildAllGroups', function(e, inventory_name, inventory_tree, groups_url) {
scope.inventory_groups = [];
Rest.setUrl(groups_url);
Rest.get()
.success( function(data, status, headers, config) {
var groups = [];
for (var i=0; i < data.results.length; i++) {
groups.push({
id: data.results[i].id,
description: data.results[i].description,
name: data.results[i].name });
}
scope.inventory_groups = SortNodes(groups);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get groups for inventory: ' + inventory_id + '. GET returned: ' + status });
});
});
function loadTreeData() {
// Load the inventory root node
Wait('start');
Rest.setUrl (GetBasePath('inventory') + inventory_id + '/');
Rest.get()
.success( function(data, status, headers, config) {
var tip = GetInventoryToolTip({ node: data });
html += "<div class=\"title\">Group Selector:</div>\n" +
"<div id=\"selector-tree\">\n" +
"<ul id=\"inventory-tree\" class=\"tree-root\">\n" +
"<li id=\"inventory-root-node\" data-state=\"opened\" data-hosts=\"" + data.related.hosts + "\" " +
"data-description=\"" + data.description + "\" " +
"data-failures=\"" + data.has_active_failures + "\" " +
"data-groups=\"" + data.related.groups + "\" " +
"data-name=\"" + data.name + "\" " +
"data-inventory=\"" + data.id + "\"" +
">" +
"<div class=\"expand-container\" id=\"root-expand-container\"><i class=\"icon-sitemap\"></i></div>" +
"<div class=\"badge-container\" id=\"root-badge-container\">\n";
html += "<a aw-tool-tip=\"" + tip['tooltip'] + "\" data-placement=\"top\"";
html += (tip.link) ? " href=\"" + tip['link'] + "\"" : "";
html += ">";
html += "<i class=\"field-badge icon-failures-" + tip['class'] + "\"></i></a>";
html += "</div>\n";
html += "<div class=\"title-container\" id=\"root-title-container\">" +
"<a class=\"activate\">" + data.name + "</a></div>";
scope.$emit('buildAllGroups', data.name, data.related.tree, data.related.groups);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status });
});
}
loadTreeData();
}
}])
// Set node name and description after an update to Group properties.
.factory('SetNodeName', [ function() {
return function(params) {
var scope = params.scope;
var name = params.name;
var descr = params.description;
var group_id = (params.group_id !== undefined) ? params.group_id : null;
var inventory_id = (params.inventory_id != undefined) ? params.inventory_id : null;
if (group_id !== null) {
$('#inventory-tree').find('li [data-group-id="' + group_id + '"]').each(function(idx) {
$(this).attr('data-name',name);
$(this).attr('data-description',descr);
$(this).find('.activate').first().text(name);
});
}
if (inventory_id !== null) {
$('#inventory-root-node').attr('data-name', name).attr('data-description', descr).find('.activate').first().text(name);
}
}
}])
.factory('ClickNode', [ function() {
return function(params) {
var selector = params.selector; //jquery selector string to find the correct <li>
$(selector + ' .activate').first().click();
}
}])
.factory('DeleteNode', [ function() {
return function(params) {
var selector = params.selector; //jquery selector string to find the correct <li>
$(selector).first().detach();
}
}]);

View File

@@ -12,10 +12,12 @@
angular.module('Utilities', ['RestServices', 'Utilities']) angular.module('Utilities', ['RestServices', 'Utilities'])
.factory('ClearScope', [ function() { .factory('ClearScope', [
function () {
return function (id) { return function (id) {
var element = document.getElementById(id), scope; var element = document.getElementById(id),
scope;
if (element) { if (element) {
scope = angular.element(element).scope(); scope = angular.element(element).scope();
scope.$destroy(); scope.$destroy();
@@ -33,15 +35,15 @@ angular.module('Utilities',['RestServices', 'Utilities'])
try { try {
$('#help-modal').dialog('close'); $('#help-modal').dialog('close');
} } catch (e) {
catch(e) {
// ignore // ignore
} }
$(window).unbind('resize'); $(window).unbind('resize');
}; };
}]) }
])
/* Empty() /* Empty()
@@ -50,11 +52,13 @@ angular.module('Utilities',['RestServices', 'Utilities'])
* Only works on non-Ojbect types. * Only works on non-Ojbect types.
* *
*/ */
.factory('Empty', [ function() { .factory('Empty', [
function () {
return function (val) { return function (val) {
return (val === null || val === undefined || val === '') ? true : false; return (val === null || val === undefined || val === '') ? true : false;
}; };
}]) }
])
.factory('ToggleClass', function () { .factory('ToggleClass', function () {
@@ -62,15 +66,15 @@ angular.module('Utilities',['RestServices', 'Utilities'])
// Toggles the existance of a css class on a given element // Toggles the existance of a css class on a given element
if ($(selector) && $(selector).hasClass(cssClass)) { if ($(selector) && $(selector).hasClass(cssClass)) {
$(selector).removeClass(cssClass); $(selector).removeClass(cssClass);
} } else if ($(selector)) {
else if ($(selector)) {
$(selector).addClass(cssClass); $(selector).addClass(cssClass);
} }
}; };
}) })
.factory('Alert', ['$rootScope', function($rootScope) { .factory('Alert', ['$rootScope',
function ($rootScope) {
return function (hdr, msg, cls, action, secondAlert, disableButtons) { return function (hdr, msg, cls, action, secondAlert, disableButtons) {
// Pass in the header and message you want displayed on TB modal dialog found in index.html. // Pass in the header and message you want displayed on TB modal dialog found in index.html.
// Assumes an #id of 'alert-modal'. Pass in an optional TB alert class (i.e. alert-danger, alert-success, // Assumes an #id of 'alert-modal'. Pass in an optional TB alert class (i.e. alert-danger, alert-success,
@@ -80,7 +84,11 @@ angular.module('Utilities',['RestServices', 'Utilities'])
$rootScope.alertHeader2 = hdr; $rootScope.alertHeader2 = hdr;
$rootScope.alertBody2 = msg; $rootScope.alertBody2 = msg;
$rootScope.alertClass2 = (cls) ? cls : 'alert-danger'; //default alert class is alert-danger $rootScope.alertClass2 = (cls) ? cls : 'alert-danger'; //default alert class is alert-danger
$('#alert-modal2').modal({ show: true, keyboard: true , backdrop: 'static' }); $('#alert-modal2').modal({
show: true,
keyboard: true,
backdrop: 'static'
});
$rootScope.disableButtons2 = (disableButtons) ? true : false; $rootScope.disableButtons2 = (disableButtons) ? true : false;
if (action) { if (action) {
$('#alert-modal2').on('hidden', function () { $('#alert-modal2').on('hidden', function () {
@@ -95,12 +103,15 @@ angular.module('Utilities',['RestServices', 'Utilities'])
} }
} }
}); });
} } else {
else {
$rootScope.alertHeader = hdr; $rootScope.alertHeader = hdr;
$rootScope.alertBody = msg; $rootScope.alertBody = msg;
$rootScope.alertClass = (cls) ? cls : 'alert-danger'; //default alert class is alert-danger $rootScope.alertClass = (cls) ? cls : 'alert-danger'; //default alert class is alert-danger
$('#alert-modal').modal({ show: true, keyboard: true , backdrop: 'static' }); $('#alert-modal').modal({
show: true,
keyboard: true,
backdrop: 'static'
});
$(document).bind('keydown', function (e) { $(document).bind('keydown', function (e) {
if (e.keyCode === 27) { if (e.keyCode === 27) {
@@ -119,7 +130,8 @@ angular.module('Utilities',['RestServices', 'Utilities'])
} }
} }
}; };
}]) }
])
.factory('ProcessErrors', ['$rootScope', '$cookieStore', '$log', '$location', 'Alert', 'Wait', .factory('ProcessErrors', ['$rootScope', '$cookieStore', '$log', '$location', 'Alert', 'Wait',
@@ -136,27 +148,21 @@ angular.module('Utilities',['RestServices', 'Utilities'])
msg = 'The API responded with a 403 Access Denied error. '; msg = 'The API responded with a 403 Access Denied error. ';
if (data.detail) { if (data.detail) {
msg += 'Detail: ' + data.detail; msg += 'Detail: ' + data.detail;
} } else {
else {
msg += 'Please contact your system administrator.'; msg += 'Please contact your system administrator.';
} }
Alert(defaultMsg.hdr, msg); Alert(defaultMsg.hdr, msg);
} } else if ((status === 401 && data.detail && data.detail === 'Token is expired') ||
else if ( (status === 401 && data.detail && data.detail === 'Token is expired') ||
(status === 401 && data.detail && data.detail === 'Invalid token')) { (status === 401 && data.detail && data.detail === 'Invalid token')) {
$rootScope.sessionTimer.expireSession(); $rootScope.sessionTimer.expireSession();
$location.url('/login'); $location.url('/login');
} } else if (data.non_field_errors) {
else if (data.non_field_errors) {
Alert('Error!', data.non_field_errors); Alert('Error!', data.non_field_errors);
} } else if (data.detail) {
else if (data.detail) {
Alert(defaultMsg.hdr, defaultMsg.msg + ' ' + data.detail); Alert(defaultMsg.hdr, defaultMsg.msg + ' ' + data.detail);
} } else if (data.__all__) {
else if (data.__all__) {
Alert('Error!', data.__all__); Alert('Error!', data.__all__);
} } else if (form) {
else if (form) {
fieldErrors = false; fieldErrors = false;
for (field in form.fields) { for (field in form.fields) {
if (data[field] && form.fields[field].tab) { if (data[field] && form.fields[field].tab) {
@@ -179,8 +185,7 @@ angular.module('Utilities',['RestServices', 'Utilities'])
$('[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').addClass('ng-invalid'); $('[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').addClass('ng-invalid');
fieldErrors = true; fieldErrors = true;
} }
} } else {
else {
if (data[field]) { if (data[field]) {
scope[field + '_api_error'] = data[field][0]; scope[field + '_api_error'] = data[field][0];
//scope[form.name + '_form'][field].$setValidity('apiError', false); //scope[form.name + '_form'][field].$setValidity('apiError', false);
@@ -192,12 +197,12 @@ angular.module('Utilities',['RestServices', 'Utilities'])
if ((!fieldErrors) && defaultMsg) { if ((!fieldErrors) && defaultMsg) {
Alert(defaultMsg.hdr, defaultMsg.msg); Alert(defaultMsg.hdr, defaultMsg.msg);
} }
} } else {
else {
Alert(defaultMsg.hdr, defaultMsg.msg); Alert(defaultMsg.hdr, defaultMsg.msg);
} }
}; };
}]) }
])
.factory('LoadBreadCrumbs', ['$rootScope', '$routeParams', '$location', 'Empty', .factory('LoadBreadCrumbs', ['$rootScope', '$routeParams', '$location', 'Empty',
@@ -252,28 +257,37 @@ angular.module('Utilities',['RestServices', 'Utilities'])
if (found && $rootScope.crumbCache[j].altPath !== undefined) { if (found && $rootScope.crumbCache[j].altPath !== undefined) {
// Use altPath to override default path construction // Use altPath to override default path construction
$rootScope.breadcrumbs.push({ title: child, path: $rootScope.crumbCache[j].altPath }); $rootScope.breadcrumbs.push({
title: child,
path: $rootScope.crumbCache[j].altPath
});
} else {
$rootScope.breadcrumbs.push({
title: child,
path: ppath + '/' + paths[i]
});
} }
else { } else {
$rootScope.breadcrumbs.push({ title: child, path: ppath + '/' + paths[i] });
}
}
else {
if (/_/.test(paths[i])) { if (/_/.test(paths[i])) {
// replace '_' with space and uppercase each word // replace '_' with space and uppercase each word
paths[i] = paths[i].replace(/(?:^|_)\S/g, toUppercase) paths[i] = paths[i].replace(/(?:^|_)\S/g, toUppercase)
.replace(/_/g, ' '); .replace(/_/g, ' ');
} }
title = paths[i].charAt(0).toUpperCase() + paths[i].slice(1); title = paths[i].charAt(0).toUpperCase() + paths[i].slice(1);
$rootScope.breadcrumbs.push({ title: title, path: ppath + '/' + paths[i] }); $rootScope.breadcrumbs.push({
title: title,
path: ppath + '/' + paths[i]
});
} }
ppath += '/' + paths[i]; ppath += '/' + paths[i];
} }
} }
}; };
}]) }
])
.factory('HelpDialog', ['$rootScope', '$location', 'Store', function($rootScope, $location, Store) { .factory('HelpDialog', ['$rootScope', '$location', 'Store',
function ($rootScope, $location, Store) {
return function (params) { return function (params) {
// Display a help dialog // Display a help dialog
// //
@@ -311,15 +325,13 @@ angular.module('Utilities',['RestServices', 'Utilities'])
try { try {
isOpen = $('#help-modal').dialog('isOpen'); isOpen = $('#help-modal').dialog('isOpen');
} } catch (e) {
catch(e) {
// ignore // ignore
} }
if (isOpen) { if (isOpen) {
$('#help-modal').html(buildHtml(defn.story.steps[current_step])); $('#help-modal').html(buildHtml(defn.story.steps[current_step]));
} } else {
else {
// Define buttons based on story length // Define buttons based on story length
btns = []; btns = [];
if (defn.story.steps.length > 1) { if (defn.story.steps.length > 1) {
@@ -349,12 +361,19 @@ angular.module('Utilities',['RestServices', 'Utilities'])
} }
}); });
} }
btns.push({ text: "Close", btns.push({
click: function() { $('#help-modal').dialog('close'); } text: "Close",
click: function () {
$('#help-modal').dialog('close');
}
}); });
// Show the dialog // Show the dialog
$('#help-modal').html(buildHtml(defn.story.steps[current_step])).dialog({ $('#help-modal').html(buildHtml(defn.story.steps[current_step])).dialog({
position: { my: "center top", at: "center top+150", of: 'body' }, position: {
my: "center top",
at: "center top+150",
of: 'body'
},
title: defn.story.hdr, title: defn.story.hdr,
width: width, width: width,
height: height, height: height,
@@ -363,7 +382,9 @@ angular.module('Utilities',['RestServices', 'Utilities'])
show: 500, show: 500,
hide: 500, hide: 500,
resizable: false, resizable: false,
close: function() { $('#help-modal').empty(); } close: function () {
$('#help-modal').empty();
}
}); });
// Make the buttons look like TB and add FA icons // Make the buttons look like TB and add FA icons
@@ -373,29 +394,36 @@ angular.module('Utilities',['RestServices', 'Utilities'])
if (l === 'Close') { if (l === 'Close') {
h = "fa-times"; h = "fa-times";
c = "btn btn-default"; c = "btn btn-default";
$(this).attr({ 'class': c }).html("<i class=\"fa " + h + "\"></i> Close"); $(this).attr({
} 'class': c
else if (l === 'Prev') { }).html("<i class=\"fa " + h + "\"></i> Close");
} else if (l === 'Prev') {
h = "fa-chevron-left"; h = "fa-chevron-left";
c = "btn btn-primary"; c = "btn btn-primary";
$(this).attr({ 'class': c }).html("<i class=\"fa " + h + "\"></i> Prev"); $(this).attr({
} 'class': c
else { }).html("<i class=\"fa " + h + "\"></i> Prev");
} else {
h = "fa-chevron-right"; h = "fa-chevron-right";
c = "btn btn-primary"; c = "btn btn-primary";
$(this).attr({ 'class': c }).html("Next <i class=\"fa " + h + "\"></i>").css({ 'margin-right': '20px'}); $(this).attr({
'class': c
}).html("Next <i class=\"fa " + h + "\"></i>").css({
'margin-right': '20px'
});
} }
}); });
$('.ui-dialog[aria-describedby="help-modal"]').find('.ui-dialog-titlebar button') $('.ui-dialog[aria-describedby="help-modal"]').find('.ui-dialog-titlebar button')
.empty().attr({ 'class': 'close' }).text('x'); .empty().attr({
'class': 'close'
}).text('x');
// If user clicks the checkbox, update local storage // If user clicks the checkbox, update local storage
$('#auto-off-checkbox').click(function () { $('#auto-off-checkbox').click(function () {
if ($('input[name="auto-off-checkbox"]:checked').length) { if ($('input[name="auto-off-checkbox"]:checked').length) {
Store('inventoryAutoHelp', 'off'); Store('inventoryAutoHelp', 'off');
} } else {
else {
Store('inventoryAutoHelp', 'on'); Store('inventoryAutoHelp', 'on');
} }
}); });
@@ -405,32 +433,39 @@ angular.module('Utilities',['RestServices', 'Utilities'])
showHelp(0); showHelp(0);
}; };
}]) }
])
.factory('ReturnToCaller', ['$location', 'Empty', function($location, Empty) { .factory('ReturnToCaller', ['$location', 'Empty',
function ($location, Empty) {
return function (idx) { return function (idx) {
// Split the current path by '/' and use the array elements from 0 up to and // Split the current path by '/' and use the array elements from 0 up to and
// including idx as the new path. If no idx value supplied, use 0 to length - 1. // including idx as the new path. If no idx value supplied, use 0 to length - 1.
var paths = $location.path().replace(/^\//, '').split('/'), var paths = $location.path().replace(/^\//, '').split('/'),
newpath = '', i; newpath = '',
i;
idx = (Empty(idx)) ? paths.length - 1 : idx + 1; idx = (Empty(idx)) ? paths.length - 1 : idx + 1;
for (i = 0; i < idx; i++) { for (i = 0; i < idx; i++) {
newpath += '/' + paths[i]; newpath += '/' + paths[i];
} }
$location.path(newpath); $location.path(newpath);
}; };
}]) }
])
.factory('FormatDate', ['$filter', function($filter) { .factory('FormatDate', ['$filter',
function ($filter) {
return function (dt) { return function (dt) {
// Wrapper for data filter- an attempt to insure all dates display in // Wrapper for data filter- an attempt to insure all dates display in
// the same format. Pass in date object. // the same format. Pass in date object.
return $filter('date')(dt, 'MM/dd/yy HH:mm:ss'); return $filter('date')(dt, 'MM/dd/yy HH:mm:ss');
}; };
}]) }
])
.factory('Wait', [ '$rootScope', function($rootScope) { .factory('Wait', ['$rootScope',
function ($rootScope) {
return function (directive) { return function (directive) {
// Display a spinning icon in the center of the screen to freeze the // Display a spinning icon in the center of the screen to freeze the
// UI while waiting on async things to complete (i.e. API calls). // UI while waiting on async things to complete (i.e. API calls).
@@ -448,15 +483,21 @@ angular.module('Utilities',['RestServices', 'Utilities'])
width: $(document).width(), width: $(document).width(),
height: $(document).height() height: $(document).height()
}).fadeIn(); }).fadeIn();
$('.spinny').css({ top: y, left: x }).fadeIn(400); $('.spinny').css({
} top: y,
else if (directive === 'stop' && $rootScope.waiting){ left: x
$('.spinny, .overlay').fadeOut(400, function(){ $rootScope.waiting = false; }); }).fadeIn(400);
} else if (directive === 'stop' && $rootScope.waiting) {
$('.spinny, .overlay').fadeOut(400, function () {
$rootScope.waiting = false;
});
} }
}; };
}]) }
])
.factory('HideElement', [ function() { .factory('HideElement', [
function () {
return function (selector, action) { return function (selector, action) {
// Fade-in a cloack or vail or a specific element // Fade-in a cloack or vail or a specific element
var target = $(selector), var target = $(selector),
@@ -485,16 +526,22 @@ angular.module('Utilities',['RestServices', 'Utilities'])
"\"></div>"); "\"></div>");
$('#curtain-div').show(0, action); $('#curtain-div').show(0, action);
}; };
}]) }
])
.factory('ShowElement', [ function() { .factory('ShowElement', [
function () {
return function () { return function () {
// And Fade-out the cloack revealing the element // And Fade-out the cloack revealing the element
$('#curtain-div').fadeOut(500, function() { $(this).remove(); }); $('#curtain-div').fadeOut(500, function () {
$(this).remove();
});
}; };
}]) }
])
.factory('GetChoices', [ 'Rest', 'ProcessErrors', function(Rest, ProcessErrors) { .factory('GetChoices', ['Rest', 'ProcessErrors',
function (Rest, ProcessErrors) {
return function (params) { return function (params) {
// Get dropdown options // Get dropdown options
@@ -507,8 +554,7 @@ angular.module('Utilities',['RestServices', 'Utilities'])
if (scope[variable]) { if (scope[variable]) {
scope[variable].length = 0; scope[variable].length = 0;
} } else {
else {
scope[variable] = []; scope[variable] = [];
} }
@@ -519,30 +565,37 @@ angular.module('Utilities',['RestServices', 'Utilities'])
choices = (choice_name) ? data.actions.GET[field][choice_name] : data.actions.GET[field].choices; choices = (choice_name) ? data.actions.GET[field][choice_name] : data.actions.GET[field].choices;
// including 'name' property so list can be used by search // including 'name' property so list can be used by search
for (i = 0; i < choices.length; i++) { for (i = 0; i < choices.length; i++) {
scope[variable].push({ label: choices[i][1], value: choices[i][0], name: choices[i][1]}); scope[variable].push({
label: choices[i][1],
value: choices[i][0],
name: choices[i][1]
});
} }
if (callback) { if (callback) {
scope.$emit(callback); scope.$emit(callback);
} }
}) })
.error(function (data, status) { .error(function (data, status) {
ProcessErrors(scope, data, status, null, ProcessErrors(scope, data, status, null, { hdr: 'Error!',
{ hdr: 'Error!', msg: 'Failed to get ' + url + '. GET status: ' + status }); msg: 'Failed to get ' + url + '. GET status: ' + status });
}); });
}; };
}]) }
])
/* /*
* Search an array of objects, returning the matchting object or null * Search an array of objects, returning the matchting object or null
* *
* Find({ list: [], key: "key", val: <key value> }); * Find({ list: [], key: "key", val: <key value> });
*/ */
.factory('Find', [ function(){ .factory('Find', [
function () {
return function (params) { return function (params) {
var list = params.list, var list = params.list,
key = params.key, key = params.key,
val = params.val, val = params.val,
found = false, i; found = false,
i;
if (typeof list === 'object' && Array.isArray(list)) { if (typeof list === 'object' && Array.isArray(list)) {
for (i = 0; i < params.list.length; i++) { for (i = 0; i < params.list.length; i++) {
if (list[i][key] === val) { if (list[i][key] === val) {
@@ -554,7 +607,8 @@ angular.module('Utilities',['RestServices', 'Utilities'])
} }
return null; return null;
}; };
}]) }
])
/* /*
* DeugForm({ form: <form object>, scope: <current scope object> }); * DeugForm({ form: <form object>, scope: <current scope object> });
@@ -563,10 +617,12 @@ angular.module('Utilities',['RestServices', 'Utilities'])
* buttons fail to enable/disable properly. * buttons fail to enable/disable properly.
* *
*/ */
.factory('DebugForm', [ function() { .factory('DebugForm', [
function () {
return function (params) { return function (params) {
var form = params.form, var form = params.form,
scope = params.scope, fld; scope = params.scope,
fld;
for (fld in form.fields) { for (fld in form.fields) {
if (scope[form.name + '_form'][fld]) { if (scope[form.name + '_form'][fld]) {
console.log(fld + ' valid: ' + scope[form.name + '_form'][fld].$valid); console.log(fld + ' valid: ' + scope[form.name + '_form'][fld].$valid);
@@ -581,7 +637,8 @@ angular.module('Utilities',['RestServices', 'Utilities'])
console.log('form pristine: ' + scope[form.name + '_form'].$pristine); console.log('form pristine: ' + scope[form.name + '_form'].$pristine);
console.log('form valid: ' + scope[form.name + '_form'].$valid); console.log('form valid: ' + scope[form.name + '_form'].$valid);
}; };
}]) }
])
/* Store /* Store
@@ -596,26 +653,28 @@ angular.module('Utilities',['RestServices', 'Utilities'])
* store(key) retrieves the value of the key * store(key) retrieves the value of the key
* *
*/ */
.factory('Store', ['Empty', function(Empty) { .factory('Store', ['Empty',
function (Empty) {
return function (key, value) { return function (key, value) {
if (!Empty(value)) { if (!Empty(value)) {
// Store the value // Store the value
localStorage[key] = JSON.stringify(value); localStorage[key] = JSON.stringify(value);
} } else if (!Empty(key)) {
else if (!Empty(key)) {
// Return the value // Return the value
var val = localStorage[key]; var val = localStorage[key];
return (!Empty(val)) ? JSON.parse(val) : null; return (!Empty(val)) ? JSON.parse(val) : null;
} }
}; };
}]) }
])
/* /*
* *
* ApplyEllipsis() * ApplyEllipsis()
* *
*/ */
.factory('ApplyEllipsis', [ function() { .factory('ApplyEllipsis', [
function () {
return function (selector) { return function (selector) {
// Add a hidden element to the DOM. We'll use this to calc the px length of // Add a hidden element to the DOM. We'll use this to calc the px length of
// our target text. // our target text.
@@ -626,12 +685,12 @@ angular.module('Utilities',['RestServices', 'Utilities'])
} }
// Find and process the text. // Find and process the text.
$(selector).each(function () { $(selector).each(function () {
var setTitle = true, txt, w, pw, cw, df; var setTitle = true,
txt, w, pw, cw, df;
if ($(this).attr('title')) { if ($(this).attr('title')) {
txt = $(this).attr('title'); txt = $(this).attr('title');
setTitle = false; setTitle = false;
} } else {
else {
txt = $(this).text(); txt = $(this).text();
} }
tmp.text(txt); tmp.text(txt);
@@ -656,14 +715,5 @@ angular.module('Utilities',['RestServices', 'Utilities'])
}); });
}; };
}]); }
]);

View File

@@ -6,7 +6,6 @@
* to access the primary model objects. * to access the primary model objects.
* *
*/ */
'use strict'; 'use strict';
angular.module('ApiLoader', ['Utilities']) angular.module('ApiLoader', ['Utilities'])
@@ -24,18 +23,27 @@ angular.module('ApiLoader', ['Utilities'])
Store('api', data); Store('api', data);
}) })
.error(function (data, status) { .error(function (data, status) {
$rootScope.defaultUrls = { status: 'error' }; $rootScope.defaultUrls = {
ProcessErrors(null, data, status, null, status: 'error'
{ hdr: 'Error', msg: 'Failed to read ' + base + '. GET status: ' + status }); };
ProcessErrors(null, data, status, null, {
hdr: 'Error',
msg: 'Failed to read ' + base + '. GET status: ' + status
});
}); });
}) })
.error(function (data, status) { .error(function (data, status) {
$rootScope.defaultUrls = { status: 'error' }; $rootScope.defaultUrls = {
ProcessErrors(null, data, status, null, status: 'error'
{ hdr: 'Error', msg: 'Failed to read /api. GET status: ' + status }); };
ProcessErrors(null, data, status, null, {
hdr: 'Error',
msg: 'Failed to read /api. GET status: ' + status
});
}); });
}; };
}]) }
])
.factory('GetBasePath', ['$rootScope', 'Store', 'LoadBasePaths', 'Empty', .factory('GetBasePath', ['$rootScope', 'Store', 'LoadBasePaths', 'Empty',
function ($rootScope, Store, LoadBasePaths, Empty) { function ($rootScope, Store, LoadBasePaths, Empty) {
@@ -51,7 +59,5 @@ angular.module('ApiLoader', ['Utilities'])
} }
return $rootScope.defaultUrls[set]; return $rootScope.defaultUrls[set];
}; };
}]); }
]);

View File

@@ -10,6 +10,7 @@
/* global chkPass:false */ /* global chkPass:false */
angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'JobsHelper']) angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'JobsHelper'])
// awpassmatch: Add to password_confirm field. Will test if value // awpassmatch: Add to password_confirm field. Will test if value
// matches that of 'input[name="password"]' // matches that of 'input[name="password"]'
.directive('awpassmatch', function() { .directive('awpassmatch', function() {

View File

@@ -8,10 +8,12 @@
'use strict'; 'use strict';
angular.module('AWFilters', []) angular.module('AWFilters', [])
// //
// capitalize -capitalize the first letter of each word // capitalize -capitalize the first letter of each word
// //
.filter('capitalize', [ function() { .filter('capitalize', [
function () {
return function (input) { return function (input) {
var values, result, i; var values, result, i;
if (input) { if (input) {
@@ -23,4 +25,5 @@ angular.module('AWFilters', [])
return result.trim(); return result.trim();
} }
}; };
}]); }
]);

File diff suppressed because it is too large Load Diff

View File

@@ -13,25 +13,22 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
.factory('Attr', function () { .factory('Attr', function () {
return function (obj, key, fld) { return function (obj, key, fld) {
var result; var i, s, result,
var value = (typeof obj[key] === "string") ? obj[key].replace(/[\'\"]/g, '&quot;') : obj[key]; value = (typeof obj[key] === "string") ? obj[key].replace(/[\'\"]/g, '&quot;') : obj[key];
if (/^ng/.test(key)) { if (/^ng/.test(key)) {
result = 'ng-' + key.replace(/^ng/, '').toLowerCase() + "=\"" + value + "\" "; result = 'ng-' + key.replace(/^ng/, '').toLowerCase() + "=\"" + value + "\" ";
} } else if (/^data|^aw/.test(key) && key !== 'awPopOver') {
else if (/^data|^aw/.test(key) && key != 'awPopOver') { s = '';
var s = ''; for (i = 0; i < key.length; i++) {
for (var i=0; i < key.length; i++) {
if (/[A-Z]/.test(key.charAt(i))) { if (/[A-Z]/.test(key.charAt(i))) {
s += '-' + key.charAt(i).toLowerCase(); s += '-' + key.charAt(i).toLowerCase();
} } else {
else {
s += key.charAt(i); s += key.charAt(i);
} }
} }
result = s + "=\"" + value + "\" "; result = s + "=\"" + value + "\" ";
} } else {
else {
switch (key) { switch (key) {
case 'trueValue': case 'trueValue':
result = "ng-true-value=\"" + value + "\" "; result = "ng-true-value=\"" + value + "\" ";
@@ -42,9 +39,8 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
case 'awPopOver': case 'awPopOver':
// construct the entire help link // construct the entire help link
result = "<a id=\"awp-" + fld + "\" href=\"\" aw-pop-over=\'" + value + "\' "; result = "<a id=\"awp-" + fld + "\" href=\"\" aw-pop-over=\'" + value + "\' ";
result += (obj.dataTitle) ? "data-title=\"" + obj['dataTitle'].replace(/[\'\"]/g, '&quot;') + "\" " : ""; result += (obj.dataPlacement) ? "data-placement=\"" + obj.dataPlacement.replace(/[\'\"]/g, '&quot;') + "\" " : "";
result += (obj.dataPlacement) ? "data-placement=\"" + obj['dataPlacement'].replace(/[\'\"]/g, '&quot;') + "\" " : ""; result += (obj.dataContainer) ? "data-container=\"" + obj.dataContainer.replace(/[\'\"]/g, '&quot;') + "\" " : "";
result += (obj.dataContainer) ? "data-container=\"" + obj['dataContainer'].replace(/[\'\"]/g, '&quot;') + "\" " : "";
result += "class=\"help-link\" "; result += "class=\"help-link\" ";
result += "><i class=\"fa fa-question-circle\"></i></a> "; result += "><i class=\"fa fa-question-circle\"></i></a> ";
break; break;
@@ -54,7 +50,7 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
case 'icon': case 'icon':
// new method of constructing <i> icon tag. Replces Icon method. // new method of constructing <i> icon tag. Replces Icon method.
result = "<i class=\"fa fa-" + value; result = "<i class=\"fa fa-" + value;
result += (obj['iconSize']) ? " " + obj['iconSize'] : ""; result += (obj.iconSize) ? " " + obj.iconSize : "";
result += "\"></i>"; result += "\"></i>";
break; break;
case 'autocomplete': case 'autocomplete':
@@ -69,23 +65,24 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
return result; return result;
} };
}) })
.factory('Icon', function () { .factory('Icon', function () {
return function (icon) { return function (icon) {
return "<i class=\"fa " + icon + "\"></i> "; return "<i class=\"fa " + icon + "\"></i> ";
} };
}) })
.factory('SelectIcon', ['Icon', function(Icon) { .factory('SelectIcon', ['Icon',
function (Icon) {
return function (params) { return function (params) {
// Common point for matching any type of action to the appropriate // Common point for matching any type of action to the appropriate
// icon. The intention is to maintain consistent meaning and presentation // icon. The intention is to maintain consistent meaning and presentation
// for every icon used in the application. // for every icon used in the application.
var icon; var icon,
var action = params.action; action = params.action,
var size = params.size; size = params.size;
switch (action) { switch (action) {
case 'help': case 'help':
icon = "fa-question-circle"; icon = "fa-question-circle";
@@ -141,46 +138,45 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
} }
icon += (size) ? " " + size : ""; icon += (size) ? " " + size : "";
return Icon(icon); return Icon(icon);
};
} }
}]) ])
.factory('Button', ['Attr', 'SelectIcon', function(Attr, SelectIcon) { .factory('Button', ['Attr', 'SelectIcon',
function (Attr, SelectIcon) {
return function (params) { return function (params) {
// pass in button object, get back html // pass in button object, get back html
var btn = params.btn; var btn = params.btn,
var action = params.action; // label used to select the icon action = params.action, // label used to select the icon
var toolbar = params.toolbar; toolbar = params.toolbar,
html = '';
if (toolbar) { if (toolbar) {
//if this is a toolbar button, set some defaults //if this is a toolbar button, set some defaults
btn['class'] = 'btn-xs btn-primary'; btn.class = 'btn-xs btn-primary';
btn['iconSize'] = 'fa-lg'; btn.iconSize = 'fa-lg';
delete btn['label']; delete btn.label;
} }
var html = '';
html += "<button type=\"button\" "; html += "<button type=\"button\" ";
html += "class=\"btn"; html += "class=\"btn";
if (btn['class']) { if (btn['class']) {
html += ' ' + btn['class']; html += ' ' + btn['class'];
} } else {
else {
html += " btn-sm"; html += " btn-sm";
} }
html += (btn['awPopOver']) ? " help-link-white" : ""; html += (btn.awPopOver) ? " help-link-white" : "";
html += "\" "; html += "\" ";
html += (btn.ngClick) ? Attr(btn, 'ngClick') : ""; html += (btn.ngClick) ? Attr(btn, 'ngClick') : "";
if (btn.id) { if (btn.id) {
html += "id=\"" + btn.id + "\" "; html += "id=\"" + btn.id + "\" ";
} } else {
else {
if (action) { if (action) {
html += "id=\"" + action + "_btn\" "; html += "id=\"" + action + "_btn\" ";
} }
@@ -188,7 +184,7 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += (btn.ngHide) ? Attr(btn, 'ngHide') : ""; html += (btn.ngHide) ? Attr(btn, 'ngHide') : "";
html += (btn.awToolTip) ? Attr(btn, 'awToolTip') : ""; html += (btn.awToolTip) ? Attr(btn, 'awToolTip') : "";
html += (btn.awToolTip && btn.dataPlacement == undefined) ? "data-placement=\"top\" " : ""; html += (btn.awToolTip && btn.dataPlacement === undefined) ? "data-placement=\"top\" " : "";
html += (btn.awPopOver) ? "aw-pop-over=\"" + html += (btn.awPopOver) ? "aw-pop-over=\"" +
btn.awPopOver.replace(/[\'\"]/g, '&quot;') + "\" " : ""; btn.awPopOver.replace(/[\'\"]/g, '&quot;') + "\" " : "";
html += (btn.dataPlacement) ? Attr(btn, 'dataPlacement') : ""; html += (btn.dataPlacement) ? Attr(btn, 'dataPlacement') : "";
@@ -200,19 +196,24 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += (btn.ngClass) ? Attr(btn, 'ngClass') : ""; html += (btn.ngClass) ? Attr(btn, 'ngClass') : "";
html += (btn.awTipPlacement) ? Attr(btn, 'awTipPlacement') : ""; html += (btn.awTipPlacement) ? Attr(btn, 'awTipPlacement') : "";
html += " >"; html += " >";
html += (btn['img']) ? "<img src=\"" + $basePath + "img/" + btn.img + "\" style=\"width: 12px; height: 12px;\" >" : ""; html += (btn.img) ? "<img src=\"" + $basePath + "img/" + btn.img + "\" style=\"width: 12px; height: 12px;\" >" : "";
html += SelectIcon({ action: action, size: btn.iconSize }); html += SelectIcon({
action: action,
size: btn.iconSize
});
html += (btn.label) ? " " + btn.label : ""; html += (btn.label) ? " " + btn.label : "";
html += "</button> "; html += "</button> ";
return html; return html;
};
} }
}]) ])
.factory('NavigationLink', ['Attr', 'Icon', function(Attr, Icon) { .factory('NavigationLink', ['Attr', 'Icon',
function (Attr, Icon) {
return function (link) { return function (link) {
var html = "<a "; var html = "<a ";
html += (link.href) ? Attr(link, 'href') : ''; html += (link.href) ? Attr(link, 'href') : '';
@@ -223,36 +224,34 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += (link.label) ? link.label : ''; html += (link.label) ? link.label : '';
html += "</a>\n"; html += "</a>\n";
return html; return html;
};
} }
}]) ])
.factory('DropDown', ['Attr', 'Icon', function(Attr, Icon) { .factory('DropDown', ['Attr', 'Icon',
function (Attr, Icon) {
return function (params) { return function (params) {
var list = params['list']; var list = params.list,
var fld = params['fld']; fld = params.fld,
var options = params['options']; i, html, field, name;
var html, field;
if (params.field) { if (params.field) {
field = params.field; field = params.field;
} } else {
else {
if (params.type) { if (params.type) {
field = list[params.type][fld]; field = list[params.type][fld];
} } else {
else { field = list.fields[fld];
field = list['fields'][fld];
} }
} }
var name = field['label'].replace(/ /g,'_'); name = field.label.replace(/ /g, '_');
if (params.td == undefined || params.td !== false) { if (params.td === undefined || params.td !== false) {
html = "<td class=\"" + fld + "-column\">\n"; html = "<td class=\"" + fld + "-column\">\n";
} } else {
else {
html = ''; html = '';
} }
@@ -266,7 +265,7 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += field.label; html += field.label;
html += " <span class=\"caret\"></span></a>\n"; html += " <span class=\"caret\"></span></a>\n";
html += "<ul class=\"dropdown-menu pull-right\" role=\"menu\" aria-labelledby=\"dropdownMenu1\">\n"; html += "<ul class=\"dropdown-menu pull-right\" role=\"menu\" aria-labelledby=\"dropdownMenu1\">\n";
for (var i=0; i < field.options.length; i++) { for (i = 0; i < field.options.length; i++) {
html += "<li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" "; html += "<li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" ";
html += "ng-click=\"" + field.options[i].ngClick + "\" "; html += "ng-click=\"" + field.options[i].ngClick + "\" ";
html += (field.options[i].ngShow) ? "ng-show=\"" + field.options[i].ngShow + "\" " : ""; html += (field.options[i].ngShow) ? "ng-show=\"" + field.options[i].ngShow + "\" " : "";
@@ -276,24 +275,26 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += "</ul>\n"; html += "</ul>\n";
html += "</div>\n"; html += "</div>\n";
html += (params.td == undefined || params.td !== false) ? "</td>\n" : ""; html += (params.td === undefined || params.td !== false) ? "</td>\n" : "";
return html; return html;
};
} }
}]) ])
.factory('BadgeCount', [ function() { .factory('BadgeCount', [
function () {
return function (params) { return function (params) {
// Adds a badge count with optional tooltip // Adds a badge count with optional tooltip
var list = params['list']; var list = params.list,
var fld = params['fld']; fld = params.fld,
var field = list.fields[fld]; field = list.fields[fld],
var options = params['options']; html;
var base = params['base'];
var html = "<td class=\"" + fld + "-column" html = "<td class=\"" + fld + "-column";
html += (field.columnClass) ? " " + field.columnClass : ""; html += (field.columnClass) ? " " + field.columnClass : "";
html += "\">\n"; html += "\">\n";
html += "<a ng-href=\"" + field.ngHref + "\" aw-tool-tip=\"" + field.awToolTip + "\""; html += "<a ng-href=\"" + field.ngHref + "\" aw-tool-tip=\"" + field.awToolTip + "\"";
@@ -302,24 +303,26 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += "<span class=\"badge"; html += "<span class=\"badge";
html += (field['class']) ? " " + field['class'] : ""; html += (field['class']) ? " " + field['class'] : "";
html += "\">"; html += "\">";
html += "\{\{ " + list.iterator + '.' + fld + " \}\}"; html += "{{ " + list.iterator + '.' + fld + " }}";
html += "</span>"; html += "</span>";
html += (field.badgeLabel) ? " " + field.badgeLabel : ""; html += (field.badgeLabel) ? " " + field.badgeLabel : "";
html += "</a>\n"; html += "</a>\n";
html += "</td>\n"; html += "</td>\n";
return html; return html;
};
} }
}]) ])
.factory('Badge', [ function() { .factory('Badge', [
function () {
return function (field) { return function (field) {
// Adds an icon(s) with optional tooltip // Adds an icon(s) with optional tooltip
var html = ''; var i, html = '';
if (field.badges) { if (field.badges) {
for (var i=0; i < field.badges.length; i++) { for (i = 0; i < field.badges.length; i++) {
if (field.badges[i].toolTip) { if (field.badges[i].toolTip) {
html += "<a href=\"\" aw-tool-tip=\"" + field.badges[i].toolTip + "\""; html += "<a href=\"\" aw-tool-tip=\"" + field.badges[i].toolTip + "\"";
html += (field.badges[i].toolTipPlacement) ? " data-placement=\"" + field.badges[i].toolTipPlacement + "\"" : ""; html += (field.badges[i].toolTipPlacement) ? " data-placement=\"" + field.badges[i].toolTipPlacement + "\"" : "";
@@ -336,8 +339,7 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
} }
html += "\n"; html += "\n";
} }
} } else {
else {
if (field.badgeToolTip) { if (field.badgeToolTip) {
html += "<a "; html += "<a ";
html += (field.badgeNgHref) ? "ng-href=\"" + field.badgeNgHref + "\" " : "href=\"\""; html += (field.badgeNgHref) ? "ng-href=\"" + field.badgeNgHref + "\" " : "href=\"\"";
@@ -358,42 +360,41 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
} }
html += "\n"; html += "\n";
} }
return html; return html;
};
} }
}]) ])
.factory('Breadcrumbs', ['Attr', function(Attr) { .factory('Breadcrumbs', ['Attr',
function (Attr) {
return function (params) { return function (params) {
// Generate breadcrumbs using the list-generator.js method. // Generate breadcrumbs using the list-generator.js method.
var list = params.list; var list = params.list,
var mode = params.mode; mode = params.mode,
var html = ''; html = '', itm, navigation;
html += "<div class=\"nav-path\">\n"; html += "<div class=\"nav-path\">\n";
html += "<ul class=\"breadcrumb\" id=\"breadcrumb-list\">\n"; html += "<ul class=\"breadcrumb\" id=\"breadcrumb-list\">\n";
html += "<li ng-repeat=\"crumb in breadcrumbs\"><a href=\"{{ '#' + crumb.path }}\">{{ crumb.title }}</a></li>\n"; html += "<li ng-repeat=\"crumb in breadcrumbs\"><a href=\"{{ '#' + crumb.path }}\">{{ crumb.title }}</a></li>\n";
if (list.navigationLinks) { if (list.navigationLinks) {
var navigation = list.navigationLinks; navigation = list.navigationLinks;
if (navigation['ngHide']) { if (navigation.ngHide) {
html += "<li class=\"active\" ng-show=\"" + navigation['ngHide'] + "\">"; html += "<li class=\"active\" ng-show=\"" + navigation.ngHide + "\">";
html += list.editTitle; html += list.editTitle;
html += "</li>\n"; html += "</li>\n";
html += "<li class=\"active\" ng-hide=\"" + navigation['ngHide'] + "\"> </li>\n"; html += "<li class=\"active\" ng-hide=\"" + navigation.ngHide + "\"> </li>\n";
} } else {
else {
html += "<li class=\"active\"> </li>\n"; html += "<li class=\"active\"> </li>\n";
html += "</ul>\n"; html += "</ul>\n";
} }
html += "<div class=\"dropdown\" "; html += "<div class=\"dropdown\" ";
html += (navigation['ngHide']) ? Attr(navigation, 'ngHide') : ''; html += (navigation.ngHide) ? Attr(navigation, 'ngHide') : '';
html += ">\n"; html += ">\n";
for (var itm in navigation) { for (itm in navigation) {
if (typeof navigation[itm] == 'object' && navigation[itm].active) { if (typeof navigation[itm] === 'object' && navigation[itm].active) {
html += "<a href=\"\" class=\"toggle\" "; html += "<a href=\"\" class=\"toggle\" ";
html += "data-toggle=\"dropdown\" "; html += "data-toggle=\"dropdown\" ";
html += ">" + navigation[itm].label + " <i class=\"fa fa-chevron-circle-down crumb-icon\"></i></a>"; html += ">" + navigation[itm].label + " <i class=\"fa fa-chevron-circle-down crumb-icon\"></i></a>";
@@ -401,8 +402,8 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
} }
} }
html += "<ul class=\"dropdown-menu\" role=\"menu\">\n"; html += "<ul class=\"dropdown-menu\" role=\"menu\">\n";
for (var itm in navigation) { for (itm in navigation) {
if (typeof navigation[itm] == 'object') { if (typeof navigation[itm] === 'object') {
html += "<li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"" + html += "<li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"" +
navigation[itm].href + "\" "; navigation[itm].href + "\" ";
// html += (navigation[itm].active) ? "class=\"active\" " : ""; // html += (navigation[itm].active) ? "class=\"active\" " : "";
@@ -417,13 +418,11 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += "</ul>\n"; html += "</ul>\n";
html += "</div><!-- dropdown -->\n"; html += "</div><!-- dropdown -->\n";
html += "</div><!-- nav-path -->\n"; html += "</div><!-- nav-path -->\n";
} } else {
else {
html += "<li class=\"active\">"; html += "<li class=\"active\">";
if (mode == 'select') { if (mode === 'select') {
html += list.selectTitle; html += list.selectTitle;
} } else {
else {
html += list.editTitle; html += list.editTitle;
} }
html += "</li>\n</ul>\n</div>\n"; html += "</li>\n</ul>\n</div>\n";
@@ -431,32 +430,32 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
return html; return html;
};
} }
}]) ])
.factory('Column', ['Attr', 'Icon', 'DropDown', 'Badge', 'BadgeCount', function(Attr, Icon, DropDown, Badge, BadgeCount) { .factory('Column', ['Attr', 'Icon', 'DropDown', 'Badge', 'BadgeCount',
function (Attr, Icon, DropDown, Badge, BadgeCount) {
return function (params) { return function (params) {
var list = params['list']; var list = params.list,
var fld = params['fld']; fld = params.fld,
var options = params['options']; options = params.options,
var base = params['base']; base = params.base,
field = list.fields[fld],
html = '', cap;
var field = list['fields'][fld]; if (field.type !== undefined && field.type === 'DropDown') {
var html = '';
if (field.type !== undefined && field.type == 'DropDown') {
html = DropDown(params); html = DropDown(params);
} } else if (field.type === 'badgeCount') {
else if (field.type == 'badgeCount') {
html = BadgeCount(params); html = BadgeCount(params);
} } else {
else {
html += "<td class=\"" + fld + "-column"; html += "<td class=\"" + fld + "-column";
html += (field['class']) ? " " + field['class'] : ""; html += (field['class']) ? " " + field['class'] : "";
html += (field['columnClass']) ? " " + field['columnClass'] : ""; html += (field.columnClass) ? " " + field.columnClass : "";
html += "\" "; html += "\" ";
html += (field.ngClass) ? Attr(field, 'ngClass') : ""; html += (field.ngClass) ? Attr(field, 'ngClass') : "";
html += (options.mode == 'lookup' || options.mode == 'select') ? " ng-click=\"toggle_" + list.iterator +"({{ " + list.iterator + ".id }})\"" : ""; html += (options.mode === 'lookup' || options.mode === 'select') ? " ng-click=\"toggle_" + list.iterator +
"({{ " + list.iterator + ".id }})\"" : "";
html += (field.columnShow) ? Attr(field, 'columnShow') : ""; html += (field.columnShow) ? Attr(field, 'columnShow') : "";
html += (field.ngBindHtml) ? "ng-bind-html-unsafe=\"" + field.ngBindHtml + "\" " : ""; html += (field.ngBindHtml) ? "ng-bind-html-unsafe=\"" + field.ngBindHtml + "\" " : "";
html += ">\n"; html += ">\n";
@@ -465,41 +464,39 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += (field.ngShow) ? "<span " + Attr(field, 'ngShow') + ">" : ""; html += (field.ngShow) ? "<span " + Attr(field, 'ngShow') + ">" : "";
// Badge // Badge
if ( options.mode !== 'lookup' && (field.badges || (field.badgeIcon && field.badgePlacement && field.badgePlacement == 'left')) ) { if (options.mode !== 'lookup' && (field.badges || (field.badgeIcon && field.badgePlacement && field.badgePlacement === 'left'))) {
html += Badge(field); html += Badge(field);
} }
// Add collapse/expand icon --used on job_events page // Add collapse/expand icon --used on job_events page
if (list['hasChildren'] && field.hasChildren) { if (list.hasChildren && field.hasChildren) {
html += "<div class=\"level level-\{\{ " + list.iterator + ".event_level \}\}\"><a href=\"\" ng-click=\"\{\{ " + list.iterator + ".ngclick \}\}\"> " + html += "<div class=\"level level-{{ " + list.iterator + ".event_level }}\"><a href=\"\" ng-click=\"{{ " +
"<i class=\"\{\{ " + list.iterator + ".ngicon \}\}\"></i></a></div>"; list.iterator + ".ngclick }}\"> " +
"<i class=\"{{ " + list.iterator + ".ngicon }}\"></i></a></div>";
//ng-show=\"'\{\{ " + list.iterator + ".related.children \}\}' !== ''\" //ng-show=\"'\{\{ " + list.iterator + ".related.children \}\}' !== ''\"
} }
if (list.name == 'groups') { if (list.name === 'groups') {
html += "<div class=\"group-name\">"; html += "<div class=\"group-name\">";
} }
if (list.name == 'hosts') { if (list.name === 'hosts') {
html += "<div class=\"host-name\">"; html += "<div class=\"host-name\">";
} }
// Start the Link // Start the Link
if ((field.key || field.link || field.linkTo || field.ngClick || field.ngHref) && if ((field.key || field.link || field.linkTo || field.ngClick || field.ngHref) &&
options['mode'] != 'lookup' && options['mode'] != 'select' && !field.noLink && !field.ngBindHtml) { options.mode !== 'lookup' && options.mode !== 'select' && !field.noLink && !field.ngBindHtml) {
var cap=false; cap = false;
if (field.linkTo) { if (field.linkTo) {
html += "<a href=\"" + field.linkTo + "\" "; html += "<a href=\"" + field.linkTo + "\" ";
cap = true; cap = true;
} } else if (field.ngClick) {
else if (field.ngClick) {
html += "<a href=\"\"" + Attr(field, 'ngClick') + " "; html += "<a href=\"\"" + Attr(field, 'ngClick') + " ";
cap = true; cap = true;
} } else if (field.ngHref) {
else if (field.ngHref) {
html += "<a ng-href=\"" + field.ngHref + "\" "; html += "<a ng-href=\"" + field.ngHref + "\" ";
cap = true; cap = true;
} } else if (field.link || (field.key && (field.link === undefined || field.link))) {
else if (field.link || (field.key && (field.link === undefined || field.link))) {
html += "<a href=\"#/" + base + "/{{" + list.iterator + ".id }}\" "; html += "<a href=\"#/" + base + "/{{" + list.iterator + ".id }}\" ";
cap = true; cap = true;
} }
@@ -526,19 +523,17 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
// Add icon: // Add icon:
if (field.ngShowIcon) { if (field.ngShowIcon) {
html += "<i ng-show=\"" + field.ngShowIcon + "\" class=\"" + field.icon + "\"></i> "; html += "<i ng-show=\"" + field.ngShowIcon + "\" class=\"" + field.icon + "\"></i> ";
} } else {
else {
if (field.icon) { if (field.icon) {
html += Icon(field.icon) + " "; html += Icon(field.icon) + " ";
} }
} }
// Add data binds // Add data binds
if (!field.ngBindHtml && (field.showValue == undefined || field.showValue == true)) { if (!field.ngBindHtml && (field.showValue === undefined || field.showValue === true)) {
if (field.ngBind) { if (field.ngBind) {
html += "{{ " + field.ngBind + " }}"; html += "{{ " + field.ngBind + " }}";
} } else {
else {
html += "{{" + list.iterator + "." + fld + "}}"; html += "{{" + list.iterator + "." + fld + "}}";
} }
} }
@@ -553,12 +548,12 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
//} //}
// close the link // close the link
if ( (field.key || field.link || field.linkTo || field.ngClick || field.ngHref ) if ((field.key || field.link || field.linkTo || field.ngClick || field.ngHref) &&
&& options.mode != 'lookup' && options.mode != 'select' && !field.noLink && !field.ngBindHtml ) { options.mode !== 'lookup' && options.mode !== 'select' && !field.noLink && !field.ngBindHtml) {
html += "</a>"; html += "</a>";
} }
if (list.name == 'hosts' || list.name == 'groups') { if (list.name === 'hosts' || list.name === 'groups') {
html += "</div>"; html += "</div>";
} }
@@ -568,7 +563,7 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
// Specific to Job Events page -showing event detail/results // Specific to Job Events page -showing event detail/results
html += (field.appendHTML) ? "<div ng-show=\"" + field.appendHTML + " !== null\" " + html += (field.appendHTML) ? "<div ng-show=\"" + field.appendHTML + " !== null\" " +
"ng-bind-html-unsafe=\"" + field.appendHTML + "\" " + "ng-bind-html-unsafe=\"" + field.appendHTML + "\" " +
"class=\"level-\{\{ " + list.iterator + ".event_level \}\}-detail\" " + "class=\"level-{{ " + list.iterator + ".event_level }}-detail\" " +
"></div>\n" : ""; "></div>\n" : "";
// Badge // Badge
@@ -576,20 +571,21 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += Badge(field); html += Badge(field);
} }
} }
return html += "</td>\n"; return html += "</td>\n";
};
} }
}]) ])
.factory('HelpCollapse', function () { .factory('HelpCollapse', function () {
return function (params) { return function (params) {
var hdr = params.hdr;
var content = params.content; var hdr = params.hdr,
var show = params.show; content = params.content,
var idx = params.idx; show = params.show,
var bind = params.bind; //Pass in scope variable containing html idx = params.idx,
var html = ''; bind = params.bind,
html = '';
html += "<div class=\"panel-group collapsible-help\" "; html += "<div class=\"panel-group collapsible-help\" ";
html += (show) ? "ng-show=\"" + show + "\"" : ""; html += (show) ? "ng-show=\"" + show + "\"" : "";
html += ">\n"; html += ">\n";
@@ -611,7 +607,7 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += "</div>\n"; html += "</div>\n";
html += "</div>\n"; html += "</div>\n";
return html; return html;
} };
}) })
.factory('SearchWidget', function () { .factory('SearchWidget', function () {
@@ -619,13 +615,16 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
// //
// Generate search widget // Generate search widget
// //
var iterator = params.iterator; var iterator = params.iterator,
var form = params.template; form = params.template,
var useMini = params.mini; useMini = params.mini,
var html= ''; fld,
var searchWidgets = (params.searchWidgets) ? params.searchWidgets : 1; i, html = '',
for (var i=1; i <= searchWidgets; i++) { modifier,
var modifier = (i == 1) ? '' : i; searchWidgets = (params.searchWidgets) ? params.searchWidgets : 1;
for (i = 1; i <= searchWidgets; i++) {
modifier = (i === 1) ? '' : i;
html += "<div class=\""; html += "<div class=\"";
html += (params.size) ? params.size : "col-lg-4 col-md-6 col-sm-12 col-xs-12"; html += (params.size) ? params.size : "col-lg-4 col-md-6 col-sm-12 col-xs-12";
html += "\" id=\"search-widget-container" + modifier + "\">\n"; html += "\" id=\"search-widget-container" + modifier + "\">\n";
@@ -643,19 +642,18 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += "<span class=\"caret\"></span>\n"; html += "<span class=\"caret\"></span>\n";
html += "</button>\n"; html += "</button>\n";
html += "<ul class=\"dropdown-menu\" id=\"" + iterator + "SearchDropdown" + modifier + "\">\n"; html += "<ul class=\"dropdown-menu\" id=\"" + iterator + "SearchDropdown" + modifier + "\">\n";
for ( var fld in form.fields) { for (fld in form.fields) {
if ( (form.fields[fld].searchable == undefined || form.fields[fld].searchable == true) if ((form.fields[fld].searchable === undefined || form.fields[fld].searchable === true) &&
&& (((form.fields[fld].searchWidget == undefined || form.fields[fld].searchWidget == 1) && i == 1 ) || (((form.fields[fld].searchWidget === undefined || form.fields[fld].searchWidget === 1) && i === 1) ||
(form.fields[fld].searchWidget == i)) ) { (form.fields[fld].searchWidget === i))) {
html += "<li><a href=\"\" ng-click=\"setSearchField('" + iterator + "','"; html += "<li><a href=\"\" ng-click=\"setSearchField('" + iterator + "','";
html += fld + "','"; html += fld + "','";
if (form.fields[fld].searchLabel) { if (form.fields[fld].searchLabel) {
html += form.fields[fld].searchLabel + "', " + i + ")\">" + html += form.fields[fld].searchLabel + "', " + i + ")\">" +
form.fields[fld].searchLabel + "</a></li>\n"; form.fields[fld].searchLabel + "</a></li>\n";
} } else {
else { html += form.fields[fld].label.replace(/<br \/>/g, ' ') + "', " + i + ")\">" +
html += form.fields[fld].label.replace(/\<br\>/g,' ') + "', " + i + ")\">" + form.fields[fld].label.replace(/<br \/>/g, ' ') + "</a></li>\n";
form.fields[fld].label.replace(/\<br\>/g,' ') + "</a></li>\n";
} }
} }
} }
@@ -702,14 +700,15 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
return html; return html;
} };
}) })
.factory('PaginateWidget', [ function() { .factory('PaginateWidget', [
function () {
return function (params) { return function (params) {
var iterator = params.iterator; var iterator = params.iterator,
var set = params.set; set = params.set,
var html = ''; html = '';
html += "<!-- Paginate Widget -->\n"; html += "<!-- Paginate Widget -->\n";
html += "<div class=\"row page-row\">\n"; html += "<div class=\"row page-row\">\n";
html += "<div class=\"col-lg-8\">\n"; html += "<div class=\"col-lg-8\">\n";
@@ -735,7 +734,6 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
html += "</div>\n"; html += "</div>\n";
return html; return html;
};
} }
}]); ]);

View File

@@ -9,113 +9,44 @@
'use strict'; 'use strict';
angular.module('License', ['RestServices', 'Utilities', 'FormGenerator', 'PromptDialog']) angular.module('License', ['RestServices', 'Utilities', 'FormGenerator', 'PromptDialog', 'LicenseFormDefinition'])
.factory('ViewLicense', ['$location', '$rootScope', 'GenerateForm', 'Rest', 'Alert', 'GetBasePath', 'ProcessErrors', .factory('ViewLicense', ['$location', '$rootScope', 'GenerateForm', 'Rest', 'Alert', 'GetBasePath', 'ProcessErrors',
'FormatDate', 'Prompt', 'Empty', 'FormatDate', 'Prompt', 'Empty', 'LicenseForm',
function($location, $rootScope, GenerateForm, Rest, Alert, GetBasePath, ProcessErrors, FormatDate, Prompt, Empty) { function ($location, $rootScope, GenerateForm, Rest, Alert, GetBasePath, ProcessErrors, FormatDate, Prompt, Empty,
LicenseForm) {
return function () { return function () {
var defaultUrl=GetBasePath('config'); var defaultUrl = GetBasePath('config'),
var generator = GenerateForm; generator = GenerateForm,
form = angular.copy(LicenseForm),
var form = { scope;
name: 'license',
well: false,
forceListeners: true,
fields: {
license_status: {
type: 'custom',
control: '<div class=\"license-status\" ng-class=\"status_color\"><i class="fa fa-circle"></i> \{\{ license_status \}\}</span></div>',
readonly: true,
section: 'License'
},
license_key: {
label: 'Key',
type: 'textarea',
'class': 'modal-input-xlarge',
readonly: true,
section: 'License'
},
license_date: {
label: 'Expires On',
type: 'text',
readonly: true,
section: 'License'
},
time_remaining: {
label: 'Time Left',
type: 'text',
readonly: true,
section: 'License'
},
available_instances: {
label: 'Available',
type: 'text',
readonly: true,
section: 'Managed Hosts'
},
current_instances: {
label: 'Used',
type: 'text',
readonly: true,
section: 'Managed Hosts'
},
free_instances: {
label: 'Remaining',
type: 'text',
readonly: true,
section: 'Managed Hosts',
controlNGClass: 'free_instances_class',
labelNGClass: 'free_instances_class'
},
company_name: {
label: 'Company',
type: 'text',
readonly: true,
section: 'Contact Info'
},
contact_name: {
label: 'Contact',
type: 'text',
readonly: true,
section: 'Contact Info'
},
contact_email: {
label: 'Contact Email',
type: 'text',
readonly: true,
section: 'Contact Info'
}
}
};
var base = $location.path().replace(/^\//,'').split('/')[0];
// Retrieve detail record and prepopulate the form // Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl); Rest.setUrl(defaultUrl);
Rest.get() Rest.get()
.success( function(data, status, headers, config) { .success(function (data) {
for (var fld in form.fields) { var fld, dt, days, remainder, hours, minutes, seconds, license;
if (fld != 'time_remaining' && fld != 'license_status') {
if (Empty(data['license_info'][fld])) { for (fld in form.fields) {
if (fld !== 'time_remaining' && fld !== 'license_status') {
if (Empty(data.license_info[fld])) {
delete form.fields[fld]; delete form.fields[fld];
} }
} }
} }
if (data['license_info']['is_aws'] || Empty(data['license_info']['license_date'])) { if (data.license_info.is_aws || Empty(data.license_info.license_date)) {
delete form.fields['license_date']; delete form.fields.license_date;
delete form.fields['time_remaining']; delete form.fields.time_remaining;
} }
var scope = generator.inject(form, { mode: 'edit', modal: true, related: false}); scope = generator.inject(form, { mode: 'edit', modal: true, related: false });
generator.reset(); generator.reset();
scope.formModalAction = function () { scope.formModalAction = function () {
$('#form-modal').modal("hide"); $('#form-modal').modal("hide");
} };
scope.formModalActionLabel = 'OK'; scope.formModalActionLabel = 'OK';
scope.formModalCancelShow = false; scope.formModalCancelShow = false;
@@ -139,70 +70,68 @@ angular.module('License', ['RestServices', 'Utilities', 'FormGenerator', 'Prompt
window.open(href, 'storeWindow'); window.open(href, 'storeWindow');
} }
}); });
} };
for (var fld in form.fields) { for (fld in form.fields) {
if (!Empty(data['license_info'][fld])) { if (!Empty(data.license_info[fld])) {
scope[fld] = data['license_info'][fld]; scope[fld] = data.license_info[fld];
} }
} }
if (scope['license_date']) { if (scope.license_date) {
var dt = new Date(parseInt(scope['license_date'])); dt = new Date(parseInt(scope.license_date));
if (dt.getFullYear() == '1970') { if (dt.getFullYear() === '1970') {
// date was passed in seconds rather than milliseconds // date was passed in seconds rather than milliseconds
dt = new Date(parseInt(scope['license_date']) * 1000); dt = new Date(parseInt(scope.license_date,10) * 1000);
scope['time_remaining'] = scope['time_remaining'] + '000'; scope.time_remaining = scope.time_remaining + '000';
} }
scope['license_date'] = FormatDate(dt); scope.license_date = FormatDate(dt);
var days = parseInt(scope['time_remaining'] / 86400000); days = parseInt(scope.time_remaining / 86400000, 10);
var remainder = scope['time_remaining'] - (days * 86400000); remainder = scope.time_remaining - (days * 86400000);
var hours = parseInt(remainder / 3600000); hours = parseInt(remainder / 3600000, 10);
remainder = remainder - (hours * 3600000); remainder = remainder - (hours * 3600000);
var minutes = parseInt(remainder / 60000); minutes = parseInt(remainder / 60000, 10);
remainder = remainder - (minutes * 60000); remainder = remainder - (minutes * 60000);
var seconds = parseInt(remainder / 1000); seconds = parseInt(remainder / 1000, 10);
scope['time_remaining'] = days + ' days ' + ('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2) + ':' + ('0' + seconds).slice(-2); scope.time_remaining = days + ' days ' + ('0' + hours).slice(-2) + ':' + ('0' + minutes).slice(-2) + ':' +
('0' + seconds).slice(-2);
} }
if (parseInt(scope['free_instances']) <= 0) { if (parseInt(scope.free_instances) <= 0) {
scope['free_instances_class'] = 'field-failure'; scope.free_instances_class = 'field-failure';
} } else {
else { scope.free_instances_class = 'field-success';
scope['free_instances_class'] = 'field-success';
} }
var license = data['license_info']; license = data.license_info;
if (license['valid_key'] !== undefined && license['valid_key'] == false) { if (license.valid_key !== undefined && !license.valid_key) {
scope['license_status'] = 'Invalid'; scope.license_status = 'Invalid';
scope['status_color'] = 'license-invalid'; scope.status_color = 'license-invalid';
} } else if (license.demo !== undefined && license.demo) {
else if (license['demo'] !== undefined && license['demo'] == true) { scope.license_status = 'Demo';
scope['license_status'] = 'Demo'; scope.status_color = 'license-demo';
scope['status_color'] = 'license-demo'; } else if (license.date_expired !== undefined && license.date_expired) {
} scope.license_status = 'Expired';
else if (license['date_expired'] !== undefined && license['date_expired'] == true) { scope.status_color = 'license-expired';
scope['license_status'] = 'Expired'; } else if (license.date_warning !== undefined && license.date_warning) {
scope['status_color'] = 'license-expired'; scope.license_status = 'Expiration Warning';
} scope.status_color = 'license-warning';
else if (license['date_warning'] !== undefined && license['date_warning'] == true) { } else if (license.free_instances !== undefined && parseInt(license.free_instances) <= 0) {
scope['license_status'] = 'Expiration Warning'; scope.license_status = 'No available managed hosts';
scope['status_color'] = 'license-warning'; scope.status_color = 'license-invalid';
} } else {
else if (license['free_instances'] !== undefined && parseInt(license['free_instances']) <= 0) { scope.license_status = 'Valid';
scope['license_status'] = 'No available managed hosts'; scope.status_color = 'license-valid';
scope['status_color'] = 'license-invalid';
}
else {
scope['license_status'] = 'Valid';
scope['status_color'] = 'license-valid';
} }
}) })
.error( function(data, status, headers, config) { .error(function (data, status) {
ProcessErrors($rootScope, data, status, form, ProcessErrors($rootScope, data, status, form, {
{ hdr: 'Error!', msg: 'Failed to retrieve license. GET status: ' + status }); hdr: 'Error!',
msg: 'Failed to retrieve license. GET status: ' + status
}); });
});
};
} }
}]); ]);

View File

@@ -51,11 +51,9 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
if (options.mode === 'lookup') { if (options.mode === 'lookup') {
element = angular.element(document.getElementById('lookup-modal-body')); element = angular.element(document.getElementById('lookup-modal-body'));
} } else if (options.id) {
else if (options.id) {
element = angular.element(document.getElementById(options.id)); element = angular.element(document.getElementById(options.id));
} } else {
else {
element = angular.element(document.getElementById('htmlTemplate')); element = angular.element(document.getElementById('htmlTemplate'));
} }
this.setList(list); this.setList(list);
@@ -69,8 +67,7 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
if (options.scope) { if (options.scope) {
this.scope = options.scope; this.scope = options.scope;
} } else {
else {
this.scope = element.scope(); // Set scope specific to the element we're compiling, avoids circular reference this.scope = element.scope(); // Set scope specific to the element we're compiling, avoids circular reference
} // From here use 'scope' to manipulate the form, as the form is not in '$scope' } // From here use 'scope' to manipulate the form, as the form is not in '$scope'
@@ -81,11 +78,11 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
this.scope[list.iterator] = null; this.scope[list.iterator] = null;
// Remove any lingering tooltip and popover <div> elements // Remove any lingering tooltip and popover <div> elements
$('.tooltip').each( function(index) { $('.tooltip').each(function() {
$(this).remove(); $(this).remove();
}); });
$('.popover').each(function(index) { $('.popover').each(function() {
// remove lingering popover <div>. Seems to be a bug in TB3 RC1 // remove lingering popover <div>. Seems to be a bug in TB3 RC1
$(this).remove(); $(this).remove();
}); });
@@ -93,8 +90,7 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
try { try {
$('#help-modal').empty().dialog('destroy'); $('#help-modal').empty().dialog('destroy');
} } catch (e) {
catch(e) {
//ignore any errors should the dialog not be initialized //ignore any errors should the dialog not be initialized
} }
@@ -102,7 +98,10 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
// options should include {hdr: <dialog header>, action: <function...> } // options should include {hdr: <dialog header>, action: <function...> }
this.scope.formModalActionDisabled = false; this.scope.formModalActionDisabled = false;
this.scope.lookupHeader = options.hdr; this.scope.lookupHeader = options.hdr;
$('#lookup-modal').modal({ backdrop: 'static', keyboard: true }); $('#lookup-modal').modal({
backdrop: 'static',
keyboard: true
});
$('#lookup-modal').unbind('hidden.bs.modal'); $('#lookup-modal').unbind('hidden.bs.modal');
$(document).bind('keydown', function (e) { $(document).bind('keydown', function (e) {
if (e.keyCode === 27) { if (e.keyCode === 27) {
@@ -119,8 +118,9 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
// Generate HTML. Do NOT call this function directly. Called by inject(). Returns an HTML // Generate HTML. Do NOT call this function directly. Called by inject(). Returns an HTML
// string to be injected into the current view. // string to be injected into the current view.
// //
var html = ''; var html = '',
var list = this.list; list = this.list,
base, size, action, btn, fld, cnt, field_action, fAction, itm;
if (options.activityStream) { if (options.activityStream) {
// Breadcrumbs for activity stream widget // Breadcrumbs for activity stream widget
@@ -128,24 +128,27 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
// before navigation // before navigation
html += "<div class=\"nav-path\">\n"; html += "<div class=\"nav-path\">\n";
html += "<ul class=\"breadcrumb\">\n"; html += "<ul class=\"breadcrumb\">\n";
html += "<li ng-repeat=\"crumb in breadcrumbs\"><a href=\"\" ng-click=\"\{\{ crumb.ngClick \}\}\">{{ crumb.title }}</a></li>\n"; html += "<li ng-repeat=\"crumb in breadcrumbs\"><a href=\"\" " +
"ng-click=\"{{ crumb.ngClick }}\">{{ crumb.title }}</a></li>\n";
html += "<li class=\"active\">"; html += "<li class=\"active\">";
html += list.editTitle; html += list.editTitle;
html += "</li>\n</ul>\n</div>\n"; html += "</li>\n</ul>\n</div>\n";
} } else if (options.mode !== 'lookup' && (options.breadCrumbs === undefined || options.breadCrumbs)) {
else if (options.mode != 'lookup' && (options.breadCrumbs == undefined || options.breadCrumbs == true)) {
//Breadcrumbs //Breadcrumbs
html += Breadcrumbs({ list: list, mode: options.mode }); html += Breadcrumbs({
list: list,
mode: options.mode
});
} }
if (options.mode == 'edit' && list.editInstructions) { if (options.mode === 'edit' && list.editInstructions) {
html += "<div class=\"alert alert-info alert-block\">\n"; html += "<div class=\"alert alert-info alert-block\">\n";
html += "<button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>\n"; html += "<button type=\"button\" class=\"close\" data-dismiss=\"alert\">&times;</button>\n";
html += "<strong>Hint: </strong>" + list.editInstructions + "\n"; html += "<strong>Hint: </strong>" + list.editInstructions + "\n";
html += "</div>\n"; html += "</div>\n";
} }
if (options.mode != 'lookup' && (list.well == undefined || list.well == true)) { if (options.mode !== 'lookup' && (list.well === undefined || list.well)) {
html += "<div class=\"well\">\n"; html += "<div class=\"well\">\n";
} }
@@ -160,42 +163,54 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
html += "<div class=\"row\">\n"; html += "<div class=\"row\">\n";
if (list.name != 'groups') { if (list.name !== 'groups') {
if (options.searchSize) { if (options.searchSize) {
html += SearchWidget({ iterator: list.iterator, template: list, mini: true , size: options.searchSize, html += SearchWidget({
searchWidgets: list.searchWidgets }); iterator: list.iterator,
} template: list,
else if (options.mode == 'summary') { mini: true,
html += SearchWidget({ iterator: list.iterator, template: list, mini: true , size: 'col-lg-6' }); size: options.searchSize,
} searchWidgets: list.searchWidgets
else if (options.mode == 'lookup' || options.id != undefined) { });
html += SearchWidget({ iterator: list.iterator, template: list, mini: true , size: 'col-lg-8' }); } else if (options.mode === 'summary') {
} html += SearchWidget({
else { iterator: list.iterator,
html += SearchWidget({ iterator: list.iterator, template: list, mini: true }); template: list,
mini: true,
size: 'col-lg-6'
});
} else if (options.mode === 'lookup' || options.id !== undefined) {
html += SearchWidget({
iterator: list.iterator,
template: list,
mini: true,
size: 'col-lg-8'
});
} else {
html += SearchWidget({
iterator: list.iterator,
template: list,
mini: true
});
} }
} }
if (options.mode != 'lookup') { if (options.mode !== 'lookup') {
//actions //actions
var base = $location.path().replace(/^\//,'').split('/')[0]; base = $location.path().replace(/^\//, '').split('/')[0];
html += "<div class=\""; html += "<div class=\"";
if (list.name == 'groups') { if (list.name === 'groups') {
html += "col-lg-12"; html += "col-lg-12";
} } else if (options.searchSize) {
else if (options.searchSize) {
// User supplied searchSize, calc the remaining // User supplied searchSize, calc the remaining
var size = parseInt(options.searchSize.replace(/([A-Z]|[a-z]|\-)/g,'')); size = parseInt(options.searchSize.replace(/([A-Z]|[a-z]|\-)/g, ''));
size = (list.searchWidgets) ? list.searchWidgets * size : size; size = (list.searchWidgets) ? list.searchWidgets * size : size;
html += 'col-lg-' + (12 - size); html += 'col-lg-' + (12 - size);
} } else if (options.mode === 'summary') {
else if (options.mode == 'summary') {
html += 'col-lg-6'; html += 'col-lg-6';
} } else if (options.id !== undefined) {
else if (options.id != undefined) {
html += "col-lg-4"; html += "col-lg-4";
} } else {
else {
html += "col-lg-8 col-md-6"; html += "col-lg-8 col-md-6";
} }
html += "\">\n"; html += "\">\n";
@@ -203,18 +218,22 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
html += "<div class=\"list-actions\">\n"; html += "<div class=\"list-actions\">\n";
// Add toolbar buttons or 'actions' // Add toolbar buttons or 'actions'
for (var action in list.actions) { for (action in list.actions) {
if (list.actions[action].mode == 'all' || list.actions[action].mode == options.mode) { if (list.actions[action].mode === 'all' || list.actions[action].mode === options.mode) {
if ( (list.actions[action].basePaths == undefined) || if ((list.actions[action].basePaths === undefined) ||
(list.actions[action].basePaths && list.actions[action].basePaths.indexOf(base) > -1)) { (list.actions[action].basePaths && list.actions[action].basePaths.indexOf(base) > -1)) {
html += this.button({ btn: list.actions[action], action: action, toolbar: true }); html += this.button({
btn: list.actions[action],
action: action,
toolbar: true
});
} }
} }
} }
//select instructions //select instructions
if (options.mode == 'select' && list.selectInstructions) { if (options.mode === 'select' && list.selectInstructions) {
var btn = { btn = {
awPopOver: list.selectInstructions, awPopOver: list.selectInstructions,
dataPlacement: 'top', dataPlacement: 'top',
dataContainer: 'body', dataContainer: 'body',
@@ -224,13 +243,16 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
iconSize: 'fa-lg' iconSize: 'fa-lg'
}; };
//html += this.button(btn, 'select'); //html += this.button(btn, 'select');
html += this.button({ btn: btn, action: 'help', toolbar: true }); html += this.button({
btn: btn,
action: 'help',
toolbar: true
});
} }
html += "</div><!-- list-acitons -->\n"; html += "</div><!-- list-acitons -->\n";
html += "</div><!-- list-actions-column -->\n"; html += "</div><!-- list-actions-column -->\n";
} } else {
else {
//lookup //lookup
html += "<div class=\"col-lg-7\"></div>\n"; html += "<div class=\"col-lg-7\"></div>\n";
} }
@@ -240,18 +262,18 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
// Add a title and optionally a close button (used on Inventory->Groups) // Add a title and optionally a close button (used on Inventory->Groups)
if (options.mode !== 'lookup' && list.showTitle) { if (options.mode !== 'lookup' && list.showTitle) {
html += "<div class=\"form-title\">"; html += "<div class=\"form-title\">";
html += (options.mode == 'edit' || options.mode == 'summary') ? list.editTitle : list.addTitle; html += (options.mode === 'edit' || options.mode === 'summary') ? list.editTitle : list.addTitle;
html += "</div>\n"; html += "</div>\n";
} }
// table header row // table header row
html += "<table id=\"" + list.name + "_table\" "; html += "<table id=\"" + list.name + "_table\" ";
html += "class=\"table" html += "class=\"table";
html += (list['class']) ? " " + list['class'] : ""; html += (list['class']) ? " " + list['class'] : "";
html += (options.mode !== 'summary' && options.mode !== 'edit' && (options.mode == 'lookup' || options.id)) ? html += (options.mode !== 'summary' && options.mode !== 'edit' && (options.mode === 'lookup' || options.id)) ?
' table-hover-inverse' : ''; ' table-hover-inverse' : '';
html += (list.hover) ? ' table-hover' : ''; html += (list.hover) ? ' table-hover' : '';
html += (options.mode == 'summary') ? ' table-summary' : ''; html += (options.mode === 'summary') ? ' table-summary' : '';
html += "\" "; html += "\" ";
html += ">\n"; html += ">\n";
html += "<thead>\n"; html += "<thead>\n";
@@ -259,9 +281,9 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
if (list.index) { if (list.index) {
html += "<th class=\"col-lg-1 col-md-1 col-sm-1 hidden-xs\">#</th>\n"; html += "<th class=\"col-lg-1 col-md-1 col-sm-1 hidden-xs\">#</th>\n";
} }
for (var fld in list.fields) { for (fld in list.fields) {
if ( (list.fields[fld].searchOnly == undefined || list.fields[fld].searchOnly == false) && if ((list.fields[fld].searchOnly === undefined || list.fields[fld].searchOnly === false) &&
!(options.mode == 'lookup' && list.fields[fld].excludeModal !== undefined && list.fields[fld].excludeModal == true) ) { !(options.mode === 'lookup' && list.fields[fld].excludeModal !== undefined && list.fields[fld].excludeModal === true)) {
html += "<th class=\"list-header"; html += "<th class=\"list-header";
html += (list.fields[fld].columnClass) ? " " + list.fields[fld].columnClass : ""; html += (list.fields[fld].columnClass) ? " " + list.fields[fld].columnClass : "";
html += "\" id=\""; html += "\" id=\"";
@@ -276,12 +298,10 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
if (list.fields[fld].key) { if (list.fields[fld].key) {
if (list.fields[fld].desc) { if (list.fields[fld].desc) {
html += "fa-sort-down"; html += "fa-sort-down";
} } else {
else {
html += "fa-sort-up"; html += "fa-sort-up";
} }
} } else {
else {
html += "fa-sort"; html += "fa-sort";
} }
html += "\"></i></a>"; html += "\"></i></a>";
@@ -289,10 +309,9 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
html += "</th>\n"; html += "</th>\n";
} }
} }
if (options.mode == 'select' || options.mode == 'lookup') { if (options.mode === 'select' || options.mode === 'lookup') {
html += "<th>Select</th>"; html += "<th>Select</th>";
} } else if (options.mode === 'edit' && list.fieldActions) {
else if (options.mode == 'edit' && list.fieldActions) {
html += "<th class=\"actions-column"; html += "<th class=\"actions-column";
html += (list.fieldActions && list.fieldActions.columnClass) ? " " + list.fieldActions.columnClass : ""; html += (list.fieldActions && list.fieldActions.columnClass) ? " " + list.fieldActions.columnClass : "";
html += "\">Actions</th>\n"; html += "\">Actions</th>\n";
@@ -303,7 +322,7 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
// table body // table body
html += "<tbody>\n"; html += "<tbody>\n";
html += "<tr ng-class=\"" + list.iterator; html += "<tr ng-class=\"" + list.iterator;
html += (options.mode == 'lookup' || options.mode == 'select') ? ".success_class" : ".active_class"; html += (options.mode === 'lookup' || options.mode === 'select') ? ".success_class" : ".active_class";
html += "\" "; html += "\" ";
html += "class=\"" + list.iterator + "_class\" ng-repeat=\"" + list.iterator + " in " + list.name; html += "class=\"" + list.iterator + "_class\" ng-repeat=\"" + list.iterator + " in " + list.name;
html += (list.orderBy) ? " | orderBy:'" + list.orderBy + "'" : ""; html += (list.orderBy) ? " | orderBy:'" + list.orderBy + "'" : "";
@@ -313,33 +332,36 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
if (list.index) { if (list.index) {
html += "<td class=\"index-column hidden-xs\">{{ $index + ((" + list.iterator + "_page - 1) * " + list.iterator + "_page_size) + 1 }}.</td>\n"; html += "<td class=\"index-column hidden-xs\">{{ $index + ((" + list.iterator + "_page - 1) * " + list.iterator + "_page_size) + 1 }}.</td>\n";
} }
var cnt = 2; cnt = 2;
var base = (list.base) ? list.base : list.name; base = (list.base) ? list.base : list.name;
base = base.replace(/^\//, ''); base = base.replace(/^\//, '');
for (fld in list.fields) { for (fld in list.fields) {
cnt++; cnt++;
if ( (list.fields[fld].searchOnly == undefined || list.fields[fld].searchOnly == false) && if ((list.fields[fld].searchOnly === undefined || list.fields[fld].searchOnly === false) &&
!(options.mode == 'lookup' && list.fields[fld].excludeModal !== undefined && list.fields[fld].excludeModal == true) ) { !(options.mode === 'lookup' && list.fields[fld].excludeModal !== undefined &&
html += Column({ list: list, fld: fld, options: options, base: base }); list.fields[fld].excludeModal === true)) {
html += Column({
list: list,
fld: fld,
options: options,
base: base
});
} }
} }
if (options.mode == 'select' || options.mode == 'lookup') { if (options.mode === 'select' || options.mode === 'lookup') {
html += "<td><input type=\"checkbox\" ng-model=\"" + list.iterator + ".checked\" name=\"check_{{" + html += "<td><input type=\"checkbox\" ng-model=\"" + list.iterator + ".checked\" name=\"check_{{" +
list.iterator + ".id }}\" ng-click=\"toggle_" + list.iterator + "({{ " + list.iterator + ".id }}, true)\" ng-true-value=\"1\" " + list.iterator + ".id }}\" ng-click=\"toggle_" + list.iterator + "({{ " + list.iterator + ".id }}, true)\" ng-true-value=\"1\" " +
"ng-false-value=\"0\" id=\"check_{{" + list.iterator + ".id}}\" /></td>"; "ng-false-value=\"0\" id=\"check_{{" + list.iterator + ".id}}\" /></td>";
} } else if ((options.mode === 'edit' || options.mode === 'summary') && list.fieldActions) {
else if ((options.mode == 'edit' || options.mode == 'summary') && list.fieldActions) {
// Row level actions // Row level actions
html += "<td class=\"actions\">"; html += "<td class=\"actions\">";
var field_action, fAction, itm;
for (field_action in list.fieldActions) { for (field_action in list.fieldActions) {
if (field_action !== 'columnClass') { if (field_action !== 'columnClass') {
if (list.fieldActions[field_action].type && list.fieldActions[field_action].type == 'DropDown') { if (list.fieldActions[field_action].type && list.fieldActions[field_action].type === 'DropDown') {
html += DropDown({ html += DropDown({
list: list, list: list,
fld: field_action, fld: field_action,
@@ -348,30 +370,30 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
type: 'fieldActions', type: 'fieldActions',
td: false td: false
}); });
} } else {
else {
fAction = list.fieldActions[field_action]; fAction = list.fieldActions[field_action];
html += "<a "; html += "<a ";
html += (fAction.href) ? "href=\"" + fAction.href + "\" " : ""; html += (fAction.href) ? "href=\"" + fAction.href + "\" " : "";
html += (fAction.ngHref) ? "ng-href=\"" + fAction.ngHref + "\" " : ""; html += (fAction.ngHref) ? "ng-href=\"" + fAction.ngHref + "\" " : "";
html += (field_action == 'cancel') ? "class=\"cancel red-txt\" " : ""; html += (field_action === 'cancel') ? "class=\"cancel red-txt\" " : "";
html += (fAction.awPopOver) ? "aw-pop-over=\"" + fAction.awPopOver + "\" " : ""; html += (fAction.awPopOver) ? "aw-pop-over=\"" + fAction.awPopOver + "\" " : "";
html += (fAction.dataPlacement) ? Attr(fAction, 'dataPlacement') : ""; html += (fAction.dataPlacement) ? Attr(fAction, 'dataPlacement') : "";
html += (fAction.dataTitle) ? Attr(fAction, 'dataTitle') : ""; html += (fAction.dataTitle) ? Attr(fAction, 'dataTitle') : "";
for (itm in fAction) { for (itm in fAction) {
if (itm != 'ngHref' && itm != 'href' && itm != 'label' && itm != 'icon' && itm != 'class' && if (itm !== 'ngHref' && itm !== 'href' && itm !== 'label' && itm !== 'icon' && itm !== 'class' &&
itm != 'iconClass' && itm != "dataPlacement" && itm != "awPopOver" && itm != "dataTitle") { itm !== 'iconClass' && itm !== "dataPlacement" && itm !== "awPopOver" && itm !== "dataTitle") {
html += Attr(fAction, itm); html += Attr(fAction, itm);
} }
} }
html += ">"; html += ">";
if (fAction.iconClass) { if (fAction.iconClass) {
html += "<i class=\"" + fAction.iconClass + "\"></i>"; html += "<i class=\"" + fAction.iconClass + "\"></i>";
} else {
html += SelectIcon({
action: field_action
});
} }
else { html += (fAction.label) ? " " + list.fieldActions[field_action].label : "";
html += SelectIcon({ action: field_action });
}
html += (fAction.label) ? " " + list.fieldActions[field_action]['label'] : "";
html += "</a>"; html += "</a>";
} }
} }
@@ -394,28 +416,33 @@ function($location, $compile, $rootScope, SearchWidget, PaginateWidget, Attr, Ic
html += "</tbody>\n"; html += "</tbody>\n";
html += "</table>\n"; html += "</table>\n";
if (options.mode == 'select' && (options.selectButton == undefined || options.selectButton == true)) { if (options.mode === 'select' && (options.selectButton === undefined || options.selectButton)) {
html += "<div class=\"navigation-buttons\">\n"; html += "<div class=\"navigation-buttons\">\n";
html += " <button class=\"btn btn-sm btn-primary pull-right\" aw-tool-tip=\"Complete your selection\" " + html += " <button class=\"btn btn-sm btn-primary pull-right\" aw-tool-tip=\"Complete your selection\" " +
"ng-click=\"finishSelection()\" ng-disabled=\"disableSelectBtn\"><i class=\"fa fa-check\"></i> Select</button>\n"; "ng-click=\"finishSelection()\" ng-disabled=\"disableSelectBtn\"><i class=\"fa fa-check\"></i> Select</button>\n";
html += "</div>\n"; html += "</div>\n";
} }
if (options.mode != 'lookup' && (list.well == undefined || list.well == true)) { if (options.mode !== 'lookup' && (list.well === undefined || list.well === true)) {
html += "</div>\n"; //well html += "</div>\n"; //well
} }
if (list.name !== 'groups') { if (list.name !== 'groups') {
if ( options.mode == 'lookup' || (options.id && options.id == "form-modal-body") ) { if (options.mode === 'lookup' || (options.id && options.id === "form-modal-body")) {
html += PaginateWidget({ set: list.name, iterator: list.iterator }); html += PaginateWidget({
} set: list.name,
else { iterator: list.iterator
html += PaginateWidget({ set: list.name, iterator: list.iterator }); });
} else {
html += PaginateWidget({
set: list.name,
iterator: list.iterator
});
} }
} }
return html; return html;
} }
};
}}]); }
]);

View File

@@ -17,17 +17,18 @@
'use strict'; 'use strict';
angular.module('PromptDialog', ['Utilities']) angular.module('PromptDialog', ['Utilities'])
.factory('Prompt', ['$rootScope', '$compile', 'Alert', function($rootScope, $compile, Alert) { .factory('Prompt', [
function () {
return function (params) { return function (params) {
var dialog = angular.element(document.getElementById('prompt-modal')); var dialog = angular.element(document.getElementById('prompt-modal')),
var scope = dialog.scope(); scope = dialog.scope(), cls;
scope.promptHeader = params.hdr; scope.promptHeader = params.hdr;
scope.promptBody = params.body; scope.promptBody = params.body;
scope.promptAction = params.action; scope.promptAction = params.action;
var cls = (params['class'] == null || params['class'] == undefined) ? 'btn-danger' : params['class']; cls = (params['class'] === null || params['class'] === undefined) ? 'btn-danger' : params['class'];
$('#prompt_action_btn').removeClass(cls).addClass(cls); $('#prompt_action_btn').removeClass(cls).addClass(cls);
@@ -36,6 +37,6 @@ angular.module('PromptDialog', ['Utilities'])
keyboard: true, keyboard: true,
show: true show: true
}); });
};
} }
}]); ]);

View File

@@ -22,74 +22,151 @@
** 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ** 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
** **
** **
** CLH 9/5/13 - Set required strength in config.js ** CLH 09/05/13 - Set required strength in config.js
** 02/10/14 - Applied jsHint
*/ */
/*jshint eqeqeq:false, unused:false */
String.prototype.strReverse = function () { String.prototype.strReverse = function () {
var newstring = ""; var newstring = "", s;
for (var s=0; s < this.length; s++) { for (s = 0; s < this.length; s++) {
newstring = this.charAt(s) + newstring; newstring = this.charAt(s) + newstring;
} }
return newstring; return newstring;
}; };
var nScore = 0; var nScore = 0;
function chkPass(pwd) { function chkPass(pwd) {
// Simultaneous variable declaration and value assignment aren't supported in IE apparently // Simultaneous variable declaration and value assignment aren't supported in IE apparently
// so I'm forced to assign the same value individually per var to support a crappy browser *sigh* // so I'm forced to assign the same value individually per var to support a crappy browser *sigh*
var nLength=0, nAlphaUC=0, nAlphaLC=0, nNumber=0, nSymbol=0, nMidChar=0, nRequirements=0, var nLength = 0,
nAlphasOnly=0, nNumbersOnly=0, nUnqChar=0, nRepChar=0, nRepInc=0, nConsecAlphaUC=0, nConsecAlphaLC=0, nAlphaUC = 0,
nConsecNumber=0, nConsecSymbol=0, nConsecCharType=0, nSeqAlpha=0, nSeqNumber=0, nSeqSymbol=0, nAlphaLC = 0,
nSeqChar=0, nReqChar=0, nMultConsecCharType=0; nNumber = 0,
var nMultRepChar=1, nMultConsecSymbol=1; nSymbol = 0,
var nMultMidChar=2, nMultRequirements=2, nMultConsecAlphaUC=2, nMultConsecAlphaLC=2, nMultConsecNumber=2; nMidChar = 0,
var nReqCharType=3, nMultAlphaUC=3, nMultAlphaLC=3, nMultSeqAlpha=3, nMultSeqNumber=3, nMultSeqSymbol=3; nRequirements = 0,
var nMultLength=4, nMultNumber=4; nAlphasOnly = 0,
var nMultSymbol=6; nNumbersOnly = 0,
var nTmpAlphaUC="", nTmpAlphaLC="", nTmpNumber="", nTmpSymbol=""; nUnqChar = 0,
var sAlphaUC="0", sAlphaLC="0", sNumber="0", sSymbol="0", sMidChar="0", sRequirements="0", nRepChar = 0,
sAlphasOnly="0", sNumbersOnly="0", sRepChar="0", sConsecAlphaUC="0", sConsecAlphaLC="0", nRepInc = 0,
sConsecNumber="0", sSeqAlpha="0", sSeqNumber="0", sSeqSymbol="0"; nConsecAlphaUC = 0,
var sAlphas = "abcdefghijklmnopqrstuvwxyz"; nConsecAlphaLC = 0,
var sNumerics = "01234567890"; nConsecNumber = 0,
var sSymbols = ")_!@#$%^&*()"; nConsecSymbol = 0,
var sComplexity = "Too Short"; nConsecCharType = 0,
var sStandards = "Below"; nSeqAlpha = 0,
var nMinPwdLen = 8; nSeqNumber = 0,
if (document.all) { var nd = 0; } else { var nd = 1; } nSeqSymbol = 0,
nSeqChar = 0,
nReqChar = 0,
nMultConsecCharType = 0,
nMultRepChar = 1,
nMultConsecSymbol = 1,
nMultMidChar = 2,
nMultRequirements = 2,
nMultConsecAlphaUC = 2,
nMultConsecAlphaLC = 2,
nMultConsecNumber = 2,
nReqCharType = 3,
nMultAlphaUC = 3,
nMultAlphaLC = 3,
nMultSeqAlpha = 3,
nMultSeqNumber = 3,
nMultSeqSymbol = 3,
nMultLength = 4,
nMultNumber = 4,
nMultSymbol = 6,
nTmpAlphaUC = "",
nTmpAlphaLC = "",
nTmpNumber = "",
nTmpSymbol = "",
sAlphaUC = "0",
sAlphaLC = "0",
sNumber = "0",
sSymbol = "0",
sMidChar = "0",
sRequirements = "0",
sAlphasOnly = "0",
sNumbersOnly = "0",
sRepChar = "0",
sConsecAlphaUC = "0",
sConsecAlphaLC = "0",
sConsecNumber = "0",
sSeqAlpha = "0",
sSeqNumber = "0",
sSeqSymbol = "0",
sAlphas = "abcdefghijklmnopqrstuvwxyz",
sNumerics = "01234567890",
sSymbols = ")_!@#$%^&*()",
sComplexity = "Too Short",
sStandards = "Below",
nMinPwdLen = 8,
a, nd, arrPwd, arrPwdLen,bCharExists,b,s,sFwd,sRev,progbar,required_strength,warning_level;
if (document.all) {
nd = 0;
} else {
nd = 1;
}
if (pwd) { if (pwd) {
nScore = parseInt(pwd.length * nMultLength); nScore = parseInt(pwd.length * nMultLength);
nLength = pwd.length; nLength = pwd.length;
var arrPwd = pwd.replace(/\s+/g,"").split(/\s*/); arrPwd = pwd.replace(/\s+/g, "").split(/\s*/);
var arrPwdLen = arrPwd.length; arrPwdLen = arrPwd.length;
/* Loop through password to check for Symbol, Numeric, Lowercase and Uppercase pattern matches */ /* Loop through password to check for Symbol, Numeric, Lowercase and Uppercase pattern matches */
for (var a=0; a < arrPwdLen; a++) { for (a = 0; a < arrPwdLen; a++) {
if (arrPwd[a].match(/[A-Z]/g)) { if (arrPwd[a].match(/[A-Z]/g)) {
if (nTmpAlphaUC !== "") { if ((nTmpAlphaUC + 1) == a) { nConsecAlphaUC++; nConsecCharType++; } } if (nTmpAlphaUC !== "") {
if ((nTmpAlphaUC + 1) == a) {
nConsecAlphaUC++;
nConsecCharType++;
}
}
nTmpAlphaUC = a; nTmpAlphaUC = a;
nAlphaUC++; nAlphaUC++;
} else if (arrPwd[a].match(/[a-z]/g)) {
if (nTmpAlphaLC !== "") {
if ((nTmpAlphaLC + 1) == a) {
nConsecAlphaLC++;
nConsecCharType++;
}
} }
else if (arrPwd[a].match(/[a-z]/g)) {
if (nTmpAlphaLC !== "") { if ((nTmpAlphaLC + 1) == a) { nConsecAlphaLC++; nConsecCharType++; } }
nTmpAlphaLC = a; nTmpAlphaLC = a;
nAlphaLC++; nAlphaLC++;
} else if (arrPwd[a].match(/[0-9]/g)) {
if (a > 0 && a < (arrPwdLen - 1)) {
nMidChar++;
}
if (nTmpNumber !== "") {
if ((nTmpNumber + 1) == a) {
nConsecNumber++;
nConsecCharType++;
}
} }
else if (arrPwd[a].match(/[0-9]/g)) {
if (a > 0 && a < (arrPwdLen - 1)) { nMidChar++; }
if (nTmpNumber !== "") { if ((nTmpNumber + 1) == a) { nConsecNumber++; nConsecCharType++; } }
nTmpNumber = a; nTmpNumber = a;
nNumber++; nNumber++;
} else if (arrPwd[a].match(/[^a-zA-Z0-9_]/g)) {
if (a > 0 && a < (arrPwdLen - 1)) {
nMidChar++;
}
if (nTmpSymbol !== "") {
if ((nTmpSymbol + 1) == a) {
nConsecSymbol++;
nConsecCharType++;
}
} }
else if (arrPwd[a].match(/[^a-zA-Z0-9_]/g)) {
if (a > 0 && a < (arrPwdLen - 1)) { nMidChar++; }
if (nTmpSymbol !== "") { if ((nTmpSymbol + 1) == a) { nConsecSymbol++; nConsecCharType++; } }
nTmpSymbol = a; nTmpSymbol = a;
nSymbol++; nSymbol++;
} }
/* Internal loop through password to check for repeat characters */ /* Internal loop through password to check for repeat characters */
var bCharExists = false; bCharExists = false;
for (var b=0; b < arrPwdLen; b++) { for (b = 0; b < arrPwdLen; b++) {
if (arrPwd[a] == arrPwd[b] && a != b) { /* repeat character exists */ if (arrPwd[a] == arrPwd[b] && a != b) { /* repeat character exists */
bCharExists = true; bCharExists = true;
/* /*
@@ -109,24 +186,33 @@ function chkPass(pwd) {
} }
/* Check for sequential alpha string patterns (forward and reverse) */ /* Check for sequential alpha string patterns (forward and reverse) */
for (var s=0; s < 23; s++) { for (s = 0; s < 23; s++) {
var sFwd = sAlphas.substring(s,parseInt(s+3)); sFwd = sAlphas.substring(s, parseInt(s + 3));
var sRev = sFwd.strReverse(); sRev = sFwd.strReverse();
if (pwd.toLowerCase().indexOf(sFwd) != -1 || pwd.toLowerCase().indexOf(sRev) != -1) { nSeqAlpha++; nSeqChar++;} if (pwd.toLowerCase().indexOf(sFwd) != -1 || pwd.toLowerCase().indexOf(sRev) != -1) {
nSeqAlpha++;
nSeqChar++;
}
} }
/* Check for sequential numeric string patterns (forward and reverse) */ /* Check for sequential numeric string patterns (forward and reverse) */
for (var s=0; s < 8; s++) { for (s = 0; s < 8; s++) {
var sFwd = sNumerics.substring(s,parseInt(s+3)); sFwd = sNumerics.substring(s, parseInt(s + 3));
var sRev = sFwd.strReverse(); sRev = sFwd.strReverse();
if (pwd.toLowerCase().indexOf(sFwd) != -1 || pwd.toLowerCase().indexOf(sRev) != -1) { nSeqNumber++; nSeqChar++;} if (pwd.toLowerCase().indexOf(sFwd) != -1 || pwd.toLowerCase().indexOf(sRev) != -1) {
nSeqNumber++;
nSeqChar++;
}
} }
/* Check for sequential symbol string patterns (forward and reverse) */ /* Check for sequential symbol string patterns (forward and reverse) */
for (var s=0; s < 8; s++) { for (s = 0; s < 8; s++) {
var sFwd = sSymbols.substring(s,parseInt(s+3)); sFwd = sSymbols.substring(s, parseInt(s + 3));
var sRev = sFwd.strReverse(); sRev = sFwd.strReverse();
if (pwd.toLowerCase().indexOf(sFwd) != -1 || pwd.toLowerCase().indexOf(sRev) != -1) { nSeqSymbol++; nSeqChar++;} if (pwd.toLowerCase().indexOf(sFwd) != -1 || pwd.toLowerCase().indexOf(sRev) != -1) {
nSeqSymbol++;
nSeqChar++;
}
} }
/* Modify overall score value based on usage vs requirements */ /* Modify overall score value based on usage vs requirements */
@@ -194,33 +280,36 @@ function chkPass(pwd) {
} }
/* Determine complexity based on overall score */ /* Determine complexity based on overall score */
if (nScore > 100) { nScore = 100; } else if (nScore < 0) { nScore = 0; } if (nScore > 100) {
nScore = 100;
} else if (nScore < 0) {
nScore = 0;
}
var progbar = $("#progbar"); progbar = $("#progbar");
var required_strength = $AnsibleConfig.password_strength; required_strength = $AnsibleConfig.password_strength;
var warning_level = ($AnsibleConfig.password_strength - 15 < 0) ? 0 : $AnsibleConfig.password_strength - 15; warning_level = ($AnsibleConfig.password_strength - 15 < 0) ? 0 : $AnsibleConfig.password_strength - 15;
progbar.css("width", nScore + '%'); progbar.css("width", nScore + '%');
if (nScore >= 0 && nScore <= warning_level) { if (nScore >= 0 && nScore <= warning_level) {
sComplexity = 'Weak'; sComplexity = 'Weak';
progbar.addClass('progress-bar-danger') progbar.addClass('progress-bar-danger');
progbar.removeClass('progress-bar-success progress-bar-warning') progbar.removeClass('progress-bar-success progress-bar-warning');
} else if (nScore > warning_level && nScore <= required_strength) { } else if (nScore > warning_level && nScore <= required_strength) {
sComplexity = 'Good'; sComplexity = 'Good';
progbar.addClass('progress-bar-warning') progbar.addClass('progress-bar-warning');
progbar.removeClass('progress-bar-success progress-bar-danger') progbar.removeClass('progress-bar-success progress-bar-danger');
} else if (nScore > required_strength) { } else if (nScore > required_strength) {
sComplexity = "Strong"; sComplexity = "Strong";
progbar.addClass('progress-bar-success') progbar.addClass('progress-bar-success');
progbar.removeClass('progress-bar-warning progress-bar-danger') progbar.removeClass('progress-bar-warning progress-bar-danger');
} }
} } else {
else {
/* no password, so reset the displays */ /* no password, so reset the displays */
var progbar = $("#progbar"); progbar = $("#progbar");
progbar.css("width", '0%'); progbar.css("width", '0%');
progbar.removeClass('progress-bar-success progress-bar-warning') progbar.removeClass('progress-bar-success progress-bar-warning');
} }
return nScore; return nScore;
} }

View File

@@ -71,10 +71,11 @@
<script src="{{ STATIC_URL }}js/forms/ProjectStatus.js"></script> <script src="{{ STATIC_URL }}js/forms/ProjectStatus.js"></script>
<script src="{{ STATIC_URL }}js/forms/Permissions.js"></script> <script src="{{ STATIC_URL }}js/forms/Permissions.js"></script>
<script src="{{ STATIC_URL }}js/forms/JobEventData.js"></script> <script src="{{ STATIC_URL }}js/forms/JobEventData.js"></script>
<script src="{{ STATIC_URL }}js/forms/JobEvents.js"></script>
<script src="{{ STATIC_URL }}js/forms/HostGroups.js"></script> <script src="{{ STATIC_URL }}js/forms/HostGroups.js"></script>
<script src="{{ STATIC_URL }}js/forms/InventoryStatus.js"></script>
<script src="{{ STATIC_URL }}js/forms/ActivityDetail.js"></script> <script src="{{ STATIC_URL }}js/forms/ActivityDetail.js"></script>
<script src="{{ STATIC_URL }}js/forms/JobSummary.js"></script> <script src="{{ STATIC_URL }}js/forms/JobSummary.js"></script>
<script src="{{ STATIC_URL }}js/forms/LicenseForm.js"></script>
<script src="{{ STATIC_URL }}js/lists/Users.js"></script> <script src="{{ STATIC_URL }}js/lists/Users.js"></script>
<script src="{{ STATIC_URL }}js/lists/Organizations.js"></script> <script src="{{ STATIC_URL }}js/lists/Organizations.js"></script>
<script src="{{ STATIC_URL }}js/lists/Admins.js"></script> <script src="{{ STATIC_URL }}js/lists/Admins.js"></script>
@@ -123,7 +124,6 @@
<script src="{{ STATIC_URL }}js/widgets/ObjectCount.js"></script> <script src="{{ STATIC_URL }}js/widgets/ObjectCount.js"></script>
<script src="{{ STATIC_URL }}js/widgets/Stream.js"></script> <script src="{{ STATIC_URL }}js/widgets/Stream.js"></script>
<script src="{{ STATIC_URL }}js/help/InventoryGroups.js"></script> <script src="{{ STATIC_URL }}js/help/InventoryGroups.js"></script>
<script src="{{ STATIC_URL }}js/help/InventoryHosts.js"></script>
<script src="{{ STATIC_URL }}lib/less/less-1.4.1.min.js"></script> <script src="{{ STATIC_URL }}lib/less/less-1.4.1.min.js"></script>
{% endif %} {% endif %}

9
package.json Normal file
View File

@@ -0,0 +1,9 @@
{
"name": "ansible-commander",
"version": "1.4.5",
"devDependencies": {
"grunt": "latest",
"grunt-contrib-jshint": "~0.8.0",
"grunt-contrib-uglify": "~0.3.1"
}
}