Merge remote-tracking branch 'origin/master' into zeromq

* origin/master: (36 commits)
  AC-564 fixed a bug with CodeMirror editor and post dialog removal/cleanup.
  AC-564 fixed a bug with CodeMirror editor and post dialog removal/cleanup.
  AC-564 added new method to codemirror wrapper to enable replacing textarea fields with an editor. Implemented in inventory, groups, hosts, and templates. Solved issues with groups related to two potential textareas at the same time. Found and fixed an error in the way ReturnToCaller() utility was being called. Finished implementing angular-md5. Adding or saving a job template now shows a pop-up on save when a callback is enabled. The pop-up shows the callback url and host key. Before user had to save and then re-open the template to get the URL. With the pop-up we're now showing it immmediately on save.
  AC-564 added new method to codemirror wrapper to enable replacing textarea fields with an editor. Implemented in inventory, groups, hosts, and templates. Solved issues with groups related to two potential textareas at the same time. Found and fixed an error in the way ReturnToCaller() utility was being called. Finished implementing angular-md5. Adding or saving a job template now shows a pop-up on save when a callback is enabled. The pop-up shows the callback url and host key. Before user had to save and then re-open the template to get the URL. With the pop-up we're now showing it immmediately on save.
  Fixed broken links where ngHref is used in list objects.
  Fixed js error post host edit save.
  Fixed menu bar height. After TB upgrade it was fixed at 50px. Moved back to 0 and let image height be dominant. Pulled in angular-codemirror overlay fix.
  Install add-apt-repository during AMI build
  Assume yes when adding PPA
  UUID will always be random
  Don't forget to install the PPA
  Fixed twiter js package. Now repo includes dist subdir.
  Fixing twitter js library
  Update to latest ubuntu-12.04 base AMI
  Include awx.min.js in sdist packaging
  Add 'npm install' task to the make process
  AC-564 implemented angular-codemirror to provide JSON/YAML syntax highlighting and linting in a full-screen editor.
  Fix issue AC-977 by including job_template in summary fields for job activity stream events
  Fixed a bug in Groups.js helper that blocked GroupsEdit, so you couldn't edit an existing group. Issue was Angular depenedency ineject was misaligned with function parameters.
  AC-725 Added tower version to app footer and license dialog. Refactored license dialog to use tabs rather than accordions. Fixed conflict between angular routes and TB tabs.
  ...
This commit is contained in:
Matthew Jones
2014-02-18 14:04:51 -05:00
1452 changed files with 350833 additions and 80206 deletions

3
.bowerrc Normal file
View File

@@ -0,0 +1,3 @@
{
"directory": "awx/ui/static/lib"
}

5
.gitignore vendored
View File

@@ -4,12 +4,13 @@ awx/projects
awx/job_status
awx/public/media
awx/public/static
awx/ui/static/js/awx-min.js
awx/ui/static/js/awx.min.js
awx/ui/static/css/awx.min.css
env/*
node_modules/**
build
deb-build
dist
/dist
htmlcov
rpm-build
*.DS_Store

44
Gruntfile.js Normal file
View File

@@ -0,0 +1,44 @@
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', '!awx/ui/static/js/config.js']
}
}
},
less: {
production: {
options: {
cleancss: true
},
files: {
"awx/ui/static/css/awx.min.css": "awx/ui/static/less/ansible-ui.less"
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.registerTask('default', ['jshint', 'uglify', 'less']);
}

View File

@@ -14,7 +14,7 @@ recursive-include config/rpm *
recursive-exclude awx devonly.py*
recursive-exclude awx/ui/static/lib/ansible *
recursive-exclude awx/settings local_settings.py*
include awx/ui/static/js/awx-min.js
include awx/ui/static/js/awx.min.js
include awx/ui/static/js/config.js
include COPYING
prune awx/public

View File

@@ -40,7 +40,8 @@ clean:
rm -rf dist/*
rm -rf build rpm-build *.egg-info
rm -rf debian deb-build
rm -f awx/ui/static/js/awx-min.js
rm -f awx/ui/static/css/awx*.js awx/ui/static/css/awx*.css
rm -rf node_modules
find . -type f -regex ".*\.py[co]$$" -delete
# Fetch from origin, rebase local commits on top of origin commits.
@@ -137,9 +138,17 @@ test_tox:
test_jenkins:
$(PYTHON) manage.py jenkins -v2
# Update local npm install
node_modules:
npm install
# Build minified JS/CSS.
minjs:
(cd tools/ui/ && ./compile.sh)
minjs: node_modules
grunt
# Check .js files for errors and lint
lintjs: node_modules
grunt jshint
# Build a pip-installable package into dist/ with a timestamped version number.
dev_build:

View File

@@ -1207,7 +1207,18 @@ class ActivityStreamSerializer(BaseSerializer):
allm2m = getattr(obj, fk).all()
if allm2m.count() > 0:
summary_fields[fk] = []
summary_fields['job_template'] = []
for thisItem in allm2m:
if fk == 'job':
job_template_item = {}
job_template_fields = SUMMARIZABLE_FK_FIELDS['job_template']
job_template = getattr(thisItem, 'job_template', None)
if job_template is not None:
for field in job_template_fields:
fval = getattr(job_template, field, None)
if fval is not None:
job_template_item[field] = fval
summary_fields['job_template'].append(job_template_item)
thisItemDict = {}
if 'id' not in related_fields:
related_fields = related_fields + ('id',)

View File

@@ -2,6 +2,7 @@
# All Rights Reserved.
# Django
from django.conf import settings
from django.shortcuts import render
from django.template import RequestContext
from django.utils.safestring import mark_safe
@@ -10,7 +11,7 @@ def handle_error(request, status=404, **kwargs):
# FIXME: Should attempt to check HTTP Accept request header and return
# plain JSON response instead of HTML (maybe only for /api/*).
context = kwargs
if request.path.startswith('/admin/'):
if 'django.contrib.admin' in settings.INSTALLED_APPS and request.path.startswith('/admin/'):
template_name = 'admin/error.html'
else:
# Return enough context to popuplate the base API template.

View File

@@ -1,384 +0,0 @@
.btn-default,
.btn-primary,
.btn-success,
.btn-info,
.btn-warning,
.btn-danger {
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
}
.btn-default:active,
.btn-primary:active,
.btn-success:active,
.btn-info:active,
.btn-warning:active,
.btn-danger:active,
.btn-default.active,
.btn-primary.active,
.btn-success.active,
.btn-info.active,
.btn-warning.active,
.btn-danger.active {
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
}
.btn:active,
.btn.active {
background-image: none;
}
.btn-default {
text-shadow: 0 1px 0 #fff;
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#e6e6e6));
background-image: -webkit-linear-gradient(top, #ffffff, 0%, #e6e6e6, 100%);
background-image: -moz-linear-gradient(top, #ffffff 0%, #e6e6e6 100%);
background-image: linear-gradient(to bottom, #ffffff 0%, #e6e6e6 100%);
background-repeat: repeat-x;
border-color: #e0e0e0;
border-color: #ccc;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
}
.btn-default:active,
.btn-default.active {
background-color: #e6e6e6;
border-color: #e0e0e0;
}
.btn-primary {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
background-repeat: repeat-x;
border-color: #2d6ca2;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
}
.btn-primary:active,
.btn-primary.active {
background-color: #3071a9;
border-color: #2d6ca2;
}
.btn-success {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44));
background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%);
background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
background-repeat: repeat-x;
border-color: #419641;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
}
.btn-success:active,
.btn-success.active {
background-color: #449d44;
border-color: #419641;
}
.btn-warning {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f));
background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%);
background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
background-repeat: repeat-x;
border-color: #eb9316;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
}
.btn-warning:active,
.btn-warning.active {
background-color: #ec971f;
border-color: #eb9316;
}
.btn-danger {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c));
background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%);
background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
background-repeat: repeat-x;
border-color: #c12e2a;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
}
.btn-danger:active,
.btn-danger.active {
background-color: #c9302c;
border-color: #c12e2a;
}
.btn-info {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5));
background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%);
background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
background-repeat: repeat-x;
border-color: #2aabd2;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
}
.btn-info:active,
.btn-info.active {
background-color: #31b0d5;
border-color: #2aabd2;
}
.thumbnail,
.img-thumbnail {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus,
.dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus {
background-color: #357ebd;
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
}
.navbar {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#f8f8f8));
background-image: -webkit-linear-gradient(top, #ffffff, 0%, #f8f8f8, 100%);
background-image: -moz-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
background-repeat: repeat-x;
border-radius: 4px;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
}
.navbar .navbar-nav > .active > a {
background-color: #f8f8f8;
}
.navbar-brand,
.navbar-nav > li > a {
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
}
.navbar-inverse {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#3c3c3c), to(#222222));
background-image: -webkit-linear-gradient(top, #3c3c3c, 0%, #222222, 100%);
background-image: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%);
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
}
.navbar-inverse .navbar-nav > .active > a {
background-color: #222222;
}
.navbar-inverse .navbar-brand,
.navbar-inverse .navbar-nav > li > a {
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.navbar-static-top,
.navbar-fixed-top,
.navbar-fixed-bottom {
border-radius: 0;
}
.alert {
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
}
.alert-success {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#c8e5bc));
background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #c8e5bc, 100%);
background-image: -moz-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
background-repeat: repeat-x;
border-color: #b2dba1;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
}
.alert-info {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#b9def0));
background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #b9def0, 100%);
background-image: -moz-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
background-repeat: repeat-x;
border-color: #9acfea;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
}
.alert-warning {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#f8efc0));
background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #f8efc0, 100%);
background-image: -moz-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
background-repeat: repeat-x;
border-color: #f5e79e;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
}
.alert-danger {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#e7c3c3));
background-image: -webkit-linear-gradient(top, #f2dede, 0%, #e7c3c3, 100%);
background-image: -moz-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
background-repeat: repeat-x;
border-color: #dca7a7;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
}
.progress {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(#f5f5f5));
background-image: -webkit-linear-gradient(top, #ebebeb, 0%, #f5f5f5, 100%);
background-image: -moz-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
}
.progress-bar {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
}
.progress-bar-success {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44));
background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%);
background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%);
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
}
.progress-bar-info {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5));
background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%);
background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
}
.progress-bar-warning {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f));
background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%);
background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
}
.progress-bar-danger {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c));
background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%);
background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%);
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
}
.list-group {
border-radius: 4px;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
}
.list-group-item.active,
.list-group-item.active:hover,
.list-group-item.active:focus {
text-shadow: 0 -1px 0 #3071a9;
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3278b3));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #3278b3, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #3278b3 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
background-repeat: repeat-x;
border-color: #3278b3;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
}
.panel {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.panel-default > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f5f5f5), to(#e8e8e8));
background-image: -webkit-linear-gradient(top, #f5f5f5, 0%, #e8e8e8, 100%);
background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
}
.panel-primary > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd));
background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%);
background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%);
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
}
.panel-success > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#d0e9c6));
background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #d0e9c6, 100%);
background-image: -moz-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
}
.panel-info > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#c4e3f3));
background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #c4e3f3, 100%);
background-image: -moz-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
}
.panel-warning > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#faf2cc));
background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #faf2cc, 100%);
background-image: -moz-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
}
.panel-danger > .panel-heading {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#ebcccc));
background-image: -webkit-linear-gradient(top, #f2dede, 0%, #ebcccc, 100%);
background-image: -moz-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
}
.well {
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#e8e8e8), to(#f5f5f5));
background-image: -webkit-linear-gradient(top, #e8e8e8, 0%, #f5f5f5, 100%);
background-image: -moz-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
background-repeat: repeat-x;
border-color: #dcdcdc;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,87 +0,0 @@
.form-control .select2-choice {
border: 0;
border-radius: 2px;
}
.form-control .select2-choice .select2-arrow {
border-radius: 0 2px 2px 0;
}
.form-control.select2-container {
height: auto !important;
padding: 0px;
}
.form-control.select2-container.select2-dropdown-open {
border-color: #5897FB;
border-radius: 3px 3px 0 0;
}
.form-control .select2-container.select2-dropdown-open .select2-choices {
border-radius: 3px 3px 0 0;
}
.form-control.select2-container .select2-choices {
border: 0 !important;
border-radius: 3px;
}
.control-group.warning .select2-container .select2-choice,
.control-group.warning .select2-container .select2-choices,
.control-group.warning .select2-container-active .select2-choice,
.control-group.warning .select2-container-active .select2-choices,
.control-group.warning .select2-dropdown-open.select2-drop-above .select2-choice,
.control-group.warning .select2-dropdown-open.select2-drop-above .select2-choices,
.control-group.warning .select2-container-multi.select2-container-active .select2-choices {
border: 1px solid #C09853 !important;
}
.control-group.warning .select2-container .select2-choice div {
border-left: 1px solid #C09853 !important;
background: #FCF8E3 !important;
}
.control-group.error .select2-container .select2-choice,
.control-group.error .select2-container .select2-choices,
.control-group.error .select2-container-active .select2-choice,
.control-group.error .select2-container-active .select2-choices,
.control-group.error .select2-dropdown-open.select2-drop-above .select2-choice,
.control-group.error .select2-dropdown-open.select2-drop-above .select2-choices,
.control-group.error .select2-container-multi.select2-container-active .select2-choices {
border: 1px solid #B94A48 !important;
}
.control-group.error .select2-container .select2-choice div {
border-left: 1px solid #B94A48 !important;
background: #F2DEDE !important;
}
.control-group.info .select2-container .select2-choice,
.control-group.info .select2-container .select2-choices,
.control-group.info .select2-container-active .select2-choice,
.control-group.info .select2-container-active .select2-choices,
.control-group.info .select2-dropdown-open.select2-drop-above .select2-choice,
.control-group.info .select2-dropdown-open.select2-drop-above .select2-choices,
.control-group.info .select2-container-multi.select2-container-active .select2-choices {
border: 1px solid #3A87AD !important;
}
.control-group.info .select2-container .select2-choice div {
border-left: 1px solid #3A87AD !important;
background: #D9EDF7 !important;
}
.control-group.success .select2-container .select2-choice,
.control-group.success .select2-container .select2-choices,
.control-group.success .select2-container-active .select2-choice,
.control-group.success .select2-container-active .select2-choices,
.control-group.success .select2-dropdown-open.select2-drop-above .select2-choice,
.control-group.success .select2-dropdown-open.select2-drop-above .select2-choices,
.control-group.success .select2-container-multi.select2-container-active .select2-choices {
border: 1px solid #468847 !important;
}
.control-group.success .select2-container .select2-choice div {
border-left: 1px solid #468847 !important;
background: #DFF0D8 !important;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,615 +0,0 @@
/*
Version: 3.4.5 Timestamp: Mon Nov 4 08:22:42 PST 2013
*/
.select2-container {
margin: 0;
position: relative;
display: inline-block;
/* inline-block for ie7 */
zoom: 1;
*display: inline;
vertical-align: middle;
}
.select2-container,
.select2-drop,
.select2-search,
.select2-search input {
/*
Force border-box so that % widths fit the parent
container without overlap because of margin/padding.
More Info : http://www.quirksmode.org/css/box.html
*/
-webkit-box-sizing: border-box; /* webkit */
-moz-box-sizing: border-box; /* firefox */
box-sizing: border-box; /* css3 */
}
.select2-container .select2-choice {
display: block;
height: 26px;
padding: 0 0 0 8px;
overflow: hidden;
position: relative;
border: 1px solid #aaa;
white-space: nowrap;
line-height: 26px;
color: #444;
text-decoration: none;
border-radius: 4px;
background-clip: padding-box;
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #fff;
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.5, #fff));
background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 50%);
background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 50%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#ffffff', endColorstr = '#eeeeee', GradientType = 0);
background-image: linear-gradient(top, #fff 0%, #eee 50%);
}
.select2-container.select2-drop-above .select2-choice {
border-bottom-color: #aaa;
border-radius: 0 0 4px 4px;
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.9, #fff));
background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 90%);
background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 90%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
background-image: linear-gradient(top, #eee 0%, #fff 90%);
}
.select2-container.select2-allowclear .select2-choice .select2-chosen {
margin-right: 42px;
}
.select2-container .select2-choice > .select2-chosen {
margin-right: 26px;
display: block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.select2-container .select2-choice abbr {
display: none;
width: 12px;
height: 12px;
position: absolute;
right: 24px;
top: 8px;
font-size: 1px;
text-decoration: none;
border: 0;
background: url('select2.png') right top no-repeat;
cursor: pointer;
outline: 0;
}
.select2-container.select2-allowclear .select2-choice abbr {
display: inline-block;
}
.select2-container .select2-choice abbr:hover {
background-position: right -11px;
cursor: pointer;
}
.select2-drop-mask {
border: 0;
margin: 0;
padding: 0;
position: fixed;
left: 0;
top: 0;
min-height: 100%;
min-width: 100%;
height: auto;
width: auto;
opacity: 0;
z-index: 9998;
/* styles required for IE to work */
background-color: #fff;
filter: alpha(opacity=0);
}
.select2-drop {
width: 100%;
margin-top: -1px;
position: absolute;
z-index: 9999;
top: 100%;
background: #fff;
color: #000;
border: 1px solid #aaa;
border-top: 0;
border-radius: 0 0 4px 4px;
-webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
}
.select2-drop-auto-width {
border-top: 1px solid #aaa;
width: auto;
}
.select2-drop-auto-width .select2-search {
padding-top: 4px;
}
.select2-drop.select2-drop-above {
margin-top: 1px;
border-top: 1px solid #aaa;
border-bottom: 0;
border-radius: 4px 4px 0 0;
-webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
}
.select2-drop-active {
border: 1px solid #5897fb;
border-top: none;
}
.select2-drop.select2-drop-above.select2-drop-active {
border-top: 1px solid #5897fb;
}
.select2-container .select2-choice .select2-arrow {
display: inline-block;
width: 18px;
height: 100%;
position: absolute;
right: 0;
top: 0;
border-left: 1px solid #aaa;
border-radius: 0 4px 4px 0;
background-clip: padding-box;
background: #ccc;
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee));
background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%);
background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#cccccc', GradientType = 0);
background-image: linear-gradient(top, #ccc 0%, #eee 60%);
}
.select2-container .select2-choice .select2-arrow b {
display: block;
width: 100%;
height: 100%;
background: url('select2.png') no-repeat 0 1px;
}
.select2-search {
display: inline-block;
width: 100%;
min-height: 26px;
margin: 0;
padding-left: 4px;
padding-right: 4px;
position: relative;
z-index: 10000;
white-space: nowrap;
}
.select2-search input {
width: 100%;
height: auto !important;
min-height: 26px;
padding: 4px 20px 4px 5px;
margin: 0;
outline: 0;
font-family: sans-serif;
font-size: 1em;
border: 1px solid #aaa;
border-radius: 0;
-webkit-box-shadow: none;
box-shadow: none;
background: #fff url('select2.png') no-repeat 100% -22px;
background: url('select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));
background: url('select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);
background: url('select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);
background: url('select2.png') no-repeat 100% -22px, linear-gradient(top, #fff 85%, #eee 99%);
}
.select2-drop.select2-drop-above .select2-search input {
margin-top: 4px;
}
.select2-search input.select2-active {
background: #fff url('select2-spinner.gif') no-repeat 100%;
background: url('select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));
background: url('select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);
background: url('select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);
background: url('select2-spinner.gif') no-repeat 100%, linear-gradient(top, #fff 85%, #eee 99%);
}
.select2-container-active .select2-choice,
.select2-container-active .select2-choices {
border: 1px solid #5897fb;
outline: none;
-webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);
box-shadow: 0 0 5px rgba(0, 0, 0, .3);
}
.select2-dropdown-open .select2-choice {
border-bottom-color: transparent;
-webkit-box-shadow: 0 1px 0 #fff inset;
box-shadow: 0 1px 0 #fff inset;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
background-color: #eee;
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #fff), color-stop(0.5, #eee));
background-image: -webkit-linear-gradient(center bottom, #fff 0%, #eee 50%);
background-image: -moz-linear-gradient(center bottom, #fff 0%, #eee 50%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);
background-image: linear-gradient(top, #fff 0%, #eee 50%);
}
.select2-dropdown-open.select2-drop-above .select2-choice,
.select2-dropdown-open.select2-drop-above .select2-choices {
border: 1px solid #5897fb;
border-top-color: transparent;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(0.5, #eee));
background-image: -webkit-linear-gradient(center top, #fff 0%, #eee 50%);
background-image: -moz-linear-gradient(center top, #fff 0%, #eee 50%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);
background-image: linear-gradient(bottom, #fff 0%, #eee 50%);
}
.select2-dropdown-open .select2-choice .select2-arrow {
background: transparent;
border-left: none;
filter: none;
}
.select2-dropdown-open .select2-choice .select2-arrow b {
background-position: -18px 1px;
}
/* results */
.select2-results {
max-height: 200px;
padding: 0 0 0 4px;
margin: 4px 4px 4px 0;
position: relative;
overflow-x: hidden;
overflow-y: auto;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.select2-results ul.select2-result-sub {
margin: 0;
padding-left: 0;
}
.select2-results ul.select2-result-sub > li .select2-result-label { padding-left: 20px }
.select2-results ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 40px }
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 60px }
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 80px }
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 100px }
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 110px }
.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 120px }
.select2-results li {
list-style: none;
display: list-item;
background-image: none;
}
.select2-results li.select2-result-with-children > .select2-result-label {
font-weight: bold;
}
.select2-results .select2-result-label {
padding: 3px 7px 4px;
margin: 0;
cursor: pointer;
min-height: 1em;
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.select2-results .select2-highlighted {
background: #3875d7;
color: #fff;
}
.select2-results li em {
background: #feffde;
font-style: normal;
}
.select2-results .select2-highlighted em {
background: transparent;
}
.select2-results .select2-highlighted ul {
background: #fff;
color: #000;
}
.select2-results .select2-no-results,
.select2-results .select2-searching,
.select2-results .select2-selection-limit {
background: #f4f4f4;
display: list-item;
}
/*
disabled look for disabled choices in the results dropdown
*/
.select2-results .select2-disabled.select2-highlighted {
color: #666;
background: #f4f4f4;
display: list-item;
cursor: default;
}
.select2-results .select2-disabled {
background: #f4f4f4;
display: list-item;
cursor: default;
}
.select2-results .select2-selected {
display: none;
}
.select2-more-results.select2-active {
background: #f4f4f4 url('select2-spinner.gif') no-repeat 100%;
}
.select2-more-results {
background: #f4f4f4;
display: list-item;
}
/* disabled styles */
.select2-container.select2-container-disabled .select2-choice {
background-color: #f4f4f4;
background-image: none;
border: 1px solid #ddd;
cursor: default;
}
.select2-container.select2-container-disabled .select2-choice .select2-arrow {
background-color: #f4f4f4;
background-image: none;
border-left: 0;
}
.select2-container.select2-container-disabled .select2-choice abbr {
display: none;
}
/* multiselect */
.select2-container-multi .select2-choices {
height: auto !important;
height: 1%;
margin: 0;
padding: 0;
position: relative;
border: 1px solid #aaa;
cursor: text;
overflow: hidden;
background-color: #fff;
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eee), color-stop(15%, #fff));
background-image: -webkit-linear-gradient(top, #eee 1%, #fff 15%);
background-image: -moz-linear-gradient(top, #eee 1%, #fff 15%);
background-image: linear-gradient(top, #eee 1%, #fff 15%);
}
.select2-locked {
padding: 3px 5px 3px 5px !important;
}
.select2-container-multi .select2-choices {
min-height: 26px;
}
.select2-container-multi.select2-container-active .select2-choices {
border: 1px solid #5897fb;
outline: none;
-webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);
box-shadow: 0 0 5px rgba(0, 0, 0, .3);
}
.select2-container-multi .select2-choices li {
float: left;
list-style: none;
}
.select2-container-multi .select2-choices .select2-search-field {
margin: 0;
padding: 0;
white-space: nowrap;
}
.select2-container-multi .select2-choices .select2-search-field input {
padding: 5px;
margin: 1px 0;
font-family: sans-serif;
font-size: 100%;
color: #666;
outline: 0;
border: 0;
-webkit-box-shadow: none;
box-shadow: none;
background: transparent !important;
}
.select2-container-multi .select2-choices .select2-search-field input.select2-active {
background: #fff url('select2-spinner.gif') no-repeat 100% !important;
}
.select2-default {
color: #999 !important;
}
.select2-container-multi .select2-choices .select2-search-choice {
padding: 3px 5px 3px 18px;
margin: 3px 0 3px 5px;
position: relative;
line-height: 13px;
color: #333;
cursor: default;
border: 1px solid #aaaaaa;
border-radius: 3px;
-webkit-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);
box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);
background-clip: padding-box;
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-color: #e4e4e4;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#f4f4f4', GradientType=0);
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eee));
background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
}
.select2-container-multi .select2-choices .select2-search-choice .select2-chosen {
cursor: default;
}
.select2-container-multi .select2-choices .select2-search-choice-focus {
background: #d4d4d4;
}
.select2-search-choice-close {
display: block;
width: 12px;
height: 13px;
position: absolute;
right: 3px;
top: 4px;
font-size: 1px;
outline: none;
background: url('select2.png') right top no-repeat;
}
.select2-container-multi .select2-search-choice-close {
left: 3px;
}
.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover {
background-position: right -11px;
}
.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close {
background-position: right -11px;
}
/* disabled styles */
.select2-container-multi.select2-container-disabled .select2-choices {
background-color: #f4f4f4;
background-image: none;
border: 1px solid #ddd;
cursor: default;
}
.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice {
padding: 3px 5px 3px 5px;
border: 1px solid #ddd;
background-image: none;
background-color: #f4f4f4;
}
.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close { display: none;
background: none;
}
/* end multiselect */
.select2-result-selectable .select2-match,
.select2-result-unselectable .select2-match {
text-decoration: underline;
}
.select2-offscreen, .select2-offscreen:focus {
clip: rect(0 0 0 0) !important;
width: 1px !important;
height: 1px !important;
border: 0 !important;
margin: 0 !important;
padding: 0 !important;
overflow: hidden !important;
position: absolute !important;
outline: 0 !important;
left: 0px !important;
top: 0px !important;
}
.select2-display-none {
display: none;
}
.select2-measure-scrollbar {
position: absolute;
top: -10000px;
left: -10000px;
width: 100px;
height: 100px;
overflow: scroll;
}
/* Retina-ize icons */
@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi) {
.select2-search input, .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice .select2-arrow b {
background-image: url('select2x2.png') !important;
background-repeat: no-repeat !important;
background-size: 60px 40px !important;
}
.select2-search input {
background-position: 100% -21px !important;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 613 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 845 B

View File

@@ -4,10 +4,12 @@
* Our main application mdoule. Declare application routes and perform initialization chores.
*
*/
var urlPrefix = $basePath;
angular.module('ansible', [
'ngRoute',
'ngSanitize',
'ngCookies',
'RestServices',
'AuthService',
'Utilities',
@@ -58,6 +60,7 @@ angular.module('ansible', [
'JobFormDefinition',
'JobEventsListDefinition',
'JobEventDataDefinition',
'JobEventsFormDefinition',
'JobHostDefinition',
'JobSummaryDefinition',
'ParseHelper',
@@ -75,9 +78,7 @@ angular.module('ansible', [
'ObjectCountWidget',
'StreamWidget',
'JobsHelper',
'InventoryStatusDefinition',
'InventoryGroupsHelpDefinition',
'InventoryHostsHelpDefinition',
'InventoryTree',
'CredentialsHelper',
'TimerService',
@@ -85,183 +86,302 @@ angular.module('ansible', [
'HomeGroupListDefinition',
'HomeHostListDefinition',
'ActivityDetailDefinition'
])
.config(['$routeProvider', function($routeProvider) {
])
.config(['$routeProvider',
function ($routeProvider) {
$routeProvider.
when('/jobs',
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobsListCtrl }).
when('/jobs', {
templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobsListCtrl'
}).
when('/jobs/:id',
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobsEdit }).
when('/jobs/:id', {
templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobsEdit'
}).
when('/jobs/:id/job_events',
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobEventsList }).
when('/jobs/:id/job_events', {
templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobEventsList'
}).
when('/jobs/:id/job_host_summaries',
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobHostSummaryList }).
when('/jobs/:id/job_host_summaries', {
templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobHostSummaryList'
}).
when('/jobs/:job_id/job_events/:event_id',
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobEventsEdit }).
when('/jobs/:job_id/job_events/:event_id', {
templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobEventsEdit'
}).
when('/job_templates',
{ templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesList }).
when('/job_templates', {
templateUrl: urlPrefix + 'partials/job_templates.html',
controller: 'JobTemplatesList'
}).
when('/job_templates/add',
{ templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesAdd }).
when('/job_templates/add', {
templateUrl: urlPrefix + 'partials/job_templates.html',
controller: 'JobTemplatesAdd'
}).
when('/job_templates/:id',
{ templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesEdit }).
when('/job_templates/:id', {
templateUrl: urlPrefix + 'partials/job_templates.html',
controller: 'JobTemplatesEdit'
}).
when('/projects',
{ templateUrl: urlPrefix + 'partials/projects.html', controller: ProjectsList }).
when('/projects', {
templateUrl: urlPrefix + 'partials/projects.html',
controller: 'ProjectsList'
}).
when('/projects/add',
{ templateUrl: urlPrefix + 'partials/projects.html', controller: ProjectsAdd }).
when('/projects/add', {
templateUrl: urlPrefix + 'partials/projects.html',
controller: 'ProjectsAdd'
}).
when('/projects/:id',
{ templateUrl: urlPrefix + 'partials/projects.html', controller: ProjectsEdit }).
when('/projects/:id', {
templateUrl: urlPrefix + 'partials/projects.html',
controller: 'ProjectsEdit'
}).
when('/projects/:project_id/organizations',
{ templateUrl: urlPrefix + 'partials/projects.html', controller: OrganizationsList }).
when('/projects/:project_id/organizations', {
templateUrl: urlPrefix + 'partials/projects.html',
controller: 'OrganizationsList'
}).
when('/projects/:project_id/organizations/add',
{ templateUrl: urlPrefix + 'partials/projects.html', controller: OrganizationsAdd }).
when('/projects/:project_id/organizations/add', {
templateUrl: urlPrefix + 'partials/projects.html',
controller: 'OrganizationsAdd'
}).
when('/hosts/:id/job_host_summaries',
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobHostSummaryList }).
when('/hosts/:id/job_host_summaries', {
templateUrl: urlPrefix + 'partials/jobs.html',
controller: 'JobHostSummaryList'
}).
when('/inventories',
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: InventoriesList }).
when('/inventories', {
templateUrl: urlPrefix + 'partials/inventories.html',
controller: 'InventoriesList'
}).
when('/inventories/add',
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: InventoriesAdd }).
when('/inventories/add', {
templateUrl: urlPrefix + 'partials/inventories.html',
controller: 'InventoriesAdd'
}).
when('/inventories/:inventory_id',
{ templateUrl: urlPrefix + 'partials/inventory-edit.html', controller: InventoriesEdit }).
when('/inventories/:inventory_id', {
templateUrl: urlPrefix + 'partials/inventory-edit.html',
controller: 'InventoriesEdit'
}).
when('/organizations', { templateUrl: urlPrefix + 'partials/organizations.html',
controller: OrganizationsList }).
when('/organizations', {
templateUrl: urlPrefix + 'partials/organizations.html',
controller: 'OrganizationsList'
}).
when('/organizations/add', { templateUrl: urlPrefix + 'partials/organizations.html',
controller: OrganizationsAdd }).
when('/organizations/add', {
templateUrl: urlPrefix + 'partials/organizations.html',
controller: 'OrganizationsAdd'
}).
when('/organizations/:organization_id', { templateUrl: urlPrefix + 'partials/organizations.html',
controller: OrganizationsEdit }).
when('/organizations/:organization_id', {
templateUrl: urlPrefix + 'partials/organizations.html',
controller: 'OrganizationsEdit'
}).
when('/organizations/:organization_id/admins', { templateUrl: urlPrefix + 'partials/organizations.html',
controller: AdminsList }).
when('/organizations/:organization_id/admins', {
templateUrl: urlPrefix + 'partials/organizations.html',
controller: 'AdminsList'
}).
when('/organizations/:organization_id/users', { templateUrl: urlPrefix + 'partials/users.html',
controller: UsersList }).
when('/organizations/:organization_id/users', {
templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersList'
}).
when('/organizations/:organization_id/users/add', { templateUrl: urlPrefix + 'partials/users.html',
controller: UsersAdd }).
when('/organizations/:organization_id/users/add', {
templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersAdd'
}).
when('/organizations/:organization_id/users/:user_id', { templateUrl: urlPrefix + 'partials/users.html',
controller: UsersEdit }).
when('/organizations/:organization_id/users/:user_id', {
templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersEdit'
}).
when('/teams', { templateUrl: urlPrefix + 'partials/teams.html',
controller: TeamsList }).
when('/teams', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'TeamsList'
}).
when('/teams/add', { templateUrl: urlPrefix + 'partials/teams.html',
controller: TeamsAdd }).
when('/teams/add', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'TeamsAdd'
}).
when('/teams/:team_id', { templateUrl: urlPrefix + 'partials/teams.html',
controller: TeamsEdit }).
when('/teams/:team_id', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'TeamsEdit'
}).
when('/teams/:team_id/permissions/add', { templateUrl: urlPrefix + 'partials/teams.html',
controller: PermissionsAdd }).
when('/teams/:team_id/permissions/add', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'PermissionsAdd'
}).
when('/teams/:team_id/permissions', { templateUrl: urlPrefix + 'partials/teams.html',
controller: PermissionsList }).
when('/teams/:team_id/permissions', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'PermissionsList'
}).
when('/teams/:team_id/permissions/:permission_id', { templateUrl: urlPrefix + 'partials/teams.html',
controller: PermissionsEdit }).
when('/teams/:team_id/permissions/:permission_id', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'PermissionsEdit'
}).
when('/teams/:team_id/users', { templateUrl: urlPrefix + 'partials/teams.html',
controller: UsersList }).
when('/teams/:team_id/users', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'UsersList'
}).
when('/teams/:team_id/users/:user_id', { templateUrl: urlPrefix + 'partials/teams.html',
controller: UsersEdit }).
when('/teams/:team_id/users/:user_id', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'UsersEdit'
}).
when('/teams/:team_id/projects', { templateUrl: urlPrefix + 'partials/teams.html',
controller: ProjectsList }).
when('/teams/:team_id/projects', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'ProjectsList'
}).
when('/teams/:team_id/projects/add', { templateUrl: urlPrefix + 'partials/teams.html',
controller: ProjectsAdd }).
when('/teams/:team_id/projects/add', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'ProjectsAdd'
}).
when('/teams/:team_id/projects/:project_id', { templateUrl: urlPrefix + 'partials/teams.html',
controller: ProjectsEdit }).
when('/teams/:team_id/projects/:project_id', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'ProjectsEdit'
}).
when('/teams/:team_id/credentials', { templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsList }).
when('/teams/:team_id/credentials', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'CredentialsList'
}).
when('/teams/:team_id/credentials/add', { templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsAdd }).
when('/teams/:team_id/credentials/add', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'CredentialsAdd'
}).
when('/teams/:team_id/credentials/:credential_id', { templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsEdit }).
when('/teams/:team_id/credentials/:credential_id', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'CredentialsEdit'
}).
when('/credentials', { templateUrl: urlPrefix + 'partials/credentials.html',
controller: CredentialsList }).
when('/credentials', {
templateUrl: urlPrefix + 'partials/credentials.html',
controller: 'CredentialsList'
}).
when('/credentials/add', { templateUrl: urlPrefix + 'partials/credentials.html',
controller: CredentialsAdd }).
when('/credentials/add', {
templateUrl: urlPrefix + 'partials/credentials.html',
controller: 'CredentialsAdd'
}).
when('/credentials/:credential_id', { templateUrl: urlPrefix + 'partials/credentials.html',
controller: CredentialsEdit }).
when('/credentials/:credential_id', {
templateUrl: urlPrefix + 'partials/credentials.html',
controller: 'CredentialsEdit'
}).
when('/users', { templateUrl: urlPrefix + 'partials/users.html',
controller: UsersList }).
when('/users', {
templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersList'
}).
when('/users/add', { templateUrl: urlPrefix + 'partials/users.html',
controller: UsersAdd }).
when('/users/add', {
templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersAdd'
}).
when('/users/:user_id', { templateUrl: urlPrefix + 'partials/users.html',
controller: UsersEdit }).
when('/users/:user_id', {
templateUrl: urlPrefix + 'partials/users.html',
controller: 'UsersEdit'
}).
when('/users/:user_id/credentials', { templateUrl: urlPrefix + 'partials/users.html',
controller: CredentialsList }).
when('/users/:user_id/credentials', {
templateUrl: urlPrefix + 'partials/users.html',
controller: 'CredentialsList'
}).
when('/users/:user_id/permissions/add', { templateUrl: urlPrefix + 'partials/users.html',
controller: PermissionsAdd }).
when('/users/:user_id/permissions/add', {
templateUrl: urlPrefix + 'partials/users.html',
controller: 'PermissionsAdd'
}).
when('/users/:user_id/permissions', { templateUrl: urlPrefix + 'partials/users.html',
controller: PermissionsList }).
when('/users/:user_id/permissions', {
templateUrl: urlPrefix + 'partials/users.html',
controller: 'PermissionsList'
}).
when('/users/:user_id/permissions/:permission_id', { templateUrl: urlPrefix + 'partials/users.html',
controller: PermissionsEdit }).
when('/users/:user_id/permissions/:permission_id', {
templateUrl: urlPrefix + 'partials/users.html',
controller: 'PermissionsEdit'
}).
when('/users/:user_id/credentials/add', { templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsAdd }).
when('/users/:user_id/credentials/add', {
templateUrl: urlPrefix + 'partials/teams.html',
controller: 'CredentialsAdd'
}).
when('/teams/:user_id/credentials/:credential_id', { templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsEdit }).
when('/teams/:user_id/credentials/:credential_id', {
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'});
}])
.run(['$cookieStore', '$rootScope', 'CheckLicense', '$location', 'Authorization','LoadBasePaths', 'ViewLicense',
otherwise({
redirectTo: '/home'
});
}
])
.run(['$cookieStore', '$rootScope', 'CheckLicense', '$location', 'Authorization', 'LoadBasePaths', 'ViewLicense',
'Timer', 'ClearScope', 'HideStream',
function($cookieStore, $rootScope, CheckLicense, $location, Authorization, LoadBasePaths, ViewLicense,
function ($cookieStore, $rootScope, CheckLicense, $location, Authorization, LoadBasePaths, ViewLicense,
Timer, ClearScope, HideStream) {
LoadBasePaths();
$rootScope.breadcrumbs = new Array();
$rootScope.crumbCache = new Array();
$rootScope.breadcrumbs = [];
$rootScope.crumbCache = [];
$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
if ($('#stream-container').is(':visible')) {
@@ -269,37 +389,34 @@ angular.module('ansible', [
}
// On each navigation request, check that the user is logged in
if ( !/^\/(login|logout)/.test($location.path()) ) {
if (!/^\/(login|logout)/.test($location.path())) {
// capture most recent URL, excluding login/logout
$rootScope.lastPath = $location.path();
$cookieStore.put('lastPath', $location.path());
}
if (Authorization.isUserLoggedIn() == false) {
if ( next.templateUrl != (urlPrefix + 'partials/login.html') ) {
if (Authorization.isUserLoggedIn() === false) {
if (next.templateUrl !== (urlPrefix + 'partials/login.html')) {
$location.path('/login');
}
}
else if ($rootScope.sessionTimer.isExpired()) {
if ( next.templateUrl != (urlPrefix + 'partials/login.html') ) {
} else if ($rootScope.sessionTimer.isExpired()) {
if (next.templateUrl !== (urlPrefix + 'partials/login.html')) {
$rootScope.sessionTimer.expireSession();
$location.path('/login');
}
}
else {
if ($rootScope.current_user == undefined || $rootScope.current_user == null) {
} else {
if ($rootScope.current_user === undefined || $rootScope.current_user === null) {
Authorization.restoreUserInfo(); //user must have hit browser refresh
}
CheckLicense();
}
// Make the correct tab active
var base = $location.path().replace(/^\//,'').split('/')[0];
if (base == '') {
var base = $location.path().replace(/^\//, '').split('/')[0];
if (base === '') {
base = 'home';
}
else {
base.replace(/\_/g,' ');
} else {
base.replace(/\_/g, ' ');
}
$('.nav-tabs a[href="#' + base + '"]').tab('show');
});
@@ -309,29 +426,31 @@ angular.module('ansible', [
$rootScope.sessionExpired = false;
$cookieStore.put('sessionExpired', false);
$location.path('/login');
}
else {
} else {
// 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
var base = ($location.path().replace(/^\//,'').split('/')[0]);
if (base == '') {
var base = ($location.path().replace(/^\//, '').split('/')[0]);
if (base === '') {
base = 'home';
$location.path('/home');
}
else {
base.replace(/\_/g,' ');
} else {
base.replace(/\_/g, ' ');
}
$('.nav-tabs a[href="#' + base + '"]').tab('show');
$rootScope.viewCurrentUser = function() {
$rootScope.viewCurrentUser = function () {
$location.path('/users/' + $rootScope.current_user.id);
}
};
$rootScope.viewLicense = function() {
//$location.path('/license');
$rootScope.viewLicense = function () {
ViewLicense();
};
$rootScope.toggleTab = function(e, tab, tabs) {
e.preventDefault();
$('#' + tabs + ' #' + tab).tab('show');
};
}
}]);
]);

View File

@@ -1,4 +1,4 @@
/************************************
/**********************************************************************
*
* 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
debug_mode: true, // Enable console logging messages
@@ -21,6 +23,29 @@ var $AnsibleConfig =
// > password_strength = green
// It also controls password validation. Passwords are rejected if the score is not > password_strength.
session_timeout: 1800 // Number of seconds before an inactive session is automatically timed out and forced to log in again.
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.
variable_edit_modes: { // Options we pass to ControlMirror for editing YAML/JSON variables
yaml: {
mode:"text/x-yaml",
matchBrackets: true,
autoCloseBrackets: true,
styleActiveLine: true,
lineNumbers: true,
gutters: ["CodeMirror-lint-markers"],
lint: true
},
json: {
mode: "application/json",
styleActiveLine: true,
matchBrackets: true,
autoCloseBrackets: true,
lineNumbers: true,
gutters: ["CodeMirror-lint-markers"],
lint: true
}
}
};

View File

@@ -10,26 +10,28 @@
'use strict';
function AdminsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
Alert, AdminList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit,
ReturnToCaller,GetBasePath, SelectionInit)
{
var list = AdminList;
var defaultUrl = GetBasePath('organizations') + $routeParams.organization_id + '/users/' ;
var view = GenerateList;
var mode = 'select';
var scope = view.inject(AdminList, { mode: mode }); // Inject our view
function AdminsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, AdminList, GenerateList, LoadBreadCrumbs,
Prompt, SearchInit, PaginateInit, ReturnToCaller, GetBasePath, SelectionInit) {
var url = GetBasePath('organizations') + $routeParams.organization_id + '/admins/';
SelectionInit({ scope: scope, list: list, url: url, returnToCaller: 1 });
var list = AdminList,
defaultUrl = GetBasePath('organizations') + $routeParams.organization_id + '/users/',
generator = GenerateList,
mode = 'select',
url = GetBasePath('organizations') + $routeParams.organization_id + '/admins/';
SearchInit({ scope: scope, set: 'admins', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
generator.inject(AdminList, { mode: mode, scope: $scope });
SelectionInit({ scope: $scope, list: list, url: url, returnToCaller: 1 });
SearchInit({ scope: $scope, set: 'admins', list: list, url: defaultUrl });
PaginateInit({ scope: $scope, list: list, url: defaultUrl });
$scope.search(list.iterator);
LoadBreadCrumbs();
}
AdminsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'AdminList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'GetBasePath', 'SelectionInit'];
AdminsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'AdminList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'GetBasePath', 'SelectionInit'
];

View File

@@ -8,20 +8,24 @@
*
*/
/* globals console:false */
'use strict';
function Authenticate($cookieStore, $window, $scope, $rootScope, $location, Authorization, ToggleClass, Alert, Wait,
Timer, Empty)
{
var setLoginFocus = function() {
Timer, Empty) {
var setLoginFocus, lastPath, sessionExpired, scope;
setLoginFocus = function () {
$('#login-username').focus();
};
var sessionExpired = (Empty($rootScope.sessionExpired)) ? $cookieStore.get('sessionExpired') : $rootScope.sessionExpired;
sessionExpired = (Empty($rootScope.sessionExpired)) ? $cookieStore.get('sessionExpired') : $rootScope.sessionExpired;
var lastPath = function() {
lastPath = function () {
return (Empty($rootScope.lastPath)) ? $cookieStore.get('lastPath') : $rootScope.lastPath;
}
};
if ($AnsibleConfig.debug_mode && console) {
console.log('User session expired: ' + sessionExpired);
@@ -29,7 +33,7 @@ function Authenticate($cookieStore, $window, $scope, $rootScope, $location, Auth
}
// Hide any lingering modal dialogs
$('.modal[aria-hidden=false]').each( function() {
$('.modal[aria-hidden=false]').each(function () {
if ($(this).attr('id') !== 'login-modal') {
$(this).modal('hide');
}
@@ -39,22 +43,26 @@ function Authenticate($cookieStore, $window, $scope, $rootScope, $location, Auth
Wait('stop');
// Display the login dialog
$('#login-modal').modal({ show: true, keyboard: false, backdrop: 'static' });
$('#login-modal').modal({
show: true,
keyboard: false,
backdrop: 'static'
});
// Set focus to username field
$('#login-modal').on('shown.bs.modal', function() {
$('#login-modal').on('shown.bs.modal', function () {
setLoginFocus();
});
var scope = angular.element(document.getElementById('login-modal')).scope();
scope = angular.element(document.getElementById('login-modal')).scope();
// Reset the login form
scope['login_username'] = null;
scope['login_password'] = null;
scope['loginForm']['login_username'].$setPristine();
scope['loginForm']['login_password'].$setPristine();
scope.login_username = null;
scope.login_password = null;
scope.loginForm.login_username.$setPristine();
scope.loginForm.login_password.$setPristine();
if ($location.path() == '/logout') {
if ($location.path() === '/logout') {
//if logout request, clear AuthToken and user session data
Authorization.logout();
}
@@ -62,74 +70,71 @@ function Authenticate($cookieStore, $window, $scope, $rootScope, $location, Auth
$rootScope.userLoggedIn = false; //hide the logout link. if you got here, you're logged out.
$cookieStore.put('userLoggedIn', false); //gets set back to true by Authorization.setToken().
$('#login-password').bind('keypress', function(e) {
$('#login-password').bind('keypress', function (e) {
var code = (e.keyCode ? e.keyCode : e.which);
if (code == 13) {
if (code === 13) {
$('#login-button').click();
}
});
scope.reset = function() {
$('#login-form input').each( function(index) { $(this).val(''); });
scope.reset = function () {
$('#login-form input').each(function () {
$(this).val('');
});
};
// Call the API to get an auth token
scope.systemLogin = function(username, password) {
scope.systemLogin = function (username, password) {
$('.api-error').empty();
var token;
if (username == null || username == undefined || username == '' ||
password == null || password == undefined || password == '' ) {
if (Empty(username) || Empty(password)) {
Alert('Error!', 'Please provide a username and password before attempting to login.', 'alert-danger', setLoginFocus);
}
else {
} else {
Wait('start');
Authorization.retrieveToken(username, password)
.success( function(data, status, headers, config) {
.success(function (data, status) {
$('#login-modal').modal('hide');
token = data.token;
Authorization.setToken(data.token, data.expires);
$rootScope.sessionTimer = Timer.init();
// Get all the profile/access info regarding the logged in user
Authorization.getUser()
.success(function(data, status, headers, config) {
.success(function (data) {
Authorization.setUserInfo(data);
$rootScope['user_is_superuser'] = data.results[0].is_superuser;
$rootScope.user_is_superuser = data.results[0].is_superuser;
Authorization.getLicense()
.success(function(data, status, headers, config) {
Authorization.setLicense(data['license_info']);
.success(function (data) {
Authorization.setLicense(data);
if (lastPath()) {
// Go back to most recent navigation path
$location.path(lastPath());
}
else {
} else {
$location.url('/home?login=true');
}
})
.error(function(data, status, headers, config) {
Wait('stop');
Alert('Error', 'Failed to access user information. GET returned status: ' + status, 'alert-danger', setLoginFocus);
});
})
.error( function(data, status, headers, config) {
.error(function () {
Wait('stop');
Alert('Error', 'Failed to access license information. GET returned status: ' + status, 'alert-danger', setLoginFocus);
});
})
.error( function(data, status, headers, config) {
.error(function (data, status) {
Wait('stop');
if ( data.non_field_errors && data.non_field_errors.length == 0 ) {
Alert('Error', 'Failed to access user information. GET returned status: ' + status, 'alert-danger', setLoginFocus);
});
})
.error(function (data, status) {
var hdr, msg, key;
Wait('stop');
if (data.non_field_errors && data.non_field_errors.length === 0) {
// show field specific errors returned by the API
for (var key in data) {
for (key in data) {
scope[key + 'Error'] = data[key][0];
}
}
else {
var hdr, msg;
if ( data.non_field_errors && data.non_field_errors.length > 0 ) {
} else {
if (data.non_field_errors && data.non_field_errors.length > 0) {
hdr = 'Error';
msg = data.non_field_errors[0];
}
else {
} else {
hdr = 'Error';
msg = 'The login attempt failed with a status of: ' + status;
}
@@ -138,9 +143,10 @@ function Authenticate($cookieStore, $window, $scope, $rootScope, $location, Auth
}
});
}
}
};
}
Authenticate.$inject = ['$cookieStore', '$window', '$scope', '$rootScope', '$location', 'Authorization', 'ToggleClass', 'Alert', 'Wait',
'Timer', 'Empty'];
'Timer', 'Empty'
];

View File

@@ -1,7 +1,6 @@
/************************************
/*************************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
*
* Credentials.js
*
* Controller functions for the Credential model.
@@ -10,69 +9,76 @@
'use strict';
function CredentialsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, CredentialList,
function CredentialsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, CredentialList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
ClearScope, ProcessErrors, GetBasePath, SelectionInit, GetChoices, Wait, Stream)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
ClearScope, ProcessErrors, GetBasePath, SelectionInit, GetChoices, Wait, Stream) {
ClearScope();
Wait('start');
var list = CredentialList;
var defaultUrl = GetBasePath('credentials');
var view = GenerateList;
var base = $location.path().replace(/^\//,'').split('/')[0];
var mode = (base == 'credentials') ? 'edit' : 'select'; // if base path 'credentials', we're here to add/edit
var scope = view.inject(list, { mode: mode }); // Inject our view
scope.selected = [];
scope.credentialLoading = true;
var list = CredentialList,
defaultUrl = GetBasePath('credentials'),
view = GenerateList,
base = $location.path().replace(/^\//, '').split('/')[0],
mode = (base === 'credentials') ? 'edit' : 'select',
url;
var url = GetBasePath(base);
url += (base == 'users') ? $routeParams.user_id + '/credentials/' : $routeParams.team_id + '/credentials/';
view.inject(list, { mode: mode, scope: $scope });
SelectionInit({ scope: scope, list: list, url: url, returnToCaller: 1 });
$scope.selected = [];
$scope.credentialLoading = true;
if (scope.removePostRefresh) {
scope.removePostRefresh();
url = GetBasePath(base) + ( (base === 'users') ? $routeParams.user_id + '/credentials/' : $routeParams.team_id + '/credentials/' );
if (mode === 'select') {
SelectionInit({ scope: $scope, list: list, url: url, returnToCaller: 1 });
}
scope.removePostRefresh = scope.$on('PostRefresh', function() {
if ($scope.removePostRefresh) {
$scope.removePostRefresh();
}
$scope.removePostRefresh = $scope.$on('PostRefresh', function () {
// Cleanup after a delete
var i, j;
Wait('stop');
$('#prompt-modal').off();
list.fields.kind.searchOptions = scope.credential_kind_options;
list.fields.kind.searchOptions = $scope.credential_kind_options;
// Translate the kind value
for(var i=0; i < scope.credentials.length; i++) {
/*
if (scope.credentials[i].summary_fields.user) {
scope.credentials[i].user_username = scope.credentials[i].summary_fields.user.username;
}
if (scope.credentials[i].summary_fields.team) {
scope.credentials[i].team_name = scope.credentials[i].summary_fields.team.name;
}
*/
for (var j=0; j < scope.credential_kind_options.length; j++) {
if (scope.credential_kind_options[j].value == scope.credentials[i].kind) {
scope.credentials[i].kind = scope.credential_kind_options[j].label
for (i = 0; i < $scope.credentials.length; i++) {
for (j = 0; j < $scope.credential_kind_options.length; j++) {
if ($scope.credential_kind_options[j].value === $scope.credentials[i].kind) {
$scope.credentials[i].kind = $scope.credential_kind_options[j].label;
break;
}
}
}
});
if (scope.removeChoicesReady) {
scope.removeChoicesReady();
if ($scope.removeChoicesReady) {
$scope.removeChoicesReady();
}
scope.removeChoicesReady = scope.$on('choicesReadyCredential', function() {
SearchInit({ scope: scope, set: 'credentials', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
$scope.removeChoicesReady = $scope.$on('choicesReadyCredential', function () {
SearchInit({
scope: $scope,
set: 'credentials',
list: list,
url: defaultUrl
});
PaginateInit({
scope: $scope,
list: list,
url: defaultUrl
});
$scope.search(list.iterator);
});
// Load the list of options for Kind
GetChoices({
scope: scope,
scope: $scope,
url: defaultUrl,
field: 'kind',
variable: 'credential_kind_options',
@@ -82,75 +88,77 @@ function CredentialsList ($scope, $rootScope, $location, $log, $routeParams, Res
LoadBreadCrumbs();
scope.showActivity = function() { Stream({ scope: scope }); }
$scope.showActivity = function () {
Stream({ scope: $scope });
};
scope.addCredential = function() {
$scope.addCredential = function () {
$location.path($location.path() + '/add');
}
};
scope.editCredential = function(id) {
$scope.editCredential = function (id) {
$location.path($location.path() + '/' + id);
}
};
scope.deleteCredential = function(id, name) {
$scope.deleteCredential = function (id, name) {
var action = function() {
$('#prompt-modal').on('hidden.bs.modal', function(){ Wait('start'); });
var action = function () {
$('#prompt-modal').on('hidden.bs.modal', function () {
Wait('start');
});
$('#prompt-modal').modal('hide');
var url = defaultUrl + id + '/';
Rest.setUrl(url);
Rest.destroy()
.success( function(data, status, headers, config) {
scope.search(list.iterator);
.success(function () {
$scope.search(list.iterator);
})
.error( function(data, status, headers, config) {
Wait('stop');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
};
Prompt({ hdr: 'Delete',
Prompt({
hdr: 'Delete',
body: 'Are you sure you want to delete ' + name + '?',
action: action
});
}
};
}
CredentialsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'CredentialList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
'GetBasePath', 'SelectionInit', 'GetChoices', 'Wait', 'Stream' ];
CredentialsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'CredentialList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', 'GetBasePath',
'SelectionInit', 'GetChoices', 'Wait', 'Stream'
];
function CredentialsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
GenerateList, SearchInit, PaginateInit, LookUpInit, UserList, TeamList, GetBasePath,
GetChoices, Empty, KindChange, OwnerChange, FormSave, DebugForm)
{
ClearScope('tree-form');
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
function CredentialsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm, GenerateForm, Rest, Alert,
ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateList, SearchInit, PaginateInit, LookUpInit, UserList, TeamList,
GetBasePath, GetChoices, Empty, KindChange, OwnerChange, FormSave) {
ClearScope();
// Inject dynamic view
var defaultUrl = GetBasePath('credentials');
var form = CredentialForm;
var generator = GenerateForm;
var scope = generator.inject(form, {mode: 'add', related: false});
var base = $location.path().replace(/^\//,'').split('/')[0];
var defaultUrl = GetBasePath('credentials');
var form = CredentialForm,
generator = GenerateForm,
defaultUrl = GetBasePath('credentials'),
url;
generator.inject(form, { mode: 'add', related: false, scope: $scope });
generator.reset();
LoadBreadCrumbs();
// Load the list of options for Kind
GetChoices({
scope: scope,
scope: $scope,
url: defaultUrl,
field: 'kind',
variable: 'credential_kind_options'
});
LookUpInit({
scope: scope,
scope: $scope,
form: form,
current_item: (!Empty($routeParams.user_id)) ? $routeParams.user_id : null,
list: UserList,
@@ -158,7 +166,7 @@ function CredentialsAdd ($scope, $rootScope, $compile, $location, $log, $routePa
});
LookUpInit({
scope: scope,
scope: $scope,
form: form,
current_item: (!Empty($routeParams.team_id)) ? $routeParams.team_id : null,
list: TeamList,
@@ -167,344 +175,351 @@ function CredentialsAdd ($scope, $rootScope, $compile, $location, $log, $routePa
if (!Empty($routeParams.user_id)) {
// Get the username based on incoming route
scope['owner'] = 'user';
scope['user'] = $routeParams.user_id;
OwnerChange({ scope: scope });
var url = GetBasePath('users') + $routeParams.user_id + '/';
$scope.owner = 'user';
$scope.user = $routeParams.user_id;
OwnerChange({ scope: $scope });
url = GetBasePath('users') + $routeParams.user_id + '/';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
scope['user_username'] = data.username;
.success(function (data) {
$scope.user_username = data.username;
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to retrieve user. GET status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve user. GET status: ' + status });
});
}
else if (!Empty($routeParams.team_id)) {
} else if (!Empty($routeParams.team_id)) {
// Get the username based on incoming route
scope['owner'] = 'team';
scope['team'] = $routeParams.team_id;
OwnerChange({ scope: scope });
var url = GetBasePath('teams') + $routeParams.team_id + '/';
$scope.owner = 'team';
$scope.team = $routeParams.team_id;
OwnerChange({ scope: $scope });
url = GetBasePath('teams') + $routeParams.team_id + '/';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
scope['team_name'] = data.name;
.success(function (data) {
$scope.team_name = data.name;
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to retrieve team. GET status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve team. GET status: ' + status });
});
}
else {
} else {
// default type of owner to a user
scope['owner'] = 'user';
OwnerChange({ scope: scope });
$scope.owner = 'user';
OwnerChange({ scope: $scope });
}
// Handle Kind change
scope.kindChange = function () {
KindChange({ scope: scope, form: form, reset: true });
}
$scope.kindChange = function () {
KindChange({ scope: $scope, form: form, reset: true });
};
// Save
scope.formSave = function() { generator.clearApiErrors(); FormSave({ scope: scope, mode: 'add' }) };
$scope.formSave = function () {
generator.clearApiErrors();
FormSave({ scope: $scope, mode: 'add' });
};
// Handle Owner change
scope.ownerChange = function() {
OwnerChange({ scope: scope });
}
$scope.ownerChange = function () {
OwnerChange({ scope: $scope });
};
// Reset defaults
scope.formReset = function() {
$scope.formReset = function () {
generator.reset();
//DebugForm({ form: CredentialForm, scope: scope });
};
// Password change
scope.clearPWConfirm = function(fld) {
$scope.clearPWConfirm = function (fld) {
// If password value changes, make sure password_confirm must be re-entered
scope[fld] = '';
scope[form.name + '_form'][fld].$setValidity('awpassmatch', false);
}
$scope[fld] = '';
$scope[form.name + '_form'][fld].$setValidity('awpassmatch', false);
};
// Respond to 'Ask at runtime?' checkbox
scope.ask = function(fld, associated) {
if (scope[fld + '_ask']) {
scope[fld] = 'ASK';
scope[associated] = '';
scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
}
else {
scope[fld] = '';
scope[associated] = '';
scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
}
$scope.ask = function (fld, associated) {
if ($scope[fld + '_ask']) {
$scope[fld] = 'ASK';
$scope[associated] = '';
$scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
} else {
$scope[fld] = '';
$scope[associated] = '';
$scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
}
};
// Click clear button
scope.clear = function(fld, associated) {
scope[fld] = '';
scope[associated] = '';
scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
scope[form.name + '_form'].$setDirty();
}
$scope.clear = function (fld, associated) {
$scope[fld] = '';
$scope[associated] = '';
$scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
$scope[form.name + '_form'].$setDirty();
};
}
CredentialsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'CredentialForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList',
'SearchInit', 'PaginateInit', 'LookUpInit', 'UserList', 'TeamList', 'GetBasePath', 'GetChoices', 'Empty',
'KindChange', 'OwnerChange', 'FormSave', 'DebugForm'];
CredentialsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'CredentialForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList', 'SearchInit', 'PaginateInit',
'LookUpInit', 'UserList', 'TeamList', 'GetBasePath', 'GetChoices', 'Empty', 'KindChange', 'OwnerChange', 'FormSave'
];
function CredentialsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
RelatedPaginateInit, ReturnToCaller, ClearScope, Prompt, GetBasePath, GetChoices,
KindChange, UserList, TeamList, LookUpInit, Empty, OwnerChange, FormSave, Stream,
Wait
)
{
ClearScope('tree-form');
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
function CredentialsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm, GenerateForm, Rest, Alert,
ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, Prompt, GetBasePath, GetChoices,
KindChange, UserList, TeamList, LookUpInit, Empty, OwnerChange, FormSave, Stream, Wait) {
var defaultUrl=GetBasePath('credentials');
var generator = GenerateForm;
var form = CredentialForm;
var scope = generator.inject(form, {mode: 'edit', related: true});
ClearScope();
var defaultUrl = GetBasePath('credentials'),
generator = GenerateForm,
form = CredentialForm,
base = $location.path().replace(/^\//, '').split('/')[0],
master = {},
id = $routeParams.credential_id;
generator.inject(form, { mode: 'edit', related: true, scope: $scope });
generator.reset();
var base = $location.path().replace(/^\//,'').split('/')[0];
var defaultUrl = GetBasePath('credentials');
var master = {};
var id = $routeParams.credential_id;
scope['id'] = id;
var relatedSets = {};
$scope.id = id;
function setAskCheckboxes() {
for (var fld in form.fields) {
if (form.fields[fld].type == 'password' && scope[fld] == 'ASK') {
var fld, i;
for (fld in form.fields) {
if (form.fields[fld].type === 'password' && $scope[fld] === 'ASK') {
// turn on 'ask' checkbox for password fields with value of 'ASK'
$("#" + fld + "-clear-btn").attr("disabled","disabled");
scope[fld + '_ask'] = true;
}
else {
scope[fld + '_ask'] = false;
$("#" + fld + "-clear-btn").attr("disabled", "disabled");
$scope[fld + '_ask'] = true;
} else {
$scope[fld + '_ask'] = false;
$("#" + fld + "-clear-btn").removeAttr("disabled");
}
master[fld + '_ask'] = scope[fld + '_ask'];
master[fld + '_ask'] = $scope[fld + '_ask'];
}
// Set kind field to the correct option
for (var i=0; i < scope['credential_kind_options'].length; i++) {
if (scope['kind'] == scope['credential_kind_options'][i].value) {
scope['kind'] = scope['credential_kind_options'][i];
for (i = 0; i < $scope.credential_kind_options.length; i++) {
if ($scope.kind === $scope.credential_kind_options[i].value) {
$scope.kind = $scope.credential_kind_options[i];
break;
}
}
}
if (scope.removeCredentialLoaded) {
scope.removeCredentialLoaded();
if ($scope.removeCredentialLoaded) {
$scope.removeCredentialLoaded();
}
scope.removeCredentialLoaded = scope.$on('credentialLoaded', function() {
$scope.removeCredentialLoaded = $scope.$on('credentialLoaded', function () {
LookUpInit({
scope: scope,
scope: $scope,
form: form,
current_item: (!Empty($scope['user_id'])) ? scope['user_id'] : null,
current_item: (!Empty($scope.user_id)) ? $scope.user_id : null,
list: UserList,
field: 'user'
});
LookUpInit({
scope: scope,
scope: $scope,
form: form,
current_item: (!Empty($scope['team_id'])) ? scope['team_id'] : null,
current_item: (!Empty($scope.team_id)) ? $scope.team_id : null,
list: TeamList,
field: 'team'
});
setAskCheckboxes();
KindChange({ scope: scope, form: form, reset: false });
OwnerChange({ scope: scope });
KindChange({
scope: $scope,
form: form,
reset: false
});
OwnerChange({ scope: $scope });
Wait('stop');
});
if (scope.removeChoicesReady) {
scope.removeChoicesReady();
if ($scope.removeChoicesReady) {
$scope.removeChoicesReady();
}
scope.removeChoicesReady = scope.$on('choicesReadyCredential', function() {
$scope.removeChoicesReady = $scope.$on('choicesReadyCredential', function () {
// Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl + ':id/');
Rest.get({ params: {id: id} })
.success( function(data, status, headers, config) {
LoadBreadCrumbs({ path: '/credentials/' + id, title: data.name });
for (var fld in form.fields) {
Rest.get({ params: { id: id } })
.success(function (data) {
var i, fld;
LoadBreadCrumbs({
path: '/credentials/' + id,
title: data.name
});
for (fld in form.fields) {
if (data[fld] !== null && data[fld] !== undefined) {
scope[fld] = data[fld];
master[fld] = scope[fld];
$scope[fld] = data[fld];
master[fld] = $scope[fld];
}
if (form.fields[fld].type == 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) {
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
if (form.fields[fld].type === 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) {
$scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField];
$scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField];
}
}
if (!Empty(scope['user'])) {
scope['owner'] = 'user';
if (!Empty($scope.user)) {
$scope.owner = 'user';
} else {
$scope.owner = 'team';
}
else {
scope['owner'] = 'team';
}
master['owner'] = scope['owner'];
master.owner = $scope.owner;
for (var i=0; i < scope.credential_kind_options.length; i++) {
if (scope.credential_kind_options[i].value == data.kind) {
scope.kind = scope.credential_kind_options[i];
for (i = 0; i < $scope.credential_kind_options.length; i++) {
if ($scope.credential_kind_options[i].value === data.kind) {
$scope.kind = $scope.credential_kind_options[i];
break;
}
}
master['kind'] = scope['kind'];
master.kind = $scope.kind;
switch (data.kind) {
case 'aws':
scope['access_key'] = data.username;
scope['secret_key'] = data.password;
master['access_key'] = scope['access_key'];
master['secret_key'] = scope['secret_key'];
$scope.access_key = data.username;
$scope.secret_key = data.password;
master.access_key = $scope.access_key;
master.secret_key = $scope.secret_key;
break;
case 'ssh':
scope['ssh_password'] = data.password;
master['ssh_password'] = scope['ssh_password'];
$scope.ssh_password = data.password;
master.ssh_password = $scope.ssh_password;
break;
case 'rax':
scope['api_key'] = data['password'];
master['api_key'] = scope['api_key'];
$scope.api_key = data.password;
master.api_key = $scope.api_key;
break;
}
scope.$emit('credentialLoaded');
$scope.$emit('credentialLoaded');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve Credential: ' + $routeParams.id + '. GET status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to retrieve Credential: ' + $routeParams.id + '. GET status: ' + status });
});
});
Wait('start');
GetChoices({
scope: scope,
scope: $scope,
url: defaultUrl,
field: 'kind',
variable: 'credential_kind_options',
callback: 'choicesReadyCredential'
});
scope.showActivity = function() { Stream({ scope: scope }); }
$scope.showActivity = function () {
Stream({ scope: $scope });
};
// Save changes to the parent
scope.formSave = function() { generator.clearApiErrors(); FormSave({ scope: scope, mode: 'edit' }) };
$scope.formSave = function () {
generator.clearApiErrors();
FormSave({ scope: $scope, mode: 'edit' });
};
// Handle Owner change
scope.ownerChange = function() {
OwnerChange({ scope: scope });
}
$scope.ownerChange = function () {
OwnerChange({ scope: $scope });
};
// Handle Kind change
scope.kindChange = function () {
KindChange({ scope: scope, form: form, reset: true });
}
$scope.kindChange = function () {
KindChange({ scope: $scope, form: form, reset: true });
};
// Cancel
scope.formReset = function() {
$scope.formReset = function () {
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
$scope[fld] = master[fld];
}
setAskCheckboxes();
KindChange({ scope: scope, form: form, reset: false });
OwnerChange({ scope: scope });
KindChange({ scope: $scope, form: form, reset: false });
OwnerChange({ scope: $scope });
};
// Related set: Add button
scope.add = function(set) {
$scope.add = function (set) {
$rootScope.flashMessage = null;
$location.path('/' + base + '/' + $routeParams.id + '/' + set + '/add');
};
// Related set: Edit button
scope.edit = function(set, id, name) {
$scope.edit = function (set, id) {
$rootScope.flashMessage = null;
$location.path('/' + base + '/' + $routeParams.id + '/' + set + '/' + id);
};
// Related set: Delete button
scope['delete'] = function(set, itm_id, name, title) {
$scope['delete'] = function (set, itm_id, name, title) {
$rootScope.flashMessage = null;
var action = function() {
var action = function () {
var url = defaultUrl + id + '/' + set + '/';
Rest.setUrl(url);
Rest.post({ id: itm_id, disassociate: 1 })
.success( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
scope.search(form.related[set].iterator);
Rest.post({
id: itm_id,
disassociate: 1
})
.error( function(data, status, headers, config) {
.success(function () {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
$scope.search(form.related[set].iterator);
})
.error(function (data, status) {
$('#prompt-modal').modal('hide');
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. POST returned status: ' + status
});
});
};
Prompt({ hdr: 'Delete',
body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?',
Prompt({
hdr: 'Delete',
body: 'Are you sure you want to remove ' + name + ' from ' + $scope.name + ' ' + title + '?',
action: action
});
}
};
// Password change
scope.clearPWConfirm = function(fld) {
$scope.clearPWConfirm = function (fld) {
// If password value changes, make sure password_confirm must be re-entered
scope[fld] = '';
scope[form.name + '_form'][fld].$setValidity('awpassmatch', false);
}
$scope[fld] = '';
$scope[form.name + '_form'][fld].$setValidity('awpassmatch', false);
};
// Respond to 'Ask at runtime?' checkbox
scope.ask = function(fld, associated) {
if (scope[fld + '_ask']) {
$("#" + fld + "-clear-btn").attr("disabled","disabled");
scope[fld] = 'ASK';
scope[associated] = '';
scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
}
else {
$scope.ask = function (fld, associated) {
if ($scope[fld + '_ask']) {
$("#" + fld + "-clear-btn").attr("disabled", "disabled");
$scope[fld] = 'ASK';
$scope[associated] = '';
$scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
} else {
$("#" + fld + "-clear-btn").removeAttr("disabled");
scope[fld] = '';
scope[associated] = '';
scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
}
$scope[fld] = '';
$scope[associated] = '';
$scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
}
};
scope.clear = function(fld, associated) {
scope[fld] = '';
scope[associated] = '';
scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
scope[form.name + '_form'].$setDirty();
}
$scope.clear = function (fld, associated) {
$scope[fld] = '';
$scope[associated] = '';
$scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
$scope[form.name + '_form'].$setDirty();
};
}
CredentialsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'CredentialForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'Prompt', 'GetBasePath', 'GetChoices',
'KindChange', 'UserList', 'TeamList', 'LookUpInit', 'Empty', 'OwnerChange', 'FormSave', 'Stream',
'Wait'];
CredentialsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'CredentialForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit',
'ReturnToCaller', 'ClearScope', 'Prompt', 'GetBasePath', 'GetChoices', 'KindChange', 'UserList', 'TeamList', 'LookUpInit',
'Empty', 'OwnerChange', 'FormSave', 'Stream', 'Wait'
];

View File

@@ -10,15 +10,16 @@
'use strict';
function Home ($scope, $compile, $routeParams, $rootScope, $location, Wait, ObjectCount, JobStatus, InventorySyncStatus, SCMSyncStatus,
function Home($scope, $compile, $routeParams, $rootScope, $location, Wait, ObjectCount, JobStatus, InventorySyncStatus, SCMSyncStatus,
ClearScope, Stream, Rest, GetBasePath, ProcessErrors, Button) {
ClearScope('home'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
ClearScope('home');
var buttons, html, e, waitCount, loadedCount;
// Add buttons to the top of the Home page. We're using lib/ansible/generator_helpers.js-> Buttons()
// to build buttons dynamically and insure all styling and icons match the rest of the application.
var buttons = {
buttons = {
refresh: {
mode: 'all',
awToolTip: "Refresh the page",
@@ -30,16 +31,27 @@ function Home ($scope, $compile, $routeParams, $rootScope, $location, Wait, Obje
mode: 'all'
}
};
var html = Button({ btn: buttons.refresh, action: 'refresh', toolbar: true });
html += Button({ btn: buttons.stream, action: 'stream', toolbar: true });
var e = angular.element(document.getElementById('home-list-actions'));
html = Button({
btn: buttons.refresh,
action: 'refresh',
toolbar: true
});
html += Button({
btn: buttons.stream,
action: 'stream',
toolbar: true
});
e = angular.element(document.getElementById('home-list-actions'));
e.html(html);
$compile(e)($scope);
var waitCount = 4;
var loadedCount = 0;
waitCount = 4;
loadedCount = 0;
if (!$routeParams['login']) {
if (!$routeParams.login) {
// If we're not logging in, start the Wait widget. Otherwise, it's already running.
Wait('start');
}
@@ -47,10 +59,10 @@ function Home ($scope, $compile, $routeParams, $rootScope, $location, Wait, Obje
if ($scope.removeWidgetLoaded) {
$scope.removeWidgetLoaded();
}
$scope.removeWidgetLoaded = $scope.$on('WidgetLoaded', function() {
$scope.removeWidgetLoaded = $scope.$on('WidgetLoaded', function () {
// Once all the widgets report back 'loaded', turn off Wait widget
loadedCount++;
if ( loadedCount == waitCount ) {
if (loadedCount === waitCount) {
Wait('stop');
}
});
@@ -58,60 +70,79 @@ function Home ($scope, $compile, $routeParams, $rootScope, $location, Wait, Obje
if ($scope.removeDashboardReady) {
$scope.removeDashboardReady();
}
$scope.removeDashboardReady = $scope.$on('dashboardReady', function(e, data) {
JobStatus({ scope: $scope, target: 'container1', dashboard: data});
InventorySyncStatus({ scope: $scope, target: 'container2', dashboard: data});
SCMSyncStatus({ scope: $scope, target: 'container4', dashboard: data});
ObjectCount({ scope: $scope, target: 'container3', dashboard: data});
$scope.removeDashboardReady = $scope.$on('dashboardReady', function (e, data) {
JobStatus({
scope: $scope,
target: 'container1',
dashboard: data
});
InventorySyncStatus({
scope: $scope,
target: 'container2',
dashboard: data
});
SCMSyncStatus({
scope: $scope,
target: 'container4',
dashboard: data
});
ObjectCount({
scope: $scope,
target: 'container3',
dashboard: data
});
});
$scope.showActivity = function() { Stream({ scope: $scope }); }
$scope.showActivity = function () {
Stream({
scope: $scope
});
};
$scope.refresh = function() {
$scope.refresh = function () {
Wait('start');
loadedCount = 0;
Rest.setUrl(GetBasePath('dashboard'));
Rest.get()
.success( function(data, status, headers, config) {
.success(function (data) {
$scope.$emit('dashboardReady', data);
})
.error ( function(data, status, headers, config) {
.error(function (data, status) {
Wait('stop');
ProcessErrors($scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get dashboard: ' + status });
})
}
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get dashboard: ' + status });
});
};
$scope.refresh();
}
}
Home.$inject=['$scope', '$compile', '$routeParams', '$rootScope', '$location', 'Wait', 'ObjectCount', 'JobStatus', 'InventorySyncStatus',
'SCMSyncStatus', 'ClearScope', 'Stream', 'Rest', 'GetBasePath', 'ProcessErrors', 'Button'];
Home.$inject = ['$scope', '$compile', '$routeParams', '$rootScope', '$location', 'Wait', 'ObjectCount', 'JobStatus', 'InventorySyncStatus',
'SCMSyncStatus', 'ClearScope', 'Stream', 'Rest', 'GetBasePath', 'ProcessErrors', 'Button'
];
function HomeGroups ($location, $routeParams, HomeGroupList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
function HomeGroups($location, $routeParams, HomeGroupList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
GetBasePath, SearchInit, PaginateInit, FormatDate, GetHostsStatusMsg, GetSyncStatusMsg, ViewUpdateStatus, Stream, GroupsEdit, Wait,
Alert, Rest, Empty, InventoryUpdate, Find) {
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var generator = GenerateList;
var list = HomeGroupList;
var defaultUrl=GetBasePath('groups');
var scope = generator.inject(list, { mode: 'edit' });
var base = $location.path().replace(/^\//,'').split('/')[0];
var generator = GenerateList,
list = HomeGroupList,
defaultUrl = GetBasePath('groups'),
scope = generator.inject(list, { mode: 'edit' }),
opt;
if (scope.removePostRefresh) {
scope.removePostRefresh();
}
scope.removePostRefresh = scope.$on('PostRefresh', function() {
var hosts_status, update_status, last_update, stat;
for (var i=0; i < scope.home_groups.length; i++) {
scope.removePostRefresh = scope.$on('PostRefresh', function () {
var i, hosts_status, stat;
for (i = 0; i < scope.home_groups.length; i++) {
scope['home_groups'][i]['inventory_name'] = scope['home_groups'][i]['summary_fields']['inventory']['name'];
scope.home_groups[i].inventory_name = scope.home_groups[i].summary_fields.inventory.name;
stat = GetSyncStatusMsg({
status: scope.home_groups[i].summary_fields.inventory_source.status
@@ -124,119 +155,135 @@ function HomeGroups ($location, $routeParams, HomeGroupList, GenerateList, Proce
group_id: scope.home_groups[i].id
});
scope['home_groups'][i].status_class = stat['class'],
scope['home_groups'][i].status_tooltip = stat['tooltip'],
scope['home_groups'][i].launch_tooltip = stat['launch_tip'],
scope['home_groups'][i].launch_class = stat['launch_class'],
scope['home_groups'][i].hosts_status_tip = hosts_status['tooltip'],
scope['home_groups'][i].show_failures = hosts_status['failures'],
scope['home_groups'][i].hosts_status_class = hosts_status['class'],
scope.home_groups[i].status_class = stat['class'];
scope.home_groups[i].status_tooltip = stat.tooltip;
scope.home_groups[i].launch_tooltip = stat.launch_tip;
scope.home_groups[i].launch_class = stat.launch_class;
scope.home_groups[i].hosts_status_tip = hosts_status.tooltip;
scope.home_groups[i].show_failures = hosts_status.failures;
scope.home_groups[i].hosts_status_class = hosts_status['class'];
scope.home_groups[i].status = scope.home_groups[i].summary_fields.inventory_source.status;
scope.home_groups[i].source = (scope.home_groups[i].summary_fields.inventory_source) ?
scope.home_groups[i].summary_fields.inventory_source.source : null;
}
});
SearchInit({ scope: scope, set: 'home_groups', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
SearchInit({
scope: scope,
set: 'home_groups',
list: list,
url: defaultUrl
});
PaginateInit({
scope: scope,
list: list,
url: defaultUrl
});
// Process search params
if ($routeParams['name']) {
if ($routeParams.name) {
scope[list.iterator + 'InputDisable'] = false;
scope[list.iterator + 'SearchValue'] = $routeParams['name'];
scope[list.iterator + 'SearchValue'] = $routeParams.name;
scope[list.iterator + 'SearchField'] = 'name';
scope[list.iterator + 'SearchFieldLabel'] = list.fields['name'].label;
scope[list.iterator + 'SearchFieldLabel'] = list.fields.name.label;
scope[list.iterator + 'SearchSelectValue'] = null;
}
if ($routeParams['id']) {
if ($routeParams.id) {
scope[list.iterator + 'InputDisable'] = false;
scope[list.iterator + 'SearchValue'] = $routeParams['id'];
scope[list.iterator + 'SearchValue'] = $routeParams.id;
scope[list.iterator + 'SearchField'] = 'id';
scope[list.iterator + 'SearchFieldLabel'] = list.fields['id'].label;
scope[list.iterator + 'SearchFieldLabel'] = list.fields.id.label;
scope[list.iterator + 'SearchSelectValue'] = null;
}
if ($routeParams['has_active_failures']) {
if ($routeParams.has_active_failures) {
scope[list.iterator + 'InputDisable'] = true;
scope[list.iterator + 'SearchValue'] = $routeParams['has_active_failures'];
scope[list.iterator + 'SearchValue'] = $routeParams.has_active_failures;
scope[list.iterator + 'SearchField'] = 'has_active_failures';
scope[list.iterator + 'SearchFieldLabel'] = list.fields['has_active_failures'].label;
scope[list.iterator + 'SearchSelectValue'] = ($routeParams['has_active_failures'] == 'true') ? { value: 1 } : { value: 0 };
scope[list.iterator + 'SearchFieldLabel'] = list.fields.has_active_failures.label;
scope[list.iterator + 'SearchSelectValue'] = ($routeParams.has_active_failures === 'true') ? { value: 1 } : { value: 0 };
}
if ($routeParams['status'] && !$routeParams['source']) {
if ($routeParams.status && !$routeParams.source) {
scope[list.iterator + 'SearchField'] = 'status';
scope[list.iterator + 'SelectShow'] = true;
scope[list.iterator + 'SearchSelectOpts'] = list.fields['status'].searchOptions;
scope[list.iterator + 'SearchFieldLabel'] = list.fields['status'].label.replace(/\<br\>/g,' ');
for (var opt in list.fields['status'].searchOptions) {
if (list.fields['status'].searchOptions[opt].value == $routeParams['status']) {
scope[list.iterator + 'SearchSelectValue'] = list.fields['status'].searchOptions[opt];
scope[list.iterator + 'SearchSelectOpts'] = list.fields.status.searchOptions;
scope[list.iterator + 'SearchFieldLabel'] = list.fields.status.label.replace(/<br\>/g, ' ');
for (opt in list.fields.status.searchOptions) {
if (list.fields.status.searchOptions[opt].value === $routeParams.status) {
scope[list.iterator + 'SearchSelectValue'] = list.fields.status.searchOptions[opt];
break;
}
}
}
if ($routeParams['source']) {
if ($routeParams.source) {
scope[list.iterator + 'SearchField'] = 'source';
scope[list.iterator + 'SelectShow'] = true;
scope[list.iterator + 'SearchSelectOpts'] = list.fields['source'].searchOptions;
scope[list.iterator + 'SearchFieldLabel'] = list.fields['source'].label.replace(/\<br\>/g,' ');
for (var opt in list.fields['source'].searchOptions) {
if (list.fields['source'].searchOptions[opt].value == $routeParams['source']) {
scope[list.iterator + 'SearchSelectValue'] = list.fields['source'].searchOptions[opt];
scope[list.iterator + 'SearchSelectOpts'] = list.fields.source.searchOptions;
scope[list.iterator + 'SearchFieldLabel'] = list.fields.source.label.replace(/<br\>/g, ' ');
for (opt in list.fields.source.searchOptions) {
if (list.fields.source.searchOptions[opt].value === $routeParams.source) {
scope[list.iterator + 'SearchSelectValue'] = list.fields.source.searchOptions[opt];
break;
}
}
if ($routeParams['status']) {
scope[list.iterator + 'ExtraParms'] = '&inventory_source__status__icontains=' + $routeParams['status'];
if ($routeParams.status) {
scope[list.iterator + 'ExtraParms'] = '&inventory_source__status__icontains=' + $routeParams.status;
}
}
if ($routeParams['has_external_source']) {
if ($routeParams.has_external_source) {
scope[list.iterator + 'SearchField'] = 'has_external_source';
scope[list.iterator + 'SearchValue'] = list.fields['has_external_source'].searchValue;
scope[list.iterator + 'SearchValue'] = list.fields.has_external_source.searchValue;
scope[list.iterator + 'InputDisable'] = true;
scope[list.iterator + 'SearchType'] = 'in';
scope[list.iterator + 'SearchFieldLabel'] = list.fields['has_external_source'].label;
scope[list.iterator + 'SearchFieldLabel'] = list.fields.has_external_source.label;
}
scope.search(list.iterator);
LoadBreadCrumbs();
scope.showActivity = function() { Stream({ scope: scope }); }
scope.showActivity = function () {
Stream({
scope: scope
});
};
scope.editGroup = function(group_id, inventory_id) {
GroupsEdit({ scope: scope, group_id: group_id, inventory_id: inventory_id, groups_reload: false });
}
scope.editGroup = function (group_id, inventory_id) {
GroupsEdit({
scope: scope,
group_id: group_id,
inventory_id: inventory_id,
groups_reload: false
});
};
scope.viewUpdateStatus = function(id) {
scope.viewUpdateStatus = function (id) {
scope.groups = scope.home_groups;
ViewUpdateStatus({ scope: scope, tree_id: id })
ViewUpdateStatus({
scope: scope,
tree_id: id
});
};
// Launch inventory sync
scope.updateGroup = function(id) {
var group = Find({ list: scope.home_groups, key: 'id', val: id});
scope.updateGroup = function (id) {
var group = Find({ list: scope.home_groups, key: 'id', val: id });
if (group) {
if (Empty(group.source)) {
// if no source, do nothing.
}
else if (group.status == 'updating') {
} else if (group.status === 'updating') {
Alert('Update in Progress', 'The inventory update process is currently running for group <em>' +
scope.home_groups[i].name + '</em>. Use the Refresh button to monitor the status.', 'alert-info');
}
else {
group.name + '</em>. Use the Refresh button to monitor the status.', 'alert-info');
} else {
Wait('start');
Rest.setUrl(group.related.inventory_source);
Rest.get()
.success( function(data, status, headers, config) {
.success(function (data) {
InventoryUpdate({
scope: scope,
url: data.related.update,
@@ -246,98 +293,132 @@ function HomeGroups ($location, $routeParams, HomeGroupList, GenerateList, Proce
group_id: group.id
});
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve inventory source: ' + group.related.inventory_source +
' POST returned status: ' + status });
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve inventory source: ' + group.related.inventory_source + ' POST returned status: ' + status
});
});
}
}
}
};
scope.refresh = function() { scope.search(list.iterator, null, false, true); }
scope.refresh = function () {
scope.search(list.iterator, null, false, true);
};
}
}
HomeGroups.$inject = [ '$location', '$routeParams', 'HomeGroupList', 'GenerateList', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller',
HomeGroups.$inject = ['$location', '$routeParams', 'HomeGroupList', 'GenerateList', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller',
'ClearScope', 'GetBasePath', 'SearchInit', 'PaginateInit', 'FormatDate', 'GetHostsStatusMsg', 'GetSyncStatusMsg', 'ViewUpdateStatus',
'Stream', 'GroupsEdit', 'Wait', 'Alert', 'Rest', 'Empty', 'InventoryUpdate', 'Find'
];
];
function HomeHosts ($location, $routeParams, HomeHostList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
function HomeHosts($location, $routeParams, HomeHostList, GenerateList, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
GetBasePath, SearchInit, PaginateInit, FormatDate, SetStatus, ToggleHostEnabled, HostsEdit, Stream, Find, ShowJobSummary) {
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var generator = GenerateList;
var list = HomeHostList;
var defaultUrl=GetBasePath('hosts');
var scope = generator.inject(list, { mode: 'edit' });
var base = $location.path().replace(/^\//,'').split('/')[0];
var generator = GenerateList,
list = HomeHostList,
defaultUrl = GetBasePath('hosts'),
scope = generator.inject(list, { mode: 'edit' });
if (scope.removePostRefresh) {
scope.removePostRefresh();
}
scope.removePostRefresh = scope.$on('PostRefresh', function() {
for (var i=0; i < scope.hosts.length; i++) {
scope['hosts'][i]['inventory_name'] = scope['hosts'][i]['summary_fields']['inventory']['name'];
scope.removePostRefresh = scope.$on('PostRefresh', function () {
for (var i = 0; i < scope.hosts.length; i++) {
scope.hosts[i].inventory_name = scope.hosts[i].summary_fields.inventory.name;
//SetHostStatus(scope['hosts'][i]);
SetStatus({ scope: scope, host: scope['hosts'][i] });
SetStatus({
scope: scope,
host: scope.hosts[i]
});
}
});
SearchInit({ scope: scope, set: 'hosts', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
SearchInit({
scope: scope,
set: 'hosts',
list: list,
url: defaultUrl
});
PaginateInit({
scope: scope,
list: list,
url: defaultUrl
});
// Process search params
if ($routeParams['name']) {
if ($routeParams.name) {
scope[HomeHostList.iterator + 'InputDisable'] = false;
scope[HomeHostList.iterator + 'SearchValue'] = $routeParams['name'];
scope[HomeHostList.iterator + 'SearchValue'] = $routeParams.name;
scope[HomeHostList.iterator + 'SearchField'] = 'name';
scope[HomeHostList.iterator + 'SearchFieldLabel'] = list.fields['name'].label;
scope[HomeHostList.iterator + 'SearchFieldLabel'] = list.fields.name.label;
}
if ($routeParams['id']) {
if ($routeParams.id) {
scope[HomeHostList.iterator + 'InputDisable'] = false;
scope[HomeHostList.iterator + 'SearchValue'] = $routeParams['id'];
scope[HomeHostList.iterator + 'SearchValue'] = $routeParams.id;
scope[HomeHostList.iterator + 'SearchField'] = 'id';
scope[HomeHostList.iterator + 'SearchFieldLabel'] = list.fields['id'].label;
scope[HomeHostList.iterator + 'SearchFieldLabel'] = list.fields.id.label;
scope[HomeHostList.iterator + 'SearchSelectValue'] = null;
}
if ($routeParams['has_active_failures']) {
if ($routeParams.has_active_failures) {
scope[HomeHostList.iterator + 'InputDisable'] = true;
scope[HomeHostList.iterator + 'SearchValue'] = $routeParams['has_active_failures'];
scope[HomeHostList.iterator + 'SearchValue'] = $routeParams.has_active_failures;
scope[HomeHostList.iterator + 'SearchField'] = 'has_active_failures';
scope[HomeHostList.iterator + 'SearchFieldLabel'] = HomeHostList.fields['has_active_failures'].label;
scope[HomeHostList.iterator + 'SearchSelectValue'] = ($routeParams['has_active_failures'] == 'true') ? { value: 1 } : { value: 0 };
scope[HomeHostList.iterator + 'SearchFieldLabel'] = HomeHostList.fields.has_active_failures.label;
scope[HomeHostList.iterator + 'SearchSelectValue'] = ($routeParams.has_active_failures === 'true') ? { value: 1 } : { value: 0 };
}
scope.search(list.iterator);
LoadBreadCrumbs();
scope.showActivity = function() { Stream({ scope: scope }); }
scope.showActivity = function () {
Stream({
scope: scope
});
};
scope.toggle_host_enabled = function(id, sources) { ToggleHostEnabled({ host_id: id, external_source: sources, scope: scope }); }
scope.toggle_host_enabled = function (id, sources) {
ToggleHostEnabled({
host_id: id,
external_source: sources,
scope: scope
});
};
scope.editHost = function(host_id, host_name) {
var host = Find({ list: scope.hosts, key: 'id', val: host_id });
scope.editHost = function (host_id) {
var host = Find({
list: scope.hosts,
key: 'id',
val: host_id
});
if (host) {
HostsEdit({ scope: scope, host_id: host_id, inventory_id: host.inventory, group_id: null, hostsReload: false });
}
HostsEdit({
scope: scope,
host_id: host_id,
inventory_id: host.inventory,
group_id: null,
hostsReload: false
});
}
};
scope.showJobSummary = function(job_id) {
ShowJobSummary({ job_id: job_id });
}
scope.showJobSummary = function (job_id) {
ShowJobSummary({
job_id: job_id
});
};
}
}
HomeHosts.$inject = [ '$location', '$routeParams', 'HomeHostList', 'GenerateList', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller',
HomeHosts.$inject = ['$location', '$routeParams', 'HomeHostList', 'GenerateList', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller',
'ClearScope', 'GetBasePath', 'SearchInit', 'PaginateInit', 'FormatDate', 'SetStatus', 'ToggleHostEnabled', 'HostsEdit', 'Stream',
'Find', 'ShowJobSummary'
];
];

View File

@@ -10,223 +10,241 @@
'use strict';
function InventoriesList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, InventoryList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
ClearScope, ProcessErrors, GetBasePath, Wait, Stream, EditInventoryProperties)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var list = InventoryList;
var defaultUrl = GetBasePath('inventory');
var view = GenerateList;
var paths = $location.path().replace(/^\//,'').split('/');
var mode = (paths[0] == 'inventories') ? 'edit' : 'select'; // if base path 'users', we're here to add/edit users
var scope = view.inject(InventoryList, { mode: mode }); // Inject our view
function InventoriesList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, InventoryList, GenerateList,
LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, Wait, Stream,
EditInventoryProperties) {
ClearScope();
var list = InventoryList,
defaultUrl = GetBasePath('inventory'),
view = GenerateList,
paths = $location.path().replace(/^\//, '').split('/'),
mode = (paths[0] === 'inventories') ? 'edit' : 'select';
view.inject(InventoryList, { mode: mode, $scope: $scope });
$rootScope.flashMessage = null;
SearchInit({ scope: scope, set: 'inventories', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
SearchInit({
scope: $scope,
set: 'inventories',
list: list,
url: defaultUrl
});
PaginateInit({
scope: $scope,
list: list,
url: defaultUrl
});
if ($routeParams['name']) {
scope[InventoryList.iterator + 'InputDisable'] = false;
scope[InventoryList.iterator + 'SearchValue'] = $routeParams['name'];
scope[InventoryList.iterator + 'SearchField'] = 'name';
scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields['name'].label;
scope[InventoryList.iterator + 'SearchSelectValue'] = null;
if ($routeParams.name) {
$scope[InventoryList.iterator + 'InputDisable'] = false;
$scope[InventoryList.iterator + 'SearchValue'] = $routeParams.name;
$scope[InventoryList.iterator + 'SearchField'] = 'name';
$scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.name.label;
$scope[InventoryList.iterator + 'SearchSelectValue'] = null;
}
if ($routeParams['has_active_failures']) {
scope[InventoryList.iterator + 'InputDisable'] = true;
scope[InventoryList.iterator + 'SearchValue'] = $routeParams['has_active_failures'];
scope[InventoryList.iterator + 'SearchField'] = 'has_active_failures';
scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields['has_active_failures'].label;
scope[InventoryList.iterator + 'SearchSelectValue'] = ($routeParams['has_active_failures'] == 'true') ? { value: 1 } : { value: 0 };
if ($routeParams.has_active_failures) {
$scope[InventoryList.iterator + 'InputDisable'] = true;
$scope[InventoryList.iterator + 'SearchValue'] = $routeParams.has_active_failures;
$scope[InventoryList.iterator + 'SearchField'] = 'has_active_failures';
$scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.has_active_failures.label;
$scope[InventoryList.iterator + 'SearchSelectValue'] = ($routeParams.has_active_failures === 'true') ? {
value: 1
} : {
value: 0
};
}
if ($routeParams['has_inventory_sources']) {
scope[InventoryList.iterator + 'InputDisable'] = true;
scope[InventoryList.iterator + 'SearchValue'] = $routeParams['has_inventory_sources'];
scope[InventoryList.iterator + 'SearchField'] = 'has_inventory_sources';
scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields['has_inventory_sources'].label;
scope[InventoryList.iterator + 'SearchSelectValue'] = ($routeParams['has_inventory_sources'] == 'true') ? { value: 1 } : { value: 0 };
if ($routeParams.has_inventory_sources) {
$scope[InventoryList.iterator + 'InputDisable'] = true;
$scope[InventoryList.iterator + 'SearchValue'] = $routeParams.has_inventory_sources;
$scope[InventoryList.iterator + 'SearchField'] = 'has_inventory_sources';
$scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.has_inventory_sources.label;
$scope[InventoryList.iterator + 'SearchSelectValue'] = ($routeParams.has_inventory_sources === 'true') ? {
value: 1
} : {
value: 0
};
}
if ($routeParams['inventory_sources_with_failures']) {
if ($routeParams.inventory_sources_with_failures) {
// pass a value of true, however this field actually contains an integer value
scope[InventoryList.iterator + 'InputDisable'] = true;
scope[InventoryList.iterator + 'SearchValue'] = $routeParams['inventory_sources_with_failures'];
scope[InventoryList.iterator + 'SearchField'] = 'inventory_sources_with_failures';
scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields['inventory_sources_with_failures'].label;
scope[InventoryList.iterator + 'SearchType'] = 'gtzero';
$scope[InventoryList.iterator + 'InputDisable'] = true;
$scope[InventoryList.iterator + 'SearchValue'] = $routeParams.inventory_sources_with_failures;
$scope[InventoryList.iterator + 'SearchField'] = 'inventory_sources_with_failures';
$scope[InventoryList.iterator + 'SearchFieldLabel'] = InventoryList.fields.inventory_sources_with_failures.label;
$scope[InventoryList.iterator + 'SearchType'] = 'gtzero';
}
scope.search(list.iterator);
$scope.search(list.iterator);
LoadBreadCrumbs();
if (scope.removePostRefresh) {
scope.removePostRefresh();
if ($scope.removePostRefresh) {
$scope.removePostRefresh();
}
scope.removePostRefresh = scope.$on('PostRefresh', function() {
$scope.removePostRefresh = $scope.$on('PostRefresh', function () {
//If we got here by deleting an inventory, stop the spinner and cleanup events
Wait('stop');
$('#prompt-modal').off();
for (var i=0; i < scope.inventories.length; i++) {
for (var i = 0; i < $scope.inventories.length; i++) {
// Set values for Failed Hosts column
//scope.inventories[i].failed_hosts = scope.inventories[i].hosts_with_active_failures + ' / ' + scope.inventories[i].total_hosts;
// $scope.inventories[i].failed_hosts = $scope.inventories[i].hosts_with_active_failures + ' / ' + $scope.inventories[i].total_hosts;
if (scope.inventories[i].hosts_with_active_failures > 0) {
scope.inventories[i].failed_hosts_tip = scope.inventories[i].hosts_with_active_failures +
( (scope.inventories[i].hosts_with_active_failures == 1) ? ' host' : ' hosts' ) + ' with job failures. Click to view details.';
scope.inventories[i].failed_hosts_link = '/#/inventories/' + scope.inventories[i].id + '/';
scope.inventories[i].failed_hosts_class = 'true';
}
else {
if (scope.inventories[i].total_hosts == 0) {
if ($scope.inventories[i].hosts_with_active_failures > 0) {
$scope.inventories[i].failed_hosts_tip = $scope.inventories[i].hosts_with_active_failures +
(( $scope.inventories[i].hosts_with_active_failures === 1) ? ' host' : ' hosts') + ' with job failures. Click to view details.';
$scope.inventories[i].failed_hosts_link = '/#/inventories/' + $scope.inventories[i].id + '/';
$scope.inventories[i].failed_hosts_class = 'true';
} else {
if ($scope.inventories[i].total_hosts === 0) {
// no hosts
scope.inventories[i].failed_hosts_tip = "No hosts defined. Click to add.";
scope.inventories[i].failed_hosts_link = '/#/inventories/' + scope.inventories[i].id + '/';
scope.inventories[i].failed_hosts_class = 'na';
}
else {
$scope.inventories[i].failed_hosts_tip = "No hosts defined. Click to add.";
$scope.inventories[i].failed_hosts_link = '/#/inventories/' + $scope.inventories[i].id + '/';
$scope.inventories[i].failed_hosts_class = 'na';
} else {
// many hosts with 0 failures
scope.inventories[i].failed_hosts_tip = scope.inventories[i].total_hosts +
( (scope.inventories[i].total_hosts > 1) ? ' hosts' : ' host' ) + " with no job failures. Click to view details.";
scope.inventories[i].failed_hosts_link = '/#/inventories/' + scope.inventories[i].id + '/';
scope.inventories[i].failed_hosts_class = 'false';
$scope.inventories[i].failed_hosts_tip = $scope.inventories[i].total_hosts +
(($scope.inventories[i].total_hosts > 1) ? ' hosts' : ' host') + " with no job failures. Click to view details.";
$scope.inventories[i].failed_hosts_link = '/#/inventories/' + $scope.inventories[i].id + '/';
$scope.inventories[i].failed_hosts_class = 'false';
}
}
// Set values for Status column
scope.inventories[i].status = scope.inventories[i].inventory_sources_with_failures + ' / ' + scope.inventories[i].total_inventory_sources;
if (scope.inventories[i].inventory_sources_with_failures > 0) {
scope.inventories[i].status_tip = scope.inventories[i].inventory_sources_with_failures + ' cloud ' +
( (scope.inventories[i].inventory_sources_with_failures == 1) ? 'source' : 'sources' ) +
$scope.inventories[i].status = $scope.inventories[i].inventory_sources_with_failures + ' / ' + $scope.inventories[i].total_inventory_sources;
if ($scope.inventories[i].inventory_sources_with_failures > 0) {
$scope.inventories[i].status_tip = $scope.inventories[i].inventory_sources_with_failures + ' cloud ' +
(($scope.inventories[i].inventory_sources_with_failures === 1) ? 'source' : 'sources') +
' with failures. Click to view details.';
scope.inventories[i].status_link = '/#/inventories/' + scope.inventories[i].id + '/';
scope.inventories[i].status_class = 'failed';
}
else {
if (scope.inventories[i].total_inventory_sources == 0) {
$scope.inventories[i].status_link = '/#/inventories/' + $scope.inventories[i].id + '/';
$scope.inventories[i].status_class = 'failed';
} else {
if ($scope.inventories[i].total_inventory_sources === 0) {
// no groups are reporting a source
scope.inventories[i].status_tip = "Not synced with a cloud source. Click to edit.";
scope.inventories[i].status_link = '/#/inventories/' + scope.inventories[i].id + '/';
scope.inventories[i].status_class = 'na';
}
else {
$scope.inventories[i].status_tip = "Not synced with a cloud source. Click to edit.";
$scope.inventories[i].status_link = '/#/inventories/' + $scope.inventories[i].id + '/';
$scope.inventories[i].status_class = 'na';
} else {
// many hosts with 0 failures
scope.inventories[i].status_tip = scope.inventories[i].total_inventory_sources +
' cloud ' + ( (scope.inventories[i].total_inventory_sources > 1) ? 'sources' : 'source' ) +
$scope.inventories[i].status_tip = $scope.inventories[i].total_inventory_sources +
' cloud ' + (( $scope.inventories[i].total_inventory_sources > 1) ? 'sources' : 'source') +
' with no failures. Click to view details.';
scope.inventories[i].status_link = '/#/inventories/' + scope.inventories[i].id + '/';
scope.inventories[i].status_class = 'successful';
$scope.inventories[i].status_link = '/#/inventories/' + $scope.inventories[i].id + '/';
$scope.inventories[i].status_class = 'successful';
}
}
}
});
if (scope.removeRefreshInventories) {
scope.removeRefreshInventories();
if ($scope.removeRefreshInventories) {
$scope.removeRefreshInventories();
}
scope.removeRefreshInventories = scope.$on('RefreshInventories', function() {
$scope.removeRefreshInventories = $scope.$on('RefreshInventories', function () {
// Reflect changes after inventory properties edit completes
scope.search(list.iterator);
$scope.search(list.iterator);
});
scope.showActivity = function() { Stream({ scope: scope }); }
$scope.showActivity = function () {
Stream({ scope: $scope });
};
scope.editInventoryProperties = function(inventory_id) {
EditInventoryProperties({ scope: scope, inventory_id: inventory_id });
}
$scope.editInventoryProperties = function (inventory_id) {
EditInventoryProperties({ scope: $scope, inventory_id: inventory_id });
};
scope.addInventory = function() {
$scope.addInventory = function () {
$location.path($location.path() + '/add');
}
};
scope.editInventory = function(id) {
$scope.editInventory = function (id) {
$location.path($location.path() + '/' + id);
}
};
scope.deleteInventory = function(id, name) {
$scope.deleteInventory = function (id, name) {
var action = function() {
var action = function () {
var url = defaultUrl + id + '/';
$('#prompt-modal').on('hidden.bs.modal', function() {
$('#prompt-modal').on('hidden.bs.modal', function () {
Wait('start');
});
$('#prompt-modal').modal('hide');
Rest.setUrl(url);
Rest.destroy()
.success( function(data, status, headers, config) {
scope.search(list.iterator);
.success(function () {
$scope.search(list.iterator);
})
.error( function(data, status, headers, config) {
.error(function (data, status) {
Wait('stop');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status
});
});
};
Prompt({ hdr: 'Delete',
Prompt({
hdr: 'Delete',
body: 'Are you sure you want to delete ' + name + '?',
action: action
});
}
};
scope.lookupOrganization = function(organization_id) {
$scope.lookupOrganization = function (organization_id) {
Rest.setUrl(GetBasePath('organizations') + organization_id + '/');
Rest.get()
.success( function(data, status, headers, config) {
.success(function (data) {
return data.name;
});
}
};
// Failed jobs link. Go to the jobs tabs, find all jobs for the inventory and sort by status
scope.viewJobs = function(id) {
$scope.viewJobs = function (id) {
$location.url('/jobs/?inventory__int=' + id);
}
};
scope.viewFailedJobs = function(id) {
$scope.viewFailedJobs = function (id) {
$location.url('/jobs/?inventory__int=' + id + '&status=failed');
}
};
}
InventoriesList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'InventoryList', 'GenerateList',
InventoriesList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'InventoryList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
'GetBasePath', 'Wait', 'Stream', 'EditInventoryProperties'];
'GetBasePath', 'Wait', 'Stream', 'EditInventoryProperties'
];
function InventoriesAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
GenerateList, OrganizationList, SearchInit, PaginateInit, LookUpInit, GetBasePath,
ParseTypeChange, Wait)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
function InventoriesAdd($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm, GenerateForm, Rest,
Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateList, OrganizationList, SearchInit, PaginateInit,
LookUpInit, GetBasePath, ParseTypeChange, Wait) {
ClearScope();
// Inject dynamic view
var defaultUrl = GetBasePath('inventory');
var form = InventoryForm;
var generator = GenerateForm;
var defaultUrl = GetBasePath('inventory'),
form = InventoryForm,
generator = GenerateForm;
form.well = true,
form.well = true;
form.formLabelSize = null;
form.formFieldSize = null;
var scope = generator.inject(form, {mode: 'add', related: false});
scope.inventoryParseType = 'yaml';
generator.inject(form, { mode: 'add', related: false, scope: $scope });
generator.reset();
LoadBreadCrumbs();
ParseTypeChange(scope,'inventory_variables', 'inventoryParseType');
$scope.inventoryParseType = 'yaml';
ParseTypeChange({ scope: $scope, variable: 'inventory_variables', parse_variable: 'inventoryParseType',
field_id: 'inventory_inventory_variables' });
LookUpInit({
scope: scope,
scope: $scope,
form: form,
current_item: ($routeParams.organization_id) ? $routeParams.organization_id : null,
list: OrganizationList,
@@ -234,16 +252,17 @@ function InventoriesAdd ($scope, $rootScope, $compile, $location, $log, $routePa
});
// Save
scope.formSave = function() {
$scope.formSave = function () {
generator.clearApiErrors();
Wait('start');
try {
var fld, json_data, data;
// Make sure we have valid variable data
if (scope.inventoryParseType == 'json') {
var json_data = JSON.parse(scope.inventory_variables); //make sure JSON parses
}
else {
var json_data = jsyaml.load(scope.inventory_variables); //parse yaml
if ( $scope.inventoryParseType === 'json') {
json_data = JSON.parse( $scope.inventory_variables); //make sure JSON parses
} else {
json_data = jsyaml.load( $scope.inventory_variables); //parse yaml
}
// Make sure our JSON is actually an object
@@ -251,47 +270,43 @@ function InventoriesAdd ($scope, $rootScope, $compile, $location, $log, $routePa
throw "failed to return an object!";
}
var data = {}
for (var fld in form.fields) {
if (fld != 'inventory_variables') {
data = {};
for (fld in form.fields) {
if (fld !== 'inventory_variables') {
if (form.fields[fld].realName) {
data[form.fields[fld].realName] = scope[fld];
}
else {
data[fld] = scope[fld];
data[form.fields[fld].realName] = $scope[fld];
} else {
data[fld] = $scope[fld];
}
}
}
Rest.setUrl(defaultUrl);
Rest.post(data)
.success( function(data, status, headers, config) {
.success(function (data) {
var inventory_id = data.id;
if (scope.inventory_variables) {
if ($scope.inventory_variables) {
Rest.setUrl(data.related.variable_data);
Rest.put(json_data)
.success( function(data, status, headers, config) {
.success(function () {
Wait('stop');
$location.path('/inventories/' + inventory_id + '/');
})
.error( function(data, status, headers, config) {
Wait('stop');
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to add inventory varaibles. PUT returned status: ' + status });
.error(function (data, status) {
ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to add inventory varaibles. PUT returned status: ' + status
});
}
else {
});
} else {
Wait('stop');
$location.path('/inventories/' + inventory_id + '/');
}
})
.error( function(data, status, headers, config) {
Wait('stop');
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to add new inventory. Post returned status: ' + status });
.error(function (data, status) {
ProcessErrors( $scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to add new inventory. Post returned status: ' + status });
});
}
catch(err) {
} catch (err) {
Wait('stop');
Alert("Error", "Error parsing inventory variables. Parser returned: " + err);
}
@@ -299,49 +314,54 @@ function InventoriesAdd ($scope, $rootScope, $compile, $location, $log, $routePa
};
// Reset
scope.formReset = function() {
// Defaults
$scope.formReset = function () {
generator.reset();
};
}
InventoriesAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList',
'OrganizationList', 'SearchInit', 'PaginateInit', 'LookUpInit', 'GetBasePath', 'ParseTypeChange', 'Wait'
];
InventoriesAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList', 'OrganizationList', 'SearchInit',
'PaginateInit', 'LookUpInit', 'GetBasePath', 'ParseTypeChange', 'Wait'
];
function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateList, ClearScope, InventoryGroups, InventoryHosts, BuildTree, Wait,
GetSyncStatusMsg, InjectHosts, HostsReload, GroupsAdd, GroupsEdit, GroupsDelete, Breadcrumbs, LoadBreadCrumbs, Empty,
Rest, ProcessErrors, InventoryUpdate, Alert, ToggleChildren, ViewUpdateStatus, GroupsCancelUpdate, Find,
HostsCreate, EditInventoryProperties, HostsEdit, HostsDelete, ToggleHostEnabled, CopyMoveGroup, CopyMoveHost,
Stream, GetBasePath, ShowJobSummary, ApplyEllipsis, WatchInventoryWindowResize, HelpDialog, InventoryGroupsHelp,
Store)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
function InventoriesEdit($scope, $location, $routeParams, $compile, GenerateList, ClearScope, InventoryGroups, InventoryHosts, BuildTree, Wait,
GetSyncStatusMsg, InjectHosts, HostsReload, GroupsAdd, GroupsEdit, GroupsDelete, Breadcrumbs, LoadBreadCrumbs, Empty, Rest, ProcessErrors,
InventoryUpdate, Alert, ToggleChildren, ViewUpdateStatus, GroupsCancelUpdate, Find, HostsCreate, EditInventoryProperties, HostsEdit,
HostsDelete, ToggleHostEnabled, CopyMoveGroup, CopyMoveHost, Stream, GetBasePath, ShowJobSummary, ApplyEllipsis, WatchInventoryWindowResize,
HelpDialog, InventoryGroupsHelp, Store) {
var generator = GenerateList;
var list = InventoryGroups;
var base = $location.path().replace(/^\//,'').split('/')[0];
ClearScope();
var generator = GenerateList,
list = InventoryGroups;
$scope.inventory_id = $routeParams.inventory_id;
LoadBreadCrumbs({ path: $location.path(), title: '{{ inventory_name }}' });
LoadBreadCrumbs({
path: $location.path(),
title: '{{ inventory_name }}'
});
// After the tree data loads for the first time, generate the groups and hosts lists
if ($scope.removeGroupTreeLoaded) {
$scope.removeGroupTreeLoaded();
}
$scope.removeGroupTreeLoaded = $scope.$on('GroupTreeLoaded', function(e, inventory_name, groups) {
$scope.removeGroupTreeLoaded = $scope.$on('GroupTreeLoaded', function (event, inventory_name, groups) {
// Add breadcrumbs
var e = angular.element(document.getElementById('breadcrumbs'));
var e, inventoryAutoHelp;
e = angular.element(document.getElementById('breadcrumbs'));
e.html(Breadcrumbs({ list: list, mode: 'edit' }));
$compile(e)($scope);
// Add groups view
generator.inject(list, { mode: 'edit', id: 'groups-container', breadCrumbs: false, searchSize: 'col-lg-5 col-md-5 col-sm-5' });
generator.inject(list, {
mode: 'edit',
id: 'groups-container',
breadCrumbs: false,
searchSize: 'col-lg-5 col-md-5 col-sm-5'
});
$scope.groups = groups;
$scope.inventory_name = inventory_name;
@@ -352,35 +372,44 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis
$scope.groups[0].selected_class = 'selected';
$scope.groups[0].active_class = 'active-row';
$scope.selected_group_name = $scope.groups[0].name;
}
else {
} else {
$scope.selected_tree_id = null;
$scope.selected_group_id = null;
}
// Add hosts view
$scope.show_failures = false;
InjectHosts({ scope: $scope, inventory_id: $scope.inventory_id, tree_id: $scope.selected_tree_id, group_id: $scope.selected_group_id });
InjectHosts({
scope: $scope,
inventory_id: $scope.inventory_id,
tree_id: $scope.selected_tree_id,
group_id: $scope.selected_group_id
});
// As the window shrinks and expands, apply ellipsis
setTimeout(function() {
setTimeout(function () {
// Hack to keep group name from slipping to a new line
$('#groups_table .name-column').each( function() {
var td_width = $(this).width();
var level_width = $(this).find('.level').width();
var level_padding = parseInt($(this).find('.level').css('padding-left').replace(/px/,''));
var level = level_width + level_padding;
var pct = ( 100 - Math.ceil((level / td_width)*100) ) + '%';
$(this).find('.group-name').css({ width: pct });
$('#groups_table .name-column').each(function () {
var td_width, level_width, level_padding, level, pct;
td_width = $(this).width();
level_width = $(this).find('.level').width();
level_padding = parseInt($(this).find('.level').css('padding-left').replace(/px/, ''));
level = level_width + level_padding;
pct = (100 - Math.ceil((level / td_width) * 100)) + '%';
$(this).find('.group-name').css({
width: pct
});
});
ApplyEllipsis('#groups_table .group-name a');
ApplyEllipsis('#hosts_table .host-name a');
}, 2500); //give the window time to display
WatchInventoryWindowResize();
var inventoryAutoHelp = Store('inventoryAutoHelp');
inventoryAutoHelp = Store('inventoryAutoHelp');
if (inventoryAutoHelp !== 'off' && $scope.autoShowGroupHelp) {
$scope.showGroupHelp({ autoShow: true });
$scope.showGroupHelp({
autoShow: true
});
}
});
@@ -390,9 +419,11 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis
if ($scope.removeGroupTreeRefreshed) {
$scope.removeGroupTreeRefreshed();
}
$scope.removeGroupTreeRefreshed = $scope.$on('GroupTreeRefreshed', function(e, inventory_name, groups) {
$scope.removeGroupTreeRefreshed = $scope.$on('GroupTreeRefreshed', function () {
// Reapply ellipsis to groups
setTimeout(function() { ApplyEllipsis('#groups_table .group-name a'); }, 2500);
setTimeout(function () {
ApplyEllipsis('#groups_table .group-name a');
}, 2500);
// Reselect the preveiously selected group node, causing host view to refresh.
$scope.showHosts($scope.selected_tree_id, $scope.selected_group_id, false);
});
@@ -401,29 +432,41 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis
if ($scope.removeGroupDeleteCompleted) {
$scope.removeGroupDeleteCompleted();
}
$scope.removeGroupDeleteCompleted = $scope.$on('GroupDeleteCompleted', function(e) {
$scope.removeGroupDeleteCompleted = $scope.$on('GroupDeleteCompleted', function () {
$scope.selected_tree_id = 1;
$scope.selected_group_id = null;
BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: true });
BuildTree({
scope: $scope,
inventory_id: $scope.inventory_id,
refresh: true
});
});
// Respond to a group drag-n-drop
if ($scope.removeCopMoveGroup) {
$scope.removeCopyMoveGroup();
}
$scope.removeCopyMoveGroup = $scope.$on('CopyMoveGroup', function(e, inbound_tree_id, target_tree_id) {
CopyMoveGroup({ scope: $scope, target_tree_id: target_tree_id, inbound_tree_id: inbound_tree_id });
$scope.removeCopyMoveGroup = $scope.$on('CopyMoveGroup', function (e, inbound_tree_id, target_tree_id) {
CopyMoveGroup({
scope: $scope,
target_tree_id: target_tree_id,
inbound_tree_id: inbound_tree_id
});
});
// Respond to a host drag-n-drop
if ($scope.removeCopMoveHost) {
$scope.removeCopyMoveHost();
}
$scope.removeCopyMoveHost = $scope.$on('CopyMoveHost', function(e, target_tree_id, host_id) {
CopyMoveHost({ scope: $scope, target_tree_id: target_tree_id, host_id: host_id });
$scope.removeCopyMoveHost = $scope.$on('CopyMoveHost', function (e, target_tree_id, host_id) {
CopyMoveHost({
scope: $scope,
target_tree_id: target_tree_id,
host_id: host_id
});
});
$scope.showHosts = function(tree_id, group_id, show_failures) {
$scope.showHosts = function (tree_id, group_id, show_failures) {
// Clicked on group
if (tree_id !== null) {
Wait('start');
@@ -431,48 +474,59 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis
$scope.selected_group_id = group_id;
$scope.hosts = [];
$scope.show_failures = show_failures; // turn on failed hosts filter in hosts view
for (var i=0; i < $scope.groups.length; i++) {
if ($scope.groups[i].id == tree_id) {
for (var i = 0; i < $scope.groups.length; i++) {
if ($scope.groups[i].id === tree_id) {
$scope.groups[i].selected_class = 'selected';
$scope.groups[i].active_class = 'active-row';
$scope.selected_group_name = $scope.groups[i].name;
}
else {
} else {
$scope.groups[i].selected_class = '';
$scope.groups[i].active_class = '';
}
}
HostsReload({ scope: $scope, group_id: group_id, tree_id: tree_id, inventory_id: $scope.inventory_id });
}
else {
HostsReload({
scope: $scope,
group_id: group_id,
tree_id: tree_id,
inventory_id: $scope.inventory_id
});
} else {
Wait('stop');
}
}
};
$scope.createGroup = function() {
GroupsAdd({ scope: $scope, inventory_id: $scope.inventory_id, group_id: $scope.selected_group_id });
}
$scope.createGroup = function () {
GroupsAdd({
scope: $scope,
inventory_id: $scope.inventory_id,
group_id: $scope.selected_group_id
});
};
$scope.editGroup = function(group_id, tree_id) {
GroupsEdit({ scope: $scope, inventory_id: $scope.inventory_id, group_id: group_id, tree_id: tree_id, groups_reload: true });
}
$scope.editGroup = function (group_id, tree_id) {
GroupsEdit({
scope: $scope,
inventory_id: $scope.inventory_id,
group_id: group_id,
tree_id: tree_id,
groups_reload: true
});
};
// Launch inventory sync
$scope.updateGroup = function(id) {
var group = Find({ list: $scope.groups, key: 'id', val: id});
$scope.updateGroup = function (id) {
var group = Find({ list: $scope.groups, key: 'id', val: id });
if (group) {
if (Empty(group.source)) {
// if no source, do nothing.
}
else if (group.status == 'updating') {
} else if (group.status === 'updating') {
Alert('Update in Progress', 'The inventory update process is currently running for group <em>' +
$scope.groups[i].name + '</em>. Use the Refresh button to monitor the status.', 'alert-info');
}
else {
group.name + '</em>. Use the Refresh button to monitor the status.', 'alert-info');
} else {
Wait('start');
Rest.setUrl(group.related.inventory_source);
Rest.get()
.success( function(data, status, headers, config) {
.success(function (data) {
InventoryUpdate({
scope: $scope,
url: data.related.update,
@@ -482,105 +536,132 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis
group_id: group.group_id
});
})
.error( function(data, status, headers, config) {
.error(function (data, status) {
Wait('stop');
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve inventory source: ' + group.related.inventory_source +
' POST returned status: ' + status });
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve inventory source: ' +
group.related.inventory_source + ' POST returned status: ' + status });
});
}
}
}
};
$scope.cancelUpdate = function(tree_id) {
$scope.cancelUpdate = function (tree_id) {
GroupsCancelUpdate({ scope: $scope, tree_id: tree_id });
}
};
$scope.toggle = function(tree_id) {
$scope.toggle = function (tree_id) {
// Expand/collapse nodes
ToggleChildren({ scope: $scope, list: list, id: tree_id });
}
};
$scope.refreshGroups = function(tree_id, group_id) {
$scope.refreshGroups = function (tree_id, group_id) {
// Refresh the tree data when refresh button cicked
if (tree_id) {
$scope.selected_tree_id = tree_id;
$scope.selected_group_id = group_id;
}
BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: true });
}
};
$scope.viewUpdateStatus = function(tree_id, group_id) {
ViewUpdateStatus({ scope: $scope, tree_id: tree_id, group_id: group_id });
}
$scope.viewUpdateStatus = function (tree_id, group_id) {
ViewUpdateStatus({
scope: $scope,
tree_id: tree_id,
group_id: group_id
});
};
$scope.deleteGroup = function(tree_id, group_id) {
GroupsDelete({ scope: $scope, tree_id: tree_id, group_id: group_id, inventory_id: $scope.inventory_id });
}
$scope.deleteGroup = function (tree_id, group_id) {
GroupsDelete({
scope: $scope,
tree_id: tree_id,
group_id: group_id,
inventory_id: $scope.inventory_id
});
};
$scope.createHost = function() {
$scope.createHost = function () {
HostsCreate({ scope: $scope });
}
};
$scope.editInventoryProperties = function() {
$scope.editInventoryProperties = function () {
EditInventoryProperties({ scope: $scope, inventory_id: $scope.inventory_id });
}
};
$scope.editHost = function(host_id) {
$scope.editHost = function (host_id) {
HostsEdit({ scope: $scope, host_id: host_id, inventory_id: $scope.inventory_id });
}
};
$scope.deleteHost = function(host_id, host_name) {
$scope.deleteHost = function (host_id, host_name) {
HostsDelete({ scope: $scope, host_id: host_id, host_name: host_name });
}
};
$scope.toggleHostEnabled = function(host_id, external_source) {
$scope.toggleHostEnabled = function (host_id, external_source) {
ToggleHostEnabled({ scope: $scope, host_id: host_id, external_source: external_source });
}
};
$scope.showGroupActivity = function() {
$scope.showGroupActivity = function () {
var url, title, group;
if ($scope.selected_group_id) {
group = Find({ list: $scope.groups, key: 'id', val: $scope.selected_tree_id });
group = Find({
list: $scope.groups,
key: 'id',
val: $scope.selected_tree_id
});
url = GetBasePath('activity_stream') + '?group__id=' + $scope.selected_group_id;
title = 'Showing all activities for group ' + group.name;
}
else {
} else {
title = 'Showing all activities for all ' + $scope.inventory_name + ' groups';
url = GetBasePath('activity_stream') + '?group__inventory__id=' + $scope.inventory_id;
}
Stream({ scope: $scope, inventory_name: $scope.inventory_name, url: url, title: title });
}
Stream({
scope: $scope,
inventory_name: $scope.inventory_name,
url: url,
title: title
});
};
$scope.showHostActivity = function() {
$scope.showHostActivity = function () {
var url, title;
title = 'Showing all activities for all ' + $scope.inventory_name + ' hosts';
url = GetBasePath('activity_stream') + '?host__inventory__id=' + $scope.inventory_id;
Stream({ scope: $scope, inventory_name: $scope.inventory_name, url: url, title: title });
}
Stream({
scope: $scope,
inventory_name: $scope.inventory_name,
url: url,
title: title
});
};
$scope.showJobSummary = function(job_id) {
ShowJobSummary({ job_id: job_id });
}
$scope.showJobSummary = function (job_id) {
ShowJobSummary({
job_id: job_id
});
};
$scope.showGroupHelp = function(params) {
var opts = { defn: InventoryGroupsHelp };
$scope.showGroupHelp = function (params) {
var opts = {
defn: InventoryGroupsHelp
};
if (params) {
opts.autoShow = params.autoShow || false;
}
HelpDialog(opts);
}
};
//Load tree data for the first time
BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: false });
BuildTree({
scope: $scope,
inventory_id: $scope.inventory_id,
refresh: false
});
}
InventoriesEdit.$inject = [ '$scope', '$location', '$routeParams', '$compile', 'GenerateList', 'ClearScope', 'InventoryGroups', 'InventoryHosts',
'BuildTree', 'Wait', 'GetSyncStatusMsg', 'InjectHosts', 'HostsReload', 'GroupsAdd', 'GroupsEdit', 'GroupsDelete',
'Breadcrumbs', 'LoadBreadCrumbs', 'Empty', 'Rest', 'ProcessErrors', 'InventoryUpdate', 'Alert', 'ToggleChildren',
'ViewUpdateStatus', 'GroupsCancelUpdate', 'Find', 'HostsCreate', 'EditInventoryProperties', 'HostsEdit',
'HostsDelete', 'ToggleHostEnabled', 'CopyMoveGroup', 'CopyMoveHost', 'Stream', 'GetBasePath', 'ShowJobSummary',
'ApplyEllipsis', 'WatchInventoryWindowResize', 'HelpDialog', 'InventoryGroupsHelp', 'Store'
];
}
InventoriesEdit.$inject = ['$scope', '$location', '$routeParams', '$compile', 'GenerateList', 'ClearScope', 'InventoryGroups', 'InventoryHosts',
'BuildTree', 'Wait', 'GetSyncStatusMsg', 'InjectHosts', 'HostsReload', 'GroupsAdd', 'GroupsEdit', 'GroupsDelete', 'Breadcrumbs',
'LoadBreadCrumbs', 'Empty', 'Rest', 'ProcessErrors', 'InventoryUpdate', 'Alert', 'ToggleChildren', 'ViewUpdateStatus', 'GroupsCancelUpdate',
'Find', 'HostsCreate', 'EditInventoryProperties', 'HostsEdit', 'HostsDelete', 'ToggleHostEnabled', 'CopyMoveGroup', 'CopyMoveHost',
'Stream', 'GetBasePath', 'ShowJobSummary', 'ApplyEllipsis', 'WatchInventoryWindowResize', 'HelpDialog', 'InventoryGroupsHelp', 'Store'
];

View File

@@ -10,49 +10,50 @@
'use strict';
function JobEventsList ($filter, $scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobEventList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
ClearScope, ProcessErrors, GetBasePath, LookUpInit, ToggleChildren,
FormatDate, EventView, Refresh, Wait)
{
ClearScope('htmlTemplate');
var list = JobEventList;
function JobEventsList($filter, $scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobEventList, GenerateList,
LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, LookUpInit, ToggleChildren,
FormatDate, EventView, Refresh, Wait) {
ClearScope();
var list = JobEventList,
defaultUrl = GetBasePath('jobs') + $routeParams.id + '/job_events/', //?parent__isnull=1';
generator = GenerateList,
page;
generator.inject(list, { mode: 'edit', scope: $scope });
list.base = $location.path();
var defaultUrl = GetBasePath('jobs') + $routeParams.id + '/job_events/'; //?parent__isnull=1';
var view = GenerateList;
var base = $location.path().replace(/^\//,'').split('/')[0];
var scope = view.inject(list, { mode: 'edit' });
scope.job_id = $routeParams.id;
$scope.job_id = $routeParams.id;
$rootScope.flashMessage = null;
scope.selected = [];
scope.expand = true; //on load, automatically expand all nodes
$scope.selected = [];
$scope.expand = true; //on load, automatically expand all nodes
scope.parentNode = 'parent-event'; // used in ngClass to dynamically set row level class and control
scope.childNode = 'child-event'; // link color and cursor
$scope.parentNode = 'parent-event'; // used in ngClass to dynamically set row level class and control
$scope.childNode = 'child-event'; // link color and cursor
if (scope.removeSetHostLinks) {
scope.removeSetHostLinks();
if ($scope.removeSetHostLinks) {
$scope.removeSetHostLinks();
}
scope.removeSetHostLinks = scope.$on('SetHostLinks', function(e, inventory_id) {
for (var i=0; i < scope.jobevents.length; i++) {
if (scope.jobevents[i].summary_fields.host) {
scope.jobevents[i].hostLink = "/#/inventories/" + inventory_id + "/hosts/?name=" +
escape(scope.jobevents[i].summary_fields.host.name);
$scope.removeSetHostLinks = $scope.$on('SetHostLinks', function (e, inventory_id) {
for (var i = 0; i < $scope.jobevents.length; i++) {
if ($scope.jobevents[i].summary_fields.host) {
$scope.jobevents[i].hostLink = "/#/inventories/" + inventory_id + "/hosts/?name=" +
encodeURI($scope.jobevents[i].summary_fields.host.name);
}
}
});
function formatJSON(eventData) {
//turn JSON event data into an html form
var html = '';
if (eventData['res']) {
var n, rows;
var found = false;
if (typeof eventData.res == 'string') {
n = eventData['res'].match(/\n/g);
var i, n, rows, fld, txt,
html = '',
found = false;
if (eventData.res) {
if (typeof eventData.res === 'string') {
n = eventData.res.match(/\n/g);
rows = (n) ? n.length : 1;
rows = (rows > 10) ? 10 : rows;
found = true;
@@ -60,14 +61,13 @@ function JobEventsList ($filter, $scope, $rootScope, $location, $log, $routePara
html += "<label>Traceback:</label>\n";
html += "<textarea readonly class=\"form-control nowrap\" rows=\"" + rows + "\">" + eventData.res + "</textarea>\n";
html += "</div>\n";
}
else {
for (var fld in eventData.res) {
if ( (fld == 'msg' || fld == 'stdout' || fld == 'stderr') &&
(eventData.res[fld] !== null && eventData.res[fld] !== '') ) {
} else {
for (fld in eventData.res) {
if ((fld === 'msg' || fld === 'stdout' || fld === 'stderr') &&
(eventData.res[fld] !== null && eventData.res[fld] !== '')) {
html += "<div class=\"form-group\">\n";
html += "<label>";
switch(fld) {
switch (fld) {
case 'msg':
case 'stdout':
html += 'Output:';
@@ -77,17 +77,17 @@ function JobEventsList ($filter, $scope, $rootScope, $location, $log, $routePara
break;
}
html += "</label>\n";
n = eventData['res'][fld].match(/\n/g);
n = eventData.res[fld].match(/\n/g);
rows = (n) ? n.length : 1;
rows = (rows > 10) ? 10 : rows;
html += "<textarea readonly class=\"form-control nowrap\" rows=\"" + rows + "\">" + eventData.res[fld] + "</textarea>\n";
html += "</div>\n";
found = true;
}
if ( fld == "results" && Array.isArray(eventData.res[fld]) && eventData.res[fld].length > 0 ) {
if (fld === "results" && Array.isArray(eventData.res[fld]) && eventData.res[fld].length > 0) {
//html += "<textarea readonly class="
var txt = '';
for (var i=0; i < eventData.res[fld].length; i++) {
txt = '';
for (i = 0; i < eventData.res[fld].length; i++) {
txt += eventData.res[fld][i];
}
n = txt.match(/\n/g);
@@ -101,7 +101,7 @@ function JobEventsList ($filter, $scope, $rootScope, $location, $log, $routePara
found = true;
}
}
if (fld == "rc" && eventData.res[fld] != '') {
if (fld === "rc" && eventData.res[fld] !== '') {
html += "<div class=\"form-group\">\n";
html += "<label>Return Code:</label>\n";
html += "<input type=\"text\" class=\"form-control nowrap mono-space\" value=\"" + eventData.res[fld] + "\" readonly >\n";
@@ -112,70 +112,58 @@ function JobEventsList ($filter, $scope, $rootScope, $location, $log, $routePara
}
html = (found) ? "<form class=\"event-form\">\n" + html + "</form>\n" : '';
}
if (eventData['host']) {
html = "<span class=\"event-detail-host visible-sm\">" + eventData['host'] + "</span>\n" + html;
}
else {
html = (html == '' ) ? null : html;
if (eventData.hosts) {
html = "<span class=\"event-detail-host visible-sm\">" + eventData.host + "</span>\n" + html;
} else {
html = (html === '') ? null : html;
}
return html;
}
if (scope.removePostRefresh) {
scope.removePostRefresh();
if ($scope.removePostRefresh) {
$scope.removePostRefresh();
}
scope.removePostRefresh = scope.$on('PostRefresh', function() {
$scope.removePostRefresh = $scope.$on('PostRefresh', function () {
// Initialize the parent levels
var set = scope[list.name];
var cDate;
for (var i=0; i < set.length; i++) {
set[i].event_display = set[i].event_display.replace(/^\u00a0*/g,'');
if (set[i].event_level < 3 ) {
set[i]['ngclick'] = "toggleChildren(" + set[i].id + ", \"" + set[i].related.children + "\")";
set[i]['ngicon'] = 'fa fa-minus-square-o node-toggle';
var set = $scope[list.name], i;
for (i = 0; i < set.length; i++) {
set[i].event_display = set[i].event_display.replace(/^\u00a0*/g, '');
if (set[i].event_level < 3) {
set[i].ngicon = 'fa fa-minus-square-o node-toggle';
set[i]['class'] = 'parentNode';
}
else {
set[i]['ngicon'] = 'fa fa-square-o node-no-toggle';
} else {
set[i].ngicon = 'fa fa-square-o node-no-toggle';
set[i]['class'] = 'childNode';
set[i]['event_detail'] = formatJSON(set[i].event_data);
set[i].event_detail = formatJSON(set[i].event_data);
}
set[i]['show'] = true;
set[i]['spaces'] = set[i].event_level * 24;
if (scope.jobevents[i].failed) {
scope.jobevents[i].status = 'error';
if (i == set.length - 1) {
scope.jobevents[i].statusBadgeToolTip = "A failure occurred durring one or more playbook tasks.";
set[i].show = true;
set[i].spaces = set[i].event_level * 24;
if ($scope.jobevents[i].failed) {
$scope.jobevents[i].status = 'error';
if (i === set.length - 1) {
$scope.jobevents[i].statusBadgeToolTip = "A failure occurred durring one or more playbook tasks.";
} else if (set[i].event_level < 3) {
$scope.jobevents[i].statusBadgeToolTip = "A failure occurred within the children of this event.";
} else {
$scope.jobevents[i].statusBadgeToolTip = "A failure occurred. Click to view details";
}
else if (set[i].event_level < 3) {
scope.jobevents[i].statusBadgeToolTip = "A failure occurred within the children of this event.";
} else if ($scope.jobevents[i].changed) {
$scope.jobevents[i].status = 'changed';
if (i === set.length - 1) {
$scope.jobevents[i].statusBadgeToolTip = "A change was completed durring one or more playbook tasks.";
} else if (set[i].event_level < 3) {
$scope.jobevents[i].statusBadgeToolTip = "A change was completed by one or more children of this event.";
} else {
$scope.jobevents[i].statusBadgeToolTip = "A change was completed. Click to view details";
}
else {
scope.jobevents[i].statusBadgeToolTip = "A failure occurred. Click to view details";
}
}
else if (scope.jobevents[i].changed) {
scope.jobevents[i].status = 'changed';
if (i == set.length - 1) {
scope.jobevents[i].statusBadgeToolTip = "A change was completed durring one or more playbook tasks.";
}
else if (set[i].event_level < 3) {
scope.jobevents[i].statusBadgeToolTip = "A change was completed by one or more children of this event.";
}
else {
scope.jobevents[i].statusBadgeToolTip = "A change was completed. Click to view details";
}
}
else {
scope.jobevents[i].status = 'success';
if (i == set.length - 1) {
scope.jobevents[i].statusBadgeToolTip = "All playbook tasks completed successfully.";
}
else if (set[i].event_level < 3) {
scope.jobevents[i].statusBadgeToolTip = "All the children of this event completed successfully.";
}
else {
scope.jobevents[i].statusBadgeToolTip = "No errors occurred. Click to view details";
} else {
$scope.jobevents[i].status = 'success';
if (i === set.length - 1) {
$scope.jobevents[i].statusBadgeToolTip = "All playbook tasks completed successfully.";
} else if (set[i].event_level < 3) {
$scope.jobevents[i].statusBadgeToolTip = "All the children of this event completed successfully.";
} else {
$scope.jobevents[i].statusBadgeToolTip = "No errors occurred. Click to view details";
}
}
//cDate = new Date(set[i].created);
@@ -185,115 +173,130 @@ function JobEventsList ($filter, $scope, $rootScope, $location, $log, $routePara
// Need below lookup to get inventory_id, which is not on event record. Plus, good idea to get status and name
// from job in the event that there are no job event records
Rest.setUrl(GetBasePath('jobs') + scope.job_id);
Rest.setUrl(GetBasePath('jobs') + $scope.job_id);
Rest.get()
.success( function(data, status, headers, config) {
scope.job_status = data.status;
scope.job_name = data.summary_fields.job_template.name;
LoadBreadCrumbs({ path: '/jobs/' + scope.job_id, title: scope.job_id + ' - ' + data.summary_fields.job_template.name });
scope.$emit('SetHostLinks', data.inventory);
.success(function (data) {
$scope.job_status = data.status;
$scope.job_name = data.summary_fields.job_template.name;
LoadBreadCrumbs({
path: '/jobs/' + $scope.job_id,
title: $scope.job_id + ' - ' + data.summary_fields.job_template.name
});
$scope.$emit('SetHostLinks', data.inventory);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get job status for job: ' + scope.job_id + '. GET status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to get job status for job: ' + $scope.job_id + '. GET status: ' + status
});
});
});
SearchInit({ scope: scope, set: 'jobevents', list: list, url: defaultUrl });
SearchInit({
scope: $scope,
set: 'jobevents',
list: list,
url: defaultUrl
});
var page = ($routeParams.page) ? parseInt($routeParams.page) - 1 : null;
PaginateInit({ scope: scope, list: list, url: defaultUrl, page: page });
page = ($routeParams.page) ? parseInt($routeParams.page,10) - 1 : null;
PaginateInit({
scope: $scope,
list: list,
url: defaultUrl,
page: page
});
// Called from Inventories tab, host failed events link:
if ($routeParams.host) {
scope[list.iterator + 'SearchField'] = 'host';
scope[list.iterator + 'SearchValue'] = $routeParams.host;
scope[list.iterator + 'SearchFieldLabel'] = list.fields['host'].label;
$scope[list.iterator + 'SearchField'] = 'host';
$scope[list.iterator + 'SearchValue'] = $routeParams.host;
$scope[list.iterator + 'SearchFieldLabel'] = list.fields.host.label;
}
scope.search(list.iterator, $routeParams.page);
$scope.search(list.iterator, $routeParams.page);
scope.toggleChildren = function(id, children) {
$scope.toggle = function (id) {
ToggleChildren({
scope: scope,
scope: $scope,
list: list,
id: id,
children: children
id: id
});
}
};
scope.viewJobEvent = function(id) {
EventView({ event_id: id });
}
$scope.viewJobEvent = function (id) {
EventView({
event_id: id
});
};
scope.refresh = function() {
scope['jobSearchSpin'] = true;
scope['jobLoading'] = true;
$scope.refresh = function () {
$scope.jobSearchSpin = true;
$scope.jobLoading = true;
Wait('start');
Refresh({ scope: scope, set: 'jobevents', iterator: 'jobevent', url: scope['current_url'] });
}
Refresh({
scope: $scope,
set: 'jobevents',
iterator: 'jobevent',
url: $scope.current_url
});
};
}
JobEventsList.$inject = [ '$filter', '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobEventList',
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
'ProcessErrors','GetBasePath', 'LookUpInit', 'ToggleChildren', 'FormatDate', 'EventView', 'Refresh', 'Wait'
];
JobEventsList.$inject = ['$filter', '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobEventList',
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
'GetBasePath', 'LookUpInit', 'ToggleChildren', 'FormatDate', 'EventView', 'Refresh', 'Wait'
];
function JobEventsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, JobEventForm, GenerateForm,
Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, FormatDate, EventView,
Wait)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
// Inject dynamic view
var form = JobEventForm;
var generator = GenerateForm;
var scope = GenerateForm.inject(form, {mode: 'edit', related: true});
function JobEventsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobEventsForm, GenerateForm,
Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath, FormatDate, EventView, Wait) {
ClearScope();
var form = JobEventsForm,
generator = GenerateForm,
defaultUrl = GetBasePath('base') + 'job_events/' + $routeParams.event_id + '/';
generator.inject(form, { mode: 'edit', related: true, scope: $scope});
generator.reset();
var defaultUrl = GetBasePath('base') + 'job_events/' + $routeParams.event_id + '/';
var base = $location.path().replace(/^\//,'').split('/')[0];
// Retrieve detail record and prepopulate the form
Wait('start');
Rest.setUrl(defaultUrl);
Rest.get()
.success( function(data, status, headers, config) {
scope['event_display'] = data['event_display'].replace(/^\u00a0*/g,'');
LoadBreadCrumbs({ path: '/jobs/' + $routeParams.job_id + '/job_events/' + $routeParams.event_id,
title: scope['event_display'] });
for (var fld in form.fields) {
switch(fld) {
.success(function (data) {
var cDate, fld, n, rows;
$scope.event_display = data.event_display.replace(/^\u00a0*/g, '');
LoadBreadCrumbs({ path: '/jobs/' + $routeParams.job_id + '/job_events/' + $routeParams.event_id, title: $scope.event_display });
for (fld in form.fields) {
switch (fld) {
case 'status':
if (data['failed']) {
scope['status'] = 'error';
}
else if (data['changed']) {
scope['status'] = 'changed';
}
else {
scope['status'] = 'success';
if (data.failed) {
$scope.status = 'error';
} else if (data.changed) {
$scope.status = 'changed';
} else {
$scope.status = 'success';
}
break;
case 'created':
var cDate = new Date(data['created']);
scope['created'] = FormatDate(cDate);
cDate = new Date(data.created);
$scope.created = FormatDate(cDate);
break;
case 'host':
if (data['summary_fields'] && data['summary_fields']['host']) {
scope['host'] = data['summary_fields']['host']['name'];
if (data.summary_fields && data.summary_fields.host) {
$scope.host = data.summary_fields.host.name;
}
break;
case 'id':
case 'task':
case 'play':
scope[fld] = data[fld];
$scope[fld] = data[fld];
break;
case 'start':
case 'end':
if (data['event_data'] && data['event_data']['res'] && data['event_data']['res'][fld] !== undefined) {
var cDate = new Date(data['event_data']['res'][fld]);
scope[fld] = FormatDate(cDate);
if (data.event_data && data.event_data.res && data.event_data.res[fld] !== undefined) {
cDate = new Date(data.event_data.res[fld]);
$scope[fld] = FormatDate(cDate);
}
break;
case 'msg':
@@ -301,46 +304,47 @@ function JobEventsEdit ($scope, $rootScope, $compile, $location, $log, $routePar
case 'stderr':
case 'delta':
case 'rc':
if (data['event_data'] && data['event_data']['res'] && data['event_data']['res'][fld] !== undefined) {
scope[fld] = data['event_data']['res'][fld];
if (form.fields[fld].type == 'textarea') {
var n = data['event_data']['res'][fld].match(/\n/g);
var rows = (n) ? n.length : 1;
if (data.event_data && data.event_data.res && data.event_data.res[fld] !== undefined) {
$scope[fld] = data.event_data.res[fld];
if (form.fields[fld].type === 'textarea') {
n = data.event_data.res[fld].match(/\n/g);
rows = (n) ? n.length : 1;
rows = (rows > 15) ? 5 : rows;
$('textarea[name="' + fld + '"]').attr('rows',rows);
$('textarea[name="' + fld + '"]').attr('rows', rows);
}
}
break;
case 'module_name':
case 'module_args':
if (data['event_data']['res'] && data['event_data']['res']['invocation']) {
scope[fld] = data['event_data']['res']['invocation'][fld];
if (data.event_data.res && data.event_data.res.invocation) {
$scope[fld] = data.event_data.res.invocation.fld;
}
break;
}
}
Wait('stop');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to retrieve host: ' + $routeParams.event_id + '. GET status: ' + status });
.error(function (data) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve host: ' + $routeParams.event_id +
'. GET status: ' + status });
});
scope.navigateBack = function() {
$scope.navigateBack = function () {
var url = '/jobs/' + $routeParams.job_id + '/job_events';
if ($routeParams.page) {
url += '?page=' + $routeParams.page;
}
$location.url(url);
}
};
scope.rawView = function() {
EventView({"event_id": scope.id });
}
$scope.rawView = function () {
EventView({
"event_id": $scope.id
});
};
}
JobEventsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobEventForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath',
'FormatDate', 'EventView', 'Wait'
];
JobEventsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobEventsForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', 'FormatDate', 'EventView', 'Wait'
];

View File

@@ -10,138 +10,158 @@
'use strict';
function JobHostSummaryList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobHostList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
ClearScope, ProcessErrors, GetBasePath, Refresh, JobStatusToolTip, Wait)
{
ClearScope('htmlTemplate');
var list = JobHostList;
var base = $location.path().replace(/^\//,'').split('/')[0];
var defaultUrl = GetBasePath(base) + $routeParams.id + '/job_host_summaries/';
var inventory_id;
function JobHostSummaryList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobHostList, GenerateList,
LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, Refresh,
JobStatusToolTip, Wait) {
ClearScope();
var list = JobHostList,
base = $location.path().replace(/^\//, '').split('/')[0],
defaultUrl = GetBasePath(base) + $routeParams.id + '/job_host_summaries/',
view = GenerateList,
scope = view.inject(list, { mode: 'edit' });
// When viewing all summaries for a particular host, show job ID, otherwise row ID.
if (base == 'hosts') {
if (base === 'hosts') {
list.index = false;
}
else {
} else {
list.index = true;
}
var view = GenerateList;
var scope = view.inject(list, { mode: 'edit' });
scope.selected = [];
$scope.selected = [];
// control enable/disable/show of job specific view elements
if (base == 'hosts') {
scope.job_id = null;
scope.host_id = $routeParams.id;
}
else {
scope.job_id = $routeParams.id;
scope.host_id = null;
if (base === 'hosts') {
$scope.job_id = null;
$scope.host_id = $routeParams.id;
} else {
$scope.job_id = $routeParams.id;
$scope.host_id = null;
}
if (scope.RemoveSetHostLink) {
scope.RemoveSetHostLink();
if ($scope.RemoveSetHostLink) {
$scope.RemoveSetHostLink();
}
scope.RemoveSetHostLink = scope.$on('setHostLink', function(e, inventory_id) {
for (var i=0; i < scope.jobhosts.length; i++) {
scope.jobhosts[i].hostLinkTo = '/#/inventories/' + inventory_id + '/?host_name=' +
escape(scope.jobhosts[i].summary_fields.host.name);
$scope.RemoveSetHostLink = $scope.$on('setHostLink', function (e, inventory_id) {
for (var i = 0; i < $scope.jobhosts.length; i++) {
$scope.jobhosts[i].hostLinkTo = '/#/inventories/' + inventory_id + '/?host_name=' +
encodeURI($scope.jobhosts[i].summary_fields.host.name);
}
});
// After a refresh, populate any needed summary field values on each row
if (scope.removePostRefresh) {
scope.removePostRefresh();
if ($scope.removePostRefresh) {
$scope.removePostRefresh();
}
scope.removePostRefresh = scope.$on('PostRefresh', function() {
$scope.removePostRefresh = $scope.$on('PostRefresh', function () {
// Set status, tooltips, badget icons, etc.
for( var i=0; i < scope.jobhosts.length; i++) {
scope.jobhosts[i].host_name = scope.jobhosts[i].summary_fields.host.name;
scope.jobhosts[i].status = (scope.jobhosts[i].failed) ? 'failed' : 'success';
scope.jobhosts[i].statusBadgeToolTip = JobStatusToolTip(scope.jobhosts[i].status) +
for (var i = 0; i < $scope.jobhosts.length; i++) {
$scope.jobhosts[i].host_name = $scope.jobhosts[i].summary_fields.host.name;
$scope.jobhosts[i].status = ($scope.jobhosts[i].failed) ? 'failed' : 'success';
$scope.jobhosts[i].statusBadgeToolTip = JobStatusToolTip($scope.jobhosts[i].status) +
" Click to view details.";
scope.jobhosts[i].statusLinkTo = '/#/jobs/' + scope.jobhosts[i].job + '/job_events/?host=' +
escape(scope.jobhosts[i].summary_fields.host.name);
$scope.jobhosts[i].statusLinkTo = '/#/jobs/' + $scope.jobhosts[i].job + '/job_events/?host=' +
encodeURI($scope.jobhosts[i].summary_fields.host.name);
}
if (scope.job_id !== null && scope.job_id !== undefined && scope.job_id !== '') {
if ($scope.job_id !== null && $scope.job_id !== undefined && $scope.job_id !== '') {
// need job_status so we can show/hide refresh button
Rest.setUrl(GetBasePath('jobs') + scope.job_id);
Rest.setUrl(GetBasePath('jobs') + $scope.job_id);
Rest.get()
.success( function(data, status, headers, config) {
LoadBreadCrumbs({ path: '/jobs/' + data.id, title: data.id + ' - ' +
data.summary_fields.job_template.name });
scope.job_status = data.status;
if (!(data.status == 'pending' || data.status == 'waiting' || data.status == 'running')) {
.success(function (data) {
LoadBreadCrumbs({
path: '/jobs/' + data.id,
title: data.id + ' - ' +
data.summary_fields.job_template.name
});
$scope.job_status = data.status;
if (!(data.status === 'pending' || data.status === 'waiting' || data.status === 'running')) {
if ($rootScope.timer) {
clearInterval($rootScope.timer);
}
}
scope.$emit('setHostLink', data.inventory);
$scope.$emit('setHostLink', data.inventory);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get job status for job: ' + scope.job_id + '. GET status: ' + status });
.error(function (data, status) {
ProcessErrors(scope, data, status, null, {
hdr: 'Error!',
msg: 'Failed to get job status for job: ' + $scope.job_id + '. GET status: ' + status
});
}
else {
});
} else {
// Make the host name appear in breadcrumbs
LoadBreadCrumbs({ path: '/hosts/' + scope['host_id'],
title: ( (scope.jobhosts.length > 0) ? scope.jobhosts[0].summary_fields.host.name : 'Host' ) });
if ($routeParams['inventory']) {
scope.$emit('setHostLink', $routeParams['inventory']);
LoadBreadCrumbs({
path: '/hosts/' + $scope.host_id,
title: (($scope.jobhosts.length > 0) ? $scope.jobhosts[0].summary_fields.host.name : 'Host')
});
if ($routeParams.inventory) {
$scope.$emit('setHostLink', $routeParams.inventory);
}
}
});
SearchInit({ scope: scope, set: 'jobhosts', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
SearchInit({
scope: scope,
set: 'jobhosts',
list: list,
url: defaultUrl
});
PaginateInit({
scope: scope,
list: list,
url: defaultUrl
});
// Called from Inventories tab, host failed events link:
if ($routeParams['host_name']) {
if ($routeParams.host_name) {
scope[list.iterator + 'SearchField'] = 'host';
scope[list.iterator + 'SearchValue'] = $routeParams['host_name'];
scope[list.iterator + 'SearchFieldLabel'] = list.fields['host'].label;
scope[list.iterator + 'SearchValue'] = $routeParams.host_name;
scope[list.iterator + 'SearchFieldLabel'] = list.fields.host.label;
}
scope.search(list.iterator);
$scope.search(list.iterator);
scope.showEvents = function(host_name, last_job) {
$scope.showEvents = function (host_name, last_job) {
// When click on !Failed Events link, redirect to latest job/job_events for the host
Rest.setUrl(last_job);
Rest.get()
.success( function(data, status, headers, config) {
LoadBreadCrumbs({ path: '/jobs/' + data.id, title: data.name });
$location.url('/jobs/' + data.id + '/job_events/?host=' + escape(host_name));
.success(function (data) {
LoadBreadCrumbs({
path: '/jobs/' + data.id,
title: data.name
});
$location.url('/jobs/' + data.id + '/job_events/?host=' + encodeURI(host_name));
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to lookup last job: ' + last_job + '. GET status: ' + status });
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to lookup last job: ' + last_job +
'. GET status: ' + status });
});
};
$scope.showJob = function (id) {
$location.path('/jobs/' + id);
};
$scope.refresh = function () {
if ($scope.host_id === null) {
$scope.jobSearchSpin = true;
$scope.jobLoading = true;
Wait('start');
Refresh({
scope: scope,
set: 'jobhosts',
iterator: 'jobhost',
url: $scope.current_url
});
}
scope.showJob = function(id) {
$location.path('/jobs/' + id);
}
scope.refresh = function() {
if (scope.host_id == null) {
scope['jobSearchSpin'] = true;
scope['jobLoading'] = true;
Wait('start');
Refresh({ scope: scope, set: 'jobhosts', iterator: 'jobhost', url: scope['current_url'] });
}
}
};
}
JobHostSummaryList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobHostList',
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
'ProcessErrors', 'GetBasePath', 'Refresh', 'JobStatusToolTip', 'Wait'
];
JobHostSummaryList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobHostList',
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
'GetBasePath', 'Refresh', 'JobStatusToolTip', 'Wait'
];

File diff suppressed because it is too large Load Diff

View File

@@ -12,110 +12,118 @@
'use strict';
function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobList, GenerateList, LoadBreadCrumbs, Prompt,
function JobsListCtrl($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobList, GenerateList, LoadBreadCrumbs, Prompt,
SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, LookUpInit, SubmitJob, FormatDate, Refresh,
JobStatusToolTip, Empty, Wait) {
ClearScope('htmlTemplate');
ClearScope();
var list = JobList,
defaultUrl = GetBasePath('jobs'),
view = GenerateList,
scope = view.inject(list, { mode: 'edit' }),
generator = GenerateList,
opt;
$rootScope.flashMessage = null;
scope.selected = [];
generator.inject(list, { mode: 'edit', scope: $scope });
if (scope.removePostRefresh) {
scope.removePostRefresh();
$rootScope.flashMessage = null;
$scope.selected = [];
if ($scope.removePostRefresh) {
$scope.removePostRefresh();
}
scope.removePostRefresh = scope.$on('PostRefresh', function() {
var i,cDate;
$("tr.success").each(function() {
$scope.removePostRefresh = $scope.$on('PostRefresh', function () {
var i, cDate;
$("tr.success").each(function () {
// Make sure no rows have a green background
var ngc = $(this).attr('ng-class');
scope[ngc] = "";
$scope[ngc] = "";
});
if (scope.jobs && scope.jobs.length) {
for (i=0; i < scope.jobs.length; i++) {
if ($scope.jobs && $scope.jobs.length) {
for (i = 0; i < $scope.jobs.length; i++) {
// Convert created date to local time zone
cDate = new Date(scope.jobs[i].created);
scope.jobs[i].created = FormatDate(cDate);
cDate = new Date($scope.jobs[i].created);
$scope.jobs[i].created = FormatDate(cDate);
// Set tooltip and link
scope.jobs[i].statusBadgeToolTip = JobStatusToolTip(scope.jobs[i].status) +
$scope.jobs[i].statusBadgeToolTip = JobStatusToolTip($scope.jobs[i].status) +
" Click to view status details.";
scope.jobs[i].statusLinkTo = '/#/jobs/' + scope.jobs[i].id;
$scope.jobs[i].statusLinkTo = '/#/jobs/' + $scope.jobs[i].id;
}
}
});
if ($routeParams.job_host_summaries__host) {
defaultUrl += '?job_host_summaries__host=' + $routeParams.job_host_summaries__host;
}
else if ($routeParams.inventory__int && $routeParams.status) {
} else if ($routeParams.inventory__int && $routeParams.status) {
defaultUrl += '?inventory__int=' + $routeParams.inventory__int + '&status=' +
$routeParams.status;
}
SearchInit({ scope: scope, set: 'jobs', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
SearchInit({
scope: $scope,
set: 'jobs',
list: list,
url: defaultUrl
});
PaginateInit({
scope: $scope,
list: list,
url: defaultUrl
});
// Called from Inventories page, failed jobs link. Find jobs for selected inventory.
if ($routeParams.inventory__int) {
scope[list.iterator + 'SearchField'] = 'inventory';
scope[list.iterator + 'SearchValue'] = $routeParams.inventory__int;
scope[list.iterator + 'SearchFieldLabel'] = 'Inventory ID';
$scope[list.iterator + 'SearchField'] = 'inventory';
$scope[list.iterator + 'SearchValue'] = $routeParams.inventory__int;
$scope[list.iterator + 'SearchFieldLabel'] = 'Inventory ID';
}
if ($routeParams.id__int) {
scope[list.iterator + 'SearchField'] = 'id';
scope[list.iterator + 'SearchValue'] = $routeParams.id__int;
scope[list.iterator + 'SearchFieldLabel'] = 'Job ID';
$scope[list.iterator + 'SearchField'] = 'id';
$scope[list.iterator + 'SearchValue'] = $routeParams.id__int;
$scope[list.iterator + 'SearchFieldLabel'] = 'Job ID';
}
if ($routeParams.status) {
scope[list.iterator + 'SearchField'] = 'status';
scope[list.iterator + 'SelectShow'] = true;
scope[list.iterator + 'SearchSelectOpts'] = list.fields.status.searchOptions;
scope[list.iterator + 'SearchFieldLabel'] = list.fields.status.label.replace(/<br>/g,' ');
$scope[list.iterator + 'SearchField'] = 'status';
$scope[list.iterator + 'SelectShow'] = true;
$scope[list.iterator + 'SearchSelectOpts'] = list.fields.status.searchOptions;
$scope[list.iterator + 'SearchFieldLabel'] = list.fields.status.label.replace(/<br>/g, ' ');
for (opt in list.fields.status.searchOptions) {
if (list.fields.status.searchOptions[opt].value === $routeParams.status) {
scope[list.iterator + 'SearchSelectValue'] = list.fields.status.searchOptions[opt];
$scope[list.iterator + 'SearchSelectValue'] = list.fields.status.searchOptions[opt];
break;
}
}
}
scope.search(list.iterator);
$scope.search(list.iterator);
LoadBreadCrumbs();
scope.refresh = function() {
$scope.refresh = function () {
Wait('start');
scope.jobLoading = false;
Refresh({ scope: scope, set: 'jobs', iterator: 'job', url: scope.current_url });
$scope.jobLoading = false;
Refresh({ scope: $scope, set: 'jobs', iterator: 'job', url: $scope.current_url });
};
scope.refreshJob = scope.refresh;
$scope.refreshJob = $scope.refresh;
scope.editJob = function(id, name) {
$scope.editJob = function (id, name) {
LoadBreadCrumbs({ path: '/jobs/' + id, title: id + ' - ' + name });
$location.path($location.path() + '/' + id);
};
scope.viewEvents = function(id, name) {
$scope.viewEvents = function (id, name) {
LoadBreadCrumbs({ path: '/jobs/' + id, title: id + ' - ' + name });
$location.path($location.path() + '/' + id + '/job_events');
};
scope.viewSummary = function(id, name) {
$scope.viewSummary = function (id, name) {
LoadBreadCrumbs({ path: '/jobs/' + id, title: id + ' - ' + name });
$location.path($location.path() + '/' + id + '/job_host_summaries');
};
scope.deleteJob = function(id) {
$scope.deleteJob = function (id) {
Rest.setUrl(defaultUrl + id + '/');
Rest.get()
.success( function(data) {
.success(function (data) {
var action, url, action_label, hdr;
@@ -123,37 +131,35 @@ function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest,
url = data.related.cancel;
action_label = 'cancel';
hdr = 'Cancel Job';
}
else {
} else {
url = defaultUrl + id + '/';
action_label = 'delete';
hdr = 'Delete Job';
}
action = function() {
action = function () {
Rest.setUrl(url);
if (action_label === 'cancel') {
Rest.post()
.success( function() {
.success(function () {
$('#prompt-modal').modal('hide');
scope.search(list.iterator);
$scope.search(list.iterator);
})
.error( function(data, status) {
.error(function (data, status) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url +
' failed. POST returned status: ' + status });
});
}
else {
} else {
Rest.destroy()
.success( function() {
.success(function () {
$('#prompt-modal').modal('hide');
scope.search(list.iterator);
$scope.search(list.iterator);
})
.error( function(data, status) {
.error(function (data, status) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url +
' failed. DELETE returned status: ' + status });
});
}
};
@@ -164,130 +170,130 @@ function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest,
action: action
});
})
.error( function(data, status) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get job details. GET returned status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get job details. GET returned status: ' + status });
});
};
scope.submitJob = function(id, template) {
SubmitJob({ scope: scope, id: id, template: template });
$scope.submitJob = function (id, template) {
SubmitJob({ scope: $scope, id: id, template: template });
};
}
JobsListCtrl.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobList',
JobsListCtrl.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobList',
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
'ProcessErrors','GetBasePath', 'LookUpInit', 'SubmitJob', 'FormatDate', 'Refresh', 'JobStatusToolTip',
'ProcessErrors', 'GetBasePath', 'LookUpInit', 'SubmitJob', 'FormatDate', 'Refresh', 'JobStatusToolTip',
'Empty', 'Wait'
];
];
function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, JobForm, GenerateForm, Rest, Alert, ProcessErrors,
LoadBreadCrumbs, RelatedSearchInit,RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList, CredentialList,
ProjectList, LookUpInit, PromptPasswords, GetBasePath, md5Setup, FormatDate, JobStatusToolTip, Wait) {
function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobForm, JobTemplateForm, GenerateForm, Rest,
Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList,
CredentialList, ProjectList, LookUpInit, PromptPasswords, GetBasePath, md5Setup, FormatDate, JobStatusToolTip, Wait, Empty) {
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
ClearScope();
var defaultUrl= GetBasePath('jobs'),
var defaultUrl = GetBasePath('jobs'),
generator = GenerateForm,
form = JobForm,
scope = generator.inject(form, {mode: 'edit', related: true}),
master = {},
id = $routeParams.id,
relatedSets = {},
loadingFinishedCount = 0;
loadingFinishedCount = 0,
templateForm = {};
generator.reset();
generator.inject(JobForm, { mode: 'edit', related: true, scope: $scope });
scope.job_id = id;
scope.parseType = 'yaml';
scope.statusSearchSpin = false;
$scope.job_id = id;
$scope.parseType = 'yaml';
$scope.statusSearchSpin = false;
function getPlaybooks(project) {
if (project !== null && project !== '' && project !== undefined) {
function getPlaybooks(project, playbook) {
if (!Empty(project)) {
var url = GetBasePath('projects') + project + '/playbooks/';
Rest.setUrl(url);
Rest.get()
.success( function(data) {
scope.playbook_options = [];
for (var i=0; i < data.length; i++) {
scope.playbook_options.push(data[i]);
.success(function (data) {
var i;
$scope.playbook_options = [];
for (i = 0; i < data.length; i++) {
$scope.playbook_options.push(data[i]);
}
scope.$emit('jobTemplateLoadFinished');
for (i = 0; i < $scope.playbook_options.length; i++) {
if ($scope.playbook_options[i] === playbook) {
$scope.playbook = $scope.playbook_options[i];
}
}
$scope.$emit('jobTemplateLoadFinished');
})
.error( function() {
scope.$emit('jobTemplateLoadFinished');
.error(function () {
$scope.$emit('jobTemplateLoadFinished');
});
}
else {
scope.$emit('jobTemplateLoadFinished');
} else {
$scope.$emit('jobTemplateLoadFinished');
}
}
// Retrieve each related set and populate the playbook list
if (scope.jobLoadedRemove) {
scope.jobLoadedRemove();
if ($scope.jobLoadedRemove) {
$scope.jobLoadedRemove();
}
scope.jobLoadedRemove = scope.$on('jobLoaded', function(e, related_cloud_credential) {
$scope.jobLoadedRemove = $scope.$on('jobLoaded', function (e, related_cloud_credential, project, playbook) {
getPlaybooks(scope.project);
getPlaybooks(project, playbook);
scope[form.name + 'ReadOnly'] = (scope.status === 'new') ? false : true;
//$scope[form.name + 'ReadOnly'] = ($scope.status === 'new') ? false : true;
$('#forks-slider').slider("option", "value", scope.forks);
$('#forks-slider').slider("disable");
$('input[type="checkbox"]').attr('disabled','disabled');
$('input[type="radio"]').attr('disabled','disabled');
$('#host_config_key-gen-btn').attr('disabled','disabled');
$('textarea').attr('readonly','readonly');
//$('#forks-slider').slider("option", "value", $scope.forks);
//$('#forks-slider').slider("disable");
//$('input[type="checkbox"]').attr('disabled', 'disabled');
//$('input[type="radio"]').attr('disabled', 'disabled');
//$('#host_config_key-gen-btn').attr('disabled', 'disabled');
//$('textarea').attr('readonly', 'readonly');
// Get job template and display/hide host callback fields
Rest.setUrl(scope.template_url);
/*Rest.setUrl($scope.template_url);
Rest.get()
.success( function(data) {
.success(function (data) {
var dft = (data.host_config_key) ? 'true' : 'false';
scope.host_config_key = data.host_config_key;
$scope.host_config_key = data.host_config_key;
md5Setup({
scope: scope,
scope: $scope,
master: master,
check_field: 'allow_callbacks',
default_val: dft
});
scope.callback_url = (data.related) ? data.related.callback : '<< Job template not found >>';
scope.$emit('jobTemplateLoadFinished');
$scope.callback_url = (data.related) ? data.related.callback : '<< Job template not found >>';
$scope.$emit('jobTemplateLoadFinished');
})
.error( function() {
.error(function () {
Wait('stop');
scope.callback_url = '<< Job template not found >>';
$scope.callback_url = '<< Job template not found >>';
});
*/
if (related_cloud_credential) {
//Get the name of the cloud credential
Rest.setUrl(related_cloud_credential);
Rest.get()
.success( function(data) {
scope.cloud_credential_name = data.name;
scope.$emit('jobTemplateLoadFinished');
.success(function (data) {
$scope.cloud_credential_name = data.name;
$scope.$emit('jobTemplateLoadFinished');
})
.error( function(data, status) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to related cloud credential. GET returned status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to related cloud credential. GET returned status: ' + status });
});
} else {
$scope.$emit('jobTemplateLoadFinished');
}
else {
scope.$emit('jobTemplateLoadFinished');
}
});
// Turn off 'Wait' after both cloud credential and playbook list come back
if (scope.removeJobTemplateLoadFinished) {
scope.removeJobTemplateLoadFinished();
if ($scope.removeJobTemplateLoadFinished) {
$scope.removeJobTemplateLoadFinished();
}
scope.removeJobTemplateLoadFinished = scope.$on('jobTemplateLoadFinished', function() {
$scope.removeJobTemplateLoadFinished = $scope.$on('jobTemplateLoadFinished', function () {
loadingFinishedCount++;
if (loadingFinishedCount >= 3) {
if (loadingFinishedCount >= 2) {
// The initial template load finished. Now load related jobs, which
// will turn off the 'working' spinner.
Wait('stop');
@@ -295,16 +301,27 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams,
});
// Our job type options
scope.job_type_options = [{ value: 'run', label: 'Run' }, { value: 'check', label: 'Check' }];
scope.verbosity_options = [
{ value: '0', label: 'Default' },
{ value: '1', label: 'Verbose' },
{ value: '3', label: 'Debug' }
];
scope.playbook_options = null;
scope.playbook = null;
$scope.job_type_options = [{
value: 'run',
label: 'Run'
}, {
value: 'check',
label: 'Check'
}];
$scope.verbosity_options = [{
value: 0,
label: 'Default'
}, {
value: 1,
label: 'Verbose'
}, {
value: 3,
label: 'Debug'
}];
$scope.playbook_options = null;
$scope.playbook = null;
function calcRows (content) {
function calcRows(content) {
var n = content.match(/\n/g),
rows = (n) ? n.length : 1;
return (rows > 15) ? 15 : rows;
@@ -313,152 +330,107 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams,
// Retrieve detail record and prepopulate the form
Wait('start');
Rest.setUrl(defaultUrl + ':id/');
Rest.get({ params: {id: id} })
.success( function(data) {
//LoadBreadCrumbs({ path: '/jobs/' + id, title: data.id + ' - ' + data.summary_fields.job_template.name });
var i, cDate, fld, json_obj, related, set;
Rest.get({ params: { id: id } })
.success(function (data) {
var i, fld, json_obj;
LoadBreadCrumbs();
for (fld in form.fields) {
$scope.status = data.status;
$scope.created = FormatDate(data.created);
$scope.result_stdout = data.result_stdout;
$scope.result_traceback = data.result_traceback;
$scope.stdout_rows = calcRows($scope.result_stdout);
$scope.traceback_rows = calcRows($scope.result_traceback);
// Now load the job template form
templateForm.addTitle = 'Create Job Templates';
templateForm.editTitle = '{{ name }}';
templateForm.name = 'job_templates';
templateForm.twoColumns = true;
templateForm.fields = angular.copy(JobTemplateForm.fields);
for (fld in templateForm.fields) {
templateForm.fields[fld].readonly = true;
}
$('#ui-accordion-jobs-collapse-0-panel-1').find('div').attr('id','job-template-container');
generator.inject(templateForm, { mode: 'edit', id: 'job-template-container', scope: $scope, breadCrumbs: false });
for (fld in templateForm.fields) {
if (fld !== 'variables' && data[fld] !== null && data[fld] !== undefined) {
if (form.fields[fld].type === 'select') {
if (scope[fld + '_options'] && scope[fld + '_options'].length > 0) {
for (i=0; i < scope[fld + '_options'].length; i++) {
if (data[fld] === scope[fld + '_options'][i].value) {
scope[fld] = scope[fld + '_options'][i];
if (JobTemplateForm.fields[fld].type === 'select') {
if ($scope[fld + '_options'] && $scope[fld + '_options'].length > 0) {
for (i = 0; i < $scope[fld + '_options'].length; i++) {
if (data[fld] === $scope[fld + '_options'][i].value) {
$scope[fld] = $scope[fld + '_options'][i];
}
}
} else {
$scope[fld] = data[fld];
}
else {
scope[fld] = data[fld];
} else {
$scope[fld] = data[fld];
}
}
}
else {
scope[fld] = data[fld];
}
master[fld] = scope[fld];
}
scope.id = data.id;
scope.name = (data.summary_fields && data.summary_fields.job_template) ? data.summary_fields.job_template.name : '';
if (fld === 'variables') {
// Parse extra_vars, converting to YAML.
if ($.isEmptyObject(data.extra_vars) || data.extra_vars === "{}" || data.extra_vars === "null" ||
data.extra_vars === "" || data.extra_vars === null) {
scope.variables = "---";
}
else {
$scope.variables = "---";
} else {
json_obj = JSON.parse(data.extra_vars);
scope.variables = jsyaml.safeDump(json_obj);
}
master.variables = scope.variables;
}
if (form.fields[fld].type === 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) {
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField];
}
for (fld in form.statusFields) {
if (data[fld] !== null && data[fld] !== undefined) {
if (fld === 'created') {
// Convert created date to local time zone
cDate = new Date(data.created);
scope.created = FormatDate(cDate);
}
else {
scope[fld] = data[fld];
$scope.variables = jsyaml.safeDump(json_obj);
}
}
}
scope.statusToolTip = JobStatusToolTip(data.status);
$('form[name="jobs_form"] input[type="text"], form[name="jobs_form"] jobs_form textarea').attr('readonly','readonly');
$('form[name="jobs_form"] select').prop('disabled', 'disabled');
$('form[name="jobs_form"] .lookup-btn').prop('disabled', 'disabled');
$('form[name="jobs_form"] .buttons, form[name="jobs_form"] hr').hide();
scope.url = data.url;
related = data.related;
for (set in form.related) {
if (related[set]) {
relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
if (JobTemplateForm.fields[fld].type === 'lookup' && data.summary_fields[JobTemplateForm.fields[fld].sourceModel]) {
$scope[JobTemplateForm.fields[fld].sourceModel + '_' + JobTemplateForm.fields[fld].sourceField] =
data.summary_fields[JobTemplateForm.fields[fld].sourceModel][JobTemplateForm.fields[fld].sourceField];
}
}
scope.stdout_rows = calcRows(scope.result_stdout);
$scope.id = data.id;
$scope.name = (data.summary_fields && data.summary_fields.job_template) ? data.summary_fields.job_template.name : '';
$scope.statusToolTip = JobStatusToolTip(data.status);
$scope.url = data.url;
$scope.project = data.project;
scope.traceback_rows = calcRows(scope.result_traceback);
LookUpInit({
scope: scope,
form: form,
current_item: data.inventory,
list: InventoryList,
field: 'inventory'
});
LookUpInit({
scope: scope,
form: form,
current_item: data.credential,
list: CredentialList,
field: 'credential'
});
LookUpInit({
scope: scope,
form: form,
current_item: data.project,
list: ProjectList,
field: 'project'
});
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
scope.template_url = data.related.job_template;
scope.$emit('jobLoaded', data.related.cloud_credential);
$scope.$emit('jobLoaded', data.related.cloud_credential, data.project, data.playbook);
})
.error( function(data, status) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve job: ' + $routeParams.id + '. GET status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve job: ' + $routeParams.id + '. GET status: ' + status });
});
scope.refresh = function() {
$scope.refresh = function () {
Wait('start');
Rest.setUrl(defaultUrl + id + '/');
Rest.get()
.success( function(data) {
scope.status = data.status;
scope.result_stdout = data.result_stdout;
scope.result_traceback = data.result_traceback;
scope.stdout_rows = calcRows(scope.result_stdout);
scope.traceback_rows = calcRows(scope.result_traceback);
.success(function (data) {
$scope.status = data.status;
$scope.result_stdout = data.result_stdout;
$scope.result_traceback = data.result_traceback;
$scope.stdout_rows = calcRows($scope.result_stdout);
$scope.traceback_rows = calcRows($scope.result_traceback);
Wait('stop');
})
.error( function(data, status) {
Wait('stop');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Attempt to load job failed. GET returned status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Attempt to load job failed. GET returned status: ' + status });
});
};
scope.jobSummary = function() {
$scope.jobSummary = function () {
$location.path('/jobs/' + id + '/job_host_summaries');
};
scope.jobEvents = function() {
$scope.jobEvents = function () {
$location.path('/jobs/' + id + '/job_events');
};
}
JobsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList',
'ProjectList', 'LookUpInit', 'PromptPasswords', 'GetBasePath', 'md5Setup', 'FormatDate',
'JobStatusToolTip', 'Wait'
];
JobsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobForm', 'JobTemplateForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit',
'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList', 'ProjectList', 'LookUpInit', 'PromptPasswords',
'GetBasePath', 'md5Setup', 'FormatDate', 'JobStatusToolTip', 'Wait', 'Empty'
];

View File

@@ -10,161 +10,170 @@
'use strict';
function OrganizationsList ($routeParams, $scope, $rootScope, $location, $log, Rest, Alert, LoadBreadCrumbs, Prompt,
GenerateList, OrganizationList, SearchInit, PaginateInit, ClearScope, ProcessErrors,
GetBasePath, SelectionInit, Wait, Stream)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
function OrganizationsList($routeParams, $scope, $rootScope, $location, $log, Rest, Alert, LoadBreadCrumbs, Prompt,
GenerateList, OrganizationList, SearchInit, PaginateInit, ClearScope, ProcessErrors, GetBasePath, SelectionInit, Wait, Stream) {
var list = OrganizationList;
var generate = GenerateList;
var paths = $location.path().replace(/^\//,'').split('/');
var mode = (paths[0] == 'organizations') ? 'edit' : 'select'; // if base path 'users', we're here to add/edit users
var scope = generate.inject(OrganizationList, { mode: mode }); // Inject our view
var defaultUrl = GetBasePath('organizations');
var iterator = list.iterator;
ClearScope();
var list = OrganizationList,
generate = GenerateList,
paths = $location.path().replace(/^\//, '').split('/'),
mode = (paths[0] === 'organizations') ? 'edit' : 'select',
defaultUrl = GetBasePath('organizations'),
url;
generate.inject(OrganizationList, { mode: mode, scope: $scope });
$rootScope.flashMessage = null;
LoadBreadCrumbs();
var url = GetBasePath('projects') + $routeParams.project_id + '/organizations/';
SelectionInit({ scope: scope, list: list, url: url, returnToCaller: 1 });
if (scope.removePostRefresh) {
scope.removePostRefresh();
if (mode === 'select') {
url = GetBasePath('projects') + $routeParams.project_id + '/organizations/';
SelectionInit({ scope: $scope, list: list, url: url, returnToCaller: 1 });
}
scope.removePostRefresh = scope.$on('PostRefresh', function() {
if ($scope.removePostRefresh) {
$scope.removePostRefresh();
}
$scope.removePostRefresh = $scope.$on('PostRefresh', function () {
// Cleanup after a delete
Wait('stop');
$('#prompt-modal').off();
});
// Initialize search and paginate pieces and load data
SearchInit({ scope: scope, set: list.name, list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
// Initialize search and pagination, then load data
SearchInit({
scope: $scope,
set: list.name,
list: list,
url: defaultUrl
});
PaginateInit({
scope: $scope,
list: list,
url: defaultUrl
});
$scope.search(list.iterator);
scope.showActivity = function() { Stream({ scope: scope }); }
$scope.showActivity = function () {
Stream({ scope: $scope });
};
scope.addOrganization = function() {
$scope.addOrganization = function () {
$location.path($location.path() + '/add');
}
};
scope.editOrganization = function(id) {
$scope.editOrganization = function (id) {
$location.path($location.path() + '/' + id);
}
};
scope.deleteOrganization = function(id, name) {
$scope.deleteOrganization = function (id, name) {
var action = function() {
$('#prompt-modal').on('hidden.bs.modal', function(){ Wait('start'); });
var action = function () {
$('#prompt-modal').on('hidden.bs.modal', function () {
Wait('start');
});
$('#prompt-modal').modal('hide');
var url = defaultUrl + id + '/';
Rest.setUrl(url);
Rest.destroy()
.success( function(data, status, headers, config) {
scope.search(list.iterator);
.success(function () {
$scope.search(list.iterator);
})
.error( function(data, status, headers, config) {
Wait('stop');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
};
Prompt({ hdr: 'Delete',
Prompt({
hdr: 'Delete',
body: 'Are you sure you want to delete ' + name + '?',
action: action
});
}
};
}
OrganizationsList.$inject=[ '$routeParams', '$scope', '$rootScope', '$location', '$log', 'Rest', 'Alert', 'LoadBreadCrumbs', 'Prompt',
'GenerateList', 'OrganizationList', 'SearchInit', 'PaginateInit', 'ClearScope', 'ProcessErrors',
'GetBasePath', 'SelectionInit', 'Wait', 'Stream'];
OrganizationsList.$inject = ['$routeParams', '$scope', '$rootScope', '$location', '$log', 'Rest', 'Alert', 'LoadBreadCrumbs', 'Prompt',
'GenerateList', 'OrganizationList', 'SearchInit', 'PaginateInit', 'ClearScope', 'ProcessErrors', 'GetBasePath', 'SelectionInit', 'Wait',
'Stream'
];
function OrganizationsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm,
function OrganizationsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath,
ReturnToCaller, Wait)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
ReturnToCaller, Wait) {
ClearScope();
// Inject dynamic view
var generator = GenerateForm;
var form = OrganizationForm;
var scope = generator.inject(form, {mode: 'add', related: false});
var base = $location.path().replace(/^\//,'').split('/')[0];
var defaultUrl = GetBasePath('organizations');
var generator = GenerateForm,
form = OrganizationForm,
base = $location.path().replace(/^\//, '').split('/')[0];
generator.inject(form, { mode: 'add', related: false, scope: $scope});
generator.reset();
LoadBreadCrumbs();
// Save
scope.formSave = function() {
$scope.formSave = function () {
generator.clearApiErrors();
Wait('start');
var url = GetBasePath(base);
url += (base != 'organizations') ? $routeParams['project_id'] + '/organizations/' : '';
url += (base !== 'organizations') ? $routeParams.project_id + '/organizations/' : '';
Rest.setUrl(url);
Rest.post({ name: $scope.name,
description: $scope.description })
.success( function(data, status, headers, config) {
Rest.post({ name: $scope.name, description: $scope.description })
.success(function (data) {
Wait('stop');
if (base == 'organizations') {
if (base === 'organizations') {
$rootScope.flashMessage = "New organization successfully created!";
$location.path('/organizations/' + data.id);
}
else {
} else {
ReturnToCaller(1);
}
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to add new organization. Post returned status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to add new organization. Post returned status: ' + status });
});
};
// Cancel
scope.formReset = function() {
$scope.formReset = function () {
$rootScope.flashMessage = null;
generator.reset();
};
}
OrganizationsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'OrganizationForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath',
'ReturnToCaller', 'Wait'];
OrganizationsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'OrganizationForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', 'ReturnToCaller', 'Wait'
];
function OrganizationsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
RelatedPaginateInit, Prompt, ClearScope, GetBasePath, Wait, Stream)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
function OrganizationsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm, GenerateForm, Rest,
Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, Prompt, ClearScope, GetBasePath, Wait, Stream) {
ClearScope();
// Inject dynamic view
var form = OrganizationForm;
var generator = GenerateForm;
var scope = GenerateForm.inject(form, {mode: 'edit', related: true});
var form = OrganizationForm,
generator = GenerateForm,
defaultUrl = GetBasePath('organizations'),
base = $location.path().replace(/^\//, '').split('/')[0],
master = {},
id = $routeParams.organization_id,
relatedSets = {};
generator.inject(form, { mode: 'edit', related: true, scope: $scope});
generator.reset();
var defaultUrl = GetBasePath('organizations');
var base = $location.path().replace(/^\//,'').split('/')[0];
var master = {};
var id = $routeParams.organization_id;
var relatedSets = {};
// After the Organization is loaded, retrieve each related set
if (scope.organizationLoadedRemove) {
scope.organizationLoadedRemove();
if ($scope.organizationLoadedRemove) {
$scope.organizationLoadedRemove();
}
scope.organizationLoadedRemove = scope.$on('organizationLoaded', function() {
$scope.organizationLoadedRemove = $scope.$on('organizationLoaded', function () {
for (var set in relatedSets) {
scope.search(relatedSets[set].iterator);
$scope.search(relatedSets[set].iterator);
}
Wait('stop');
});
@@ -173,106 +182,113 @@ function OrganizationsEdit ($scope, $rootScope, $compile, $location, $log, $rout
Wait('start');
Rest.setUrl(defaultUrl + id + '/');
Rest.get()
.success( function(data, status, headers, config) {
.success(function (data) {
var fld, related, set;
LoadBreadCrumbs({ path: '/organizations/' + id, title: data.name });
for (var fld in form.fields) {
for (fld in form.fields) {
if (data[fld]) {
scope[fld] = data[fld];
$scope[fld] = data[fld];
master[fld] = data[fld];
}
}
var related = data.related;
for (var set in form.related) {
related = data.related;
for (set in form.related) {
if (related[set]) {
relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
relatedSets[set] = {
url: related[set],
iterator: form.related[set].iterator
};
}
}
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
scope.$emit('organizationLoaded');
RelatedSearchInit({ scope: $scope, form: form, relatedSets: relatedSets });
RelatedPaginateInit({ scope: $scope, relatedSets: relatedSets });
$scope.$emit('organizationLoaded');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve organization: ' + $routeParams.id + '. GET status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to retrieve organization: ' + $routeParams.id + '. GET status: ' + status });
});
// Save changes to the parent
scope.formSave = function() {
$scope.formSave = function () {
var fld, params = {};
generator.clearApiErrors();
Wait('start');
var params = {};
for (var fld in form.fields) {
params[fld] = scope[fld];
for (fld in form.fields) {
params[fld] = $scope[fld];
}
Rest.setUrl(defaultUrl + id + '/');
Rest.put(params)
.success( function(data, status, headers, config) {
.success(function () {
Wait('stop');
master = params;
$rootScope.flashMessage = "Your changes were successfully saved!";
})
.error( function(data, status, headers, config) {
Wait('stop');
ProcessErrors(scope, data, status, OrganizationForm,
{ hdr: 'Error!', msg: 'Failed to update organization: ' + id + '. PUT status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, OrganizationForm, { hdr: 'Error!',
msg: 'Failed to update organization: ' + id + '. PUT status: ' + status });
});
};
scope.showActivity = function() { Stream({ scope: scope }); }
$scope.showActivity = function () {
Stream({
$scope: $scope
});
};
// Reset the form
scope.formReset = function() {
$scope.formReset = function () {
$rootScope.flashMessage = null;
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
$scope[fld] = master[fld];
}
};
// Related set: Add button
scope.add = function(set) {
$scope.add = function (set) {
$rootScope.flashMessage = null;
$location.path('/' + base + '/' + $routeParams.organization_id + '/' + set);
};
// Related set: Edit button
scope.edit = function(set, id, name) {
$scope.edit = function (set, id) {
$rootScope.flashMessage = null;
$location.path('/' + set + '/' + id);
};
// Related set: Delete button
scope['delete'] = function(set, itm_id, name, title) {
$scope['delete'] = function (set, itm_id, name, title) {
$rootScope.flashMessage = null;
var action = function() {
var action = function () {
Wait('start');
var url = defaultUrl + $routeParams.organization_id + '/' + set + '/';
Rest.setUrl(url);
Rest.post({ id: itm_id, disassociate: 1 })
.success( function(data, status, headers, config) {
Wait('stop');
.success(function () {
$('#prompt-modal').modal('hide');
scope.search(form.related[set].iterator);
$scope.search(form.related[set].iterator);
})
.error( function(data, status, headers, config) {
Wait('stop');
.error(function (data, status) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
});
};
Prompt({ hdr: 'Delete',
body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?',
Prompt({
hdr: 'Delete',
body: 'Are you sure you want to remove ' + name + ' from ' + $scope.name + ' ' + title + '?',
action: action
});
}
};
}
OrganizationsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'OrganizationForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
'RelatedPaginateInit', 'Prompt', 'ClearScope', 'GetBasePath', 'Wait', 'Stream'];
OrganizationsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'OrganizationForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit', 'Prompt', 'ClearScope', 'GetBasePath',
'Wait', 'Stream'
];

View File

@@ -10,111 +10,124 @@
'use strict';
function PermissionsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, PermissionList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
ClearScope, ProcessErrors, GetBasePath, CheckAccess, Wait)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var list = PermissionList;
var base = $location.path().replace(/^\//,'').split('/')[0];
var defaultUrl = GetBasePath(base);
defaultUrl += ($routeParams['user_id'] !== undefined) ? $routeParams['user_id'] : $routeParams['team_id'];
function PermissionsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, PermissionList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors,
GetBasePath, CheckAccess, Wait) {
ClearScope();
var list = PermissionList,
base = $location.path().replace(/^\//, '').split('/')[0],
defaultUrl = GetBasePath(base),
generator = GenerateList;
generator.inject(list, { mode: 'edit', scope: $scope });
defaultUrl += ($routeParams.user_id !== undefined) ? $routeParams.user_id : $routeParams.team_id;
defaultUrl += '/permissions/';
var view = GenerateList;
var scope = view.inject(list, { mode: 'edit' }); // Inject our view
scope.selected = [];
$scope.selected = [];
CheckAccess({ scope: scope });
CheckAccess({
scope: $scope
});
if (scope.removePostRefresh) {
scope.removePostRefresh();
if ($scope.removePostRefresh) {
$scope.removePostRefresh();
}
scope.removePostRefresh = scope.$on('PostRefresh', function() {
$scope.removePostRefresh = $scope.$on('PostRefresh', function () {
// Cleanup after a delete
Wait('stop');
$('#prompt-modal').off();
});
SearchInit({ scope: scope, set: 'permissions', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
SearchInit({
scope: $scope,
set: 'permissions',
list: list,
url: defaultUrl
});
PaginateInit({
scope: $scope,
list: list,
url: defaultUrl
});
$scope.search(list.iterator);
LoadBreadCrumbs();
scope.addPermission = function() {
if (scope.PermissionAddAllowed) {
$scope.addPermission = function () {
if ($scope.PermissionAddAllowed) {
$location.path($location.path() + '/add');
}
}
};
scope.editPermission = function(id) {
$scope.editPermission = function (id) {
$location.path($location.path() + '/' + id);
}
};
scope.deletePermission = function(id, name) {
var action = function() {
$('#prompt-modal').on('hidden.bs.modal', function(){ Wait('start'); });
$scope.deletePermission = function (id, name) {
var action = function () {
$('#prompt-modal').on('hidden.bs.modal', function () {
Wait('start');
});
$('#prompt-modal').modal('hide');
var url = GetBasePath('base') + 'permissions/' + id + '/';
Rest.setUrl(url);
Rest.destroy()
.success( function(data, status, headers, config) {
scope.search(list.iterator);
.success(function () {
$scope.search(list.iterator);
})
.error( function(data, status, headers, config) {
.error(function (data, status) {
Wait('stop');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
};
if (scope.PermissionAddAllowed) {
Prompt({ hdr: 'Delete',
if ($scope.PermissionAddAllowed) {
Prompt({
hdr: 'Delete',
body: 'Are you sure you want to delete ' + name + '?',
action: action
});
}
}
};
}
PermissionsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'PermissionList',
PermissionsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'PermissionList',
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller',
'ClearScope', 'ProcessErrors', 'GetBasePath', 'CheckAccess', 'Wait'
];
];
function PermissionsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm,
function PermissionsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope,
GetBasePath, ReturnToCaller, InventoryList, ProjectList, LookUpInit, CheckAccess,
Wait, PermissionCategoryChange)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
Wait, PermissionCategoryChange) {
ClearScope();
// Inject dynamic view
var form = PermissionsForm;
var generator = GenerateForm;
var id = ($routeParams.user_id !== undefined) ? $routeParams.user_id : $routeParams.team_id;
var base = $location.path().replace(/^\//,'').split('/')[0];
var defaultUrl = GetBasePath(base) + id + '/permissions';
var scope = generator.inject(form, {mode: 'add', related: false});
var master = {};
var form = PermissionsForm,
generator = GenerateForm,
id = ($routeParams.user_id !== undefined) ? $routeParams.user_id : $routeParams.team_id,
base = $location.path().replace(/^\//, '').split('/')[0],
master = {};
CheckAccess({ scope: scope })
generator.inject(form, { mode: 'add', related: false, scope: $scope });
CheckAccess({ scope: $scope });
generator.reset();
LoadBreadCrumbs();
scope['inventoryrequired'] = true;
scope['projectrequired'] = false;
scope.category = 'Inventory';
$scope.inventoryrequired = true;
$scope.projectrequired = false;
$scope.category = 'Inventory';
master.category = 'Inventory';
master.inventoryrequired = true;
master.projectrequired = false;
LookUpInit({
scope: scope,
scope: $scope,
form: form,
current_item: null,
list: InventoryList,
@@ -122,7 +135,7 @@ function PermissionsAdd ($scope, $rootScope, $compile, $location, $log, $routePa
});
LookUpInit({
scope: scope,
scope: $scope,
form: form,
current_item: null,
list: ProjectList,
@@ -130,112 +143,111 @@ function PermissionsAdd ($scope, $rootScope, $compile, $location, $log, $routePa
});
// Save
scope.formSave = function() {
$scope.formSave = function () {
var fld, url, data = {};
generator.clearApiErrors();
Wait('start');
if (scope.PermissionAddAllowed) {
var data = {};
for (var fld in form.fields) {
data[fld] = scope[fld];
if ($scope.PermissionAddAllowed) {
data = {};
for (fld in form.fields) {
data[fld] = $scope[fld];
}
var url = (base == 'teams') ? GetBasePath('teams') + id + '/permissions/' : GetBasePath('users') + id + '/permissions/';
url = (base === 'teams') ? GetBasePath('teams') + id + '/permissions/' : GetBasePath('users') + id + '/permissions/';
Rest.setUrl(url);
Rest.post(data)
.success( function(data, status, headers, config) {
.success(function () {
Wait('stop');
ReturnToCaller(1);
})
.error( function(data, status, headers, config) {
.error(function (data, status) {
Wait('stop');
ProcessErrors(scope, data, status, PermissionsForm,
{ hdr: 'Error!', msg: 'Failed to create new permission. Post returned status: ' + status });
ProcessErrors($scope, data, status, PermissionsForm, { hdr: 'Error!',
msg: 'Failed to create new permission. Post returned status: ' + status });
});
}
else {
Alert('Access Denied', 'You do not have access to create new permission objects. Please contact a system administrator.', 'alert-danger');
} else {
Alert('Access Denied', 'You do not have access to create new permission objects. Please contact a system administrator.',
'alert-danger');
}
};
// Cancel
scope.formReset = function() {
$scope.formReset = function () {
$rootScope.flashMessage = null;
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
$scope[fld] = master[fld];
}
scope.selectCategory();
$scope.selectCategory();
};
scope.selectCategory = function() { PermissionCategoryChange({ scope: scope, reset: true }); };
$scope.selectCategory = function () {
PermissionCategoryChange({ scope: $scope, reset: true });
};
scope.selectCategory();
$scope.selectCategory();
}
PermissionsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'PermissionsForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath',
'ReturnToCaller', 'InventoryList', 'ProjectList', 'LookUpInit', 'CheckAccess', 'Wait',
'PermissionCategoryChange'
];
PermissionsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'PermissionsForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'GetBasePath', 'ReturnToCaller',
'InventoryList', 'ProjectList', 'LookUpInit', 'CheckAccess', 'Wait', 'PermissionCategoryChange'
];
function PermissionsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller,
ClearScope, Prompt, GetBasePath, InventoryList, ProjectList, LookUpInit, CheckAccess,
Wait, PermissionCategoryChange)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
function PermissionsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, Prompt, GetBasePath,
InventoryList, ProjectList, LookUpInit, CheckAccess, Wait, PermissionCategoryChange) {
var generator = GenerateForm;
var form = PermissionsForm;
var scope = generator.inject(form, {mode: 'edit', related: true});
var base_id = ($routeParams.user_id !== undefined) ? $routeParams.user_id : $routeParams.team_id;
var base = $location.path().replace(/^\//,'').split('/')[0];
var id = $routeParams.permission_id;
var defaultUrl = GetBasePath('base') + 'permissions/' + id + '/';
ClearScope();
var generator = GenerateForm,
form = PermissionsForm,
base_id = ($routeParams.user_id !== undefined) ? $routeParams.user_id : $routeParams.team_id,
id = $routeParams.permission_id,
defaultUrl = GetBasePath('base') + 'permissions/' + id + '/',
master = {};
generator.inject(form, { mode: 'edit', related: true, scope: $scope });
generator.reset();
var master = {};
var relatedSets = {};
CheckAccess({ scope: scope });
CheckAccess({ scope: $scope });
scope.selectCategory = function(resetIn) {
var reset = (resetIn == false) ? false : true;
PermissionCategoryChange({ scope: scope, reset: reset }); }
$scope.selectCategory = function (resetIn) {
var reset = (resetIn === false) ? false : true;
PermissionCategoryChange({ scope: $scope, reset: reset });
};
// Retrieve detail record and prepopulate the form
Wait('start');
Rest.setUrl(defaultUrl);
Rest.get()
.success( function(data, status, headers, config) {
.success(function (data) {
var fld, sourceModel, sourceField;
LoadBreadCrumbs({ path: '/users/' + base_id + '/permissions/' + id, title: data.name });
for (var fld in form.fields) {
for (fld in form.fields) {
if (data[fld]) {
if (form.fields[fld].sourceModel) {
var sourceModel = form.fields[fld].sourceModel;
var sourceField = form.fields[fld].sourceField;
scope[sourceModel + '_' + sourceField] = data.summary_fields[sourceModel][sourceField];
sourceModel = form.fields[fld].sourceModel;
sourceField = form.fields[fld].sourceField;
$scope[sourceModel + '_' + sourceField] = data.summary_fields[sourceModel][sourceField];
master[sourceModel + '_' + sourceField] = data.summary_fields[sourceModel][sourceField];
}
scope[fld] = data[fld];
master[fld] = scope[fld];
$scope[fld] = data[fld];
master[fld] = $scope[fld];
}
}
scope.category = 'Deploy';
if (data['permission_type'] != 'run' && data['permission_type'] != 'check' ) {
scope.category = 'Inventory';
$scope.category = 'Deploy';
if (data.permission_type !== 'run' && data.permission_type !== 'check') {
$scope.category = 'Inventory';
}
master['category'] = scope.category;
scope.selectCategory(false); //call without resetting scope.category value
master.category = $scope.category;
$scope.selectCategory(false); //call without resetting $scope.category value
LookUpInit({
scope: scope,
scope: $scope,
form: form,
current_item: data.inventory,
list: InventoryList,
@@ -243,70 +255,67 @@ function PermissionsEdit ($scope, $rootScope, $compile, $location, $log, $routeP
});
LookUpInit({
scope: scope,
scope: $scope,
form: form,
current_item: data.project,
list: ProjectList,
field: 'project'
});
if (!scope.PermissionAddAllowed) {
if (!$scope.PermissionAddAllowed) {
// If not a privileged user, disable access
$('form[name="permission_form"]').find('select, input, button').each(function(index){
$('form[name="permission_form"]').find('select, input, button').each(function () {
if ($(this).is('input') || $(this).is('select')) {
$(this).attr('readonly','readonly');
$(this).attr('readonly', 'readonly');
}
if ( $(this).is('input[type="checkbox"]') ||
if ($(this).is('input[type="checkbox"]') ||
$(this).is('input[type="radio"]') ||
$(this).is('button') ) {
$(this).attr('disabled','disabled');
$(this).is('button')) {
$(this).attr('disabled', 'disabled');
}
});
}
Wait('stop');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve Permission: ' + id + '. GET status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to retrieve Permission: ' + id + '. GET status: ' + status });
});
// Save changes to the parent
scope.formSave = function() {
$scope.formSave = function () {
var fld, data = {};
generator.clearApiErrors();
Wait('start');
var data = {}
for (var fld in form.fields) {
data[fld] = scope[fld];
for (fld in form.fields) {
data[fld] = $scope[fld];
}
Rest.setUrl(defaultUrl);
Rest.put(data)
.success( function(data, status, headers, config) {
.success(function () {
Wait('stop');
ReturnToCaller(1);
})
.error( function(data, status, headers, config) {
Wait('stop');
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update Permission: ' + $routeParams.id + '. PUT status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, form, { hdr: 'Error!', msg: 'Failed to update Permission: ' +
$routeParams.id + '. PUT status: ' + status });
});
};
// Cancel
scope.formReset = function() {
$scope.formReset = function () {
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
$scope[fld] = master[fld];
}
scope.selectCategory(false);
$scope.selectCategory(false);
};
}
PermissionsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'PermissionsForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller',
'ClearScope', 'Prompt', 'GetBasePath', 'InventoryList', 'ProjectList', 'LookUpInit', 'CheckAccess',
'Wait', 'PermissionCategoryChange'
];
PermissionsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'PermissionsForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'Prompt', 'GetBasePath',
'InventoryList', 'ProjectList', 'LookUpInit', 'CheckAccess', 'Wait', 'PermissionCategoryChange'
];

File diff suppressed because it is too large Load Diff

View File

@@ -10,112 +10,124 @@
'use strict';
function TeamsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, TeamList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
ClearScope, ProcessErrors, SetTeamListeners, GetBasePath, SelectionInit, Wait, Stream)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
var list = TeamList;
var defaultUrl = GetBasePath('teams');
var view = GenerateList;
var paths = $location.path().replace(/^\//,'').split('/');
var mode = (paths[0] == 'teams') ? 'edit' : 'select'; // if base path 'teams', we're here to add/edit teams
var scope = view.inject(list, { mode: mode }); // Inject our view
scope.selected = [];
function TeamsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, TeamList, GenerateList, LoadBreadCrumbs,
Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, SetTeamListeners, GetBasePath, SelectionInit, Wait,
Stream) {
var url = GetBasePath('base') + $location.path() + '/';
SelectionInit({ scope: scope, list: list, url: url, returnToCaller: 1 });
ClearScope();
if (scope.removePostRefresh) {
scope.removePostRefresh();
var list = TeamList,
defaultUrl = GetBasePath('teams'),
generator = GenerateList,
paths = $location.path().replace(/^\//, '').split('/'),
mode = (paths[0] === 'teams') ? 'edit' : 'select',
url;
generator.inject(list, { mode: mode, scope: $scope });
$scope.selected = [];
url = GetBasePath('base') + $location.path() + '/';
SelectionInit({
scope: $scope,
list: list,
url: url,
returnToCaller: 1
});
if ($scope.removePostRefresh) {
$scope.removePostRefresh();
}
scope.removePostRefresh = scope.$on('PostRefresh', function() {
$scope.removePostRefresh = $scope.$on('PostRefresh', function () {
// After a refresh, populate the organization name on each row
if (scope.teams) {
for ( var i=0; i < scope.teams.length; i++) {
scope.teams[i].organization_name = scope.teams[i].summary_fields.organization.name;
var i;
if ($scope.teams) {
for (i = 0; i < $scope.teams.length; i++) {
$scope.teams[i].organization_name = $scope.teams[i].summary_fields.organization.name;
}
}
});
SearchInit({ scope: scope, set: 'teams', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
SearchInit({
scope: $scope,
set: 'teams',
list: list,
url: defaultUrl
});
PaginateInit({
scope: $scope,
list: list,
url: defaultUrl
});
$scope.search(list.iterator);
LoadBreadCrumbs();
scope.showActivity = function() { Stream({ scope: scope }); }
$scope.showActivity = function () {
Stream({ scope: $scope });
};
scope.addTeam = function() {
$scope.addTeam = function () {
$location.path($location.path() + '/add');
}
};
scope.editTeam = function(id) {
$scope.editTeam = function (id) {
$location.path($location.path() + '/' + id);
}
};
scope.deleteTeam = function(id, name) {
$scope.deleteTeam = function (id, name) {
var action = function() {
var action = function () {
Wait('start');
var url = defaultUrl + id + '/';
Rest.setUrl(url);
Rest.destroy()
.success( function(data, status, headers, config) {
.success(function () {
Wait('stop');
$('#prompt-modal').modal('hide');
scope.search(list.iterator);
$scope.search(list.iterator);
})
.error( function(data, status, headers, config) {
.error(function (data, status) {
Wait('stop');
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
ProcessErrors($scope, data, status, null, {
hdr: 'Error!',
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status
});
});
};
Prompt({ hdr: 'Delete',
Prompt({
hdr: 'Delete',
body: 'Are you sure you want to delete ' + name + '?',
action: action
});
}
/*
scope.lookupOrganization = function(organization_id) {
Rest.setUrl(GetBasePath('organizations') + organization_id + '/');
Rest.get()
.success( function(data, status, headers, config) {
return data.name;
});
}
*/
};
}
TeamsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'TeamList', 'GenerateList',
TeamsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'TeamList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
'SetTeamListeners', 'GetBasePath', 'SelectionInit', 'Wait', 'Stream' ];
'SetTeamListeners', 'GetBasePath', 'SelectionInit', 'Wait', 'Stream'
];
function TeamsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, GenerateForm,
function TeamsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, GenerateForm,
Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateList,
OrganizationList, SearchInit, PaginateInit, GetBasePath, LookUpInit, Wait)
{
OrganizationList, SearchInit, PaginateInit, GetBasePath, LookUpInit, Wait) {
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
//$scope.
// Inject dynamic view
var defaultUrl = GetBasePath('teams');
var form = TeamForm;
var generator = GenerateForm;
var scope = generator.inject(form, {mode: 'add', related: false});
var defaultUrl = GetBasePath('teams'),
form = TeamForm,
generator = GenerateForm,
scope = generator.inject(form, { mode: 'add', related: false });
$rootScope.flashMessage = null;
generator.reset();
LoadBreadCrumbs();
LookUpInit({
scope: scope,
scope: $scope,
form: form,
current_item: null,
list: OrganizationList,
@@ -123,233 +135,248 @@ function TeamsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams,
});
// Save
scope.formSave = function() {
$scope.formSave = function () {
var fld, data;
generator.clearApiErrors();
Wait('start');
Rest.setUrl(defaultUrl);
var data = {}
for (var fld in form.fields) {
data = {};
for (fld in form.fields) {
data[fld] = scope[fld];
}
Rest.post(data)
.success( function(data, status, headers, config) {
.success(function (data) {
Wait('stop');
$rootScope.flashMessage = "New team successfully created!";
$location.path('/teams/' + data.id);
})
.error( function(data, status, headers, config) {
.error(function (data, status) {
Wait('stop');
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to add new team. Post returned status: ' + status });
ProcessErrors($scope, data, status, form, { hdr: 'Error!', msg: 'Failed to add new team. Post returned status: ' +
status });
});
};
// Reset
scope.formReset = function() {
$scope.formReset = function () {
// Defaults
generator.reset();
};
}
TeamsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'TeamForm', 'GenerateForm',
TeamsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'TeamForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList',
'OrganizationList', 'SearchInit', 'PaginateInit', 'GetBasePath', 'LookUpInit', 'Wait'];
'OrganizationList', 'SearchInit', 'PaginateInit', 'GetBasePath', 'LookUpInit', 'Wait'
];
function TeamsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInit, Prompt,
GetBasePath, CheckAccess, OrganizationList, Wait, Stream)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
function TeamsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, GenerateForm, Rest, Alert, ProcessErrors,
LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInit, Prompt, GetBasePath, CheckAccess,
OrganizationList, Wait, Stream) {
var defaultUrl=GetBasePath('teams');
var generator = GenerateForm;
var form = TeamForm;
var scope = generator.inject(form, {mode: 'edit', related: true});
ClearScope();
var defaultUrl = GetBasePath('teams'),
generator = GenerateForm,
form = TeamForm,
base = $location.path().replace(/^\//, '').split('/')[0],
master = {},
id = $routeParams.team_id,
relatedSets = {};
generator.inject(form, { mode: 'edit', related: true, scope: $scope });
generator.reset();
var base = $location.path().replace(/^\//,'').split('/')[0];
var master = {};
var id = $routeParams.team_id;
var relatedSets = {};
scope.PermissionAddAllowed = false;
$scope.PermissionAddAllowed = false;
// Retrieve each related set and any lookups
if (scope.teamLoadedRemove) {
scope.teamLoadedRemove();
if ($scope.teamLoadedRemove) {
$scope.teamLoadedRemove();
}
scope.teamLoadedRemove = scope.$on('teamLoaded', function() {
CheckAccess({ scope: scope });
Rest.setUrl(scope['organization_url']);
$scope.teamLoadedRemove = $scope.$on('teamLoaded', function () {
CheckAccess({ scope: $scope });
Rest.setUrl($scope.organization_url);
Rest.get()
.success( function(data, status, headers, config) {
scope['organization_name'] = data.name;
master['organization_name'] = data.name;
.success(function (data) {
$scope.organization_name = data.name;
master.organization_name = data.name;
Wait('stop');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to retrieve organization: ' + scope.orgnization_url + '. GET status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve organization: ' +
$scope.orgnization_url + '. GET status: ' + status });
});
for (var set in relatedSets) {
scope.search(relatedSets[set].iterator);
$scope.search(relatedSets[set].iterator);
}
});
// Retrieve detail record and prepopulate the form
Wait('start');
Rest.setUrl(defaultUrl + ':id/');
Rest.get({ params: {id: id} })
.success( function(data, status, headers, config) {
Rest.get({
params: {
id: id
}
})
.success(function (data) {
var fld, related, set;
LoadBreadCrumbs({ path: '/teams/' + id, title: data.name });
for (var fld in form.fields) {
for (fld in form.fields) {
if (data[fld]) {
scope[fld] = data[fld];
master[fld] = scope[fld];
$scope[fld] = data[fld];
master[fld] = $scope[fld];
}
}
var related = data.related;
for (var set in form.related) {
related = data.related;
for (set in form.related) {
if (related[set]) {
relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
relatedSets[set] = {
url: related[set],
iterator: form.related[set].iterator
};
}
}
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
RelatedSearchInit({
scope: $scope,
form: form,
relatedSets: relatedSets
});
RelatedPaginateInit({
scope: $scope,
relatedSets: relatedSets
});
LookUpInit({
scope: scope,
scope: $scope,
form: form,
current_item: data['organization'],
current_item: data.organization,
list: OrganizationList,
field: 'organization'
});
scope['organization_url'] = data.related.organization;
scope.$emit('teamLoaded');
$scope.organization_url = data.related.organization;
$scope.$emit('teamLoaded');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve team: ' + $routeParams.team_id + '. GET status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, form, { hdr: 'Error!', msg: 'Failed to retrieve team: ' + $routeParams.team_id +
'. GET status: ' + status });
});
scope.showActivity = function() { Stream({ scope: scope }); }
$scope.showActivity = function () {
Stream({ scope: $scope });
};
// Save changes to the parent
scope.formSave = function() {
$scope.formSave = function () {
var data = {}, fld;
generator.clearApiErrors();
Wait('start');
$rootScope.flashMessage = null;
Rest.setUrl(defaultUrl + $routeParams.team_id +'/');
var data = {}
for (var fld in form.fields) {
data[fld] = scope[fld];
Rest.setUrl(defaultUrl + $routeParams.team_id + '/');
for (fld in form.fields) {
data[fld] = $scope[fld];
}
Rest.put(data)
.success( function(data, status, headers, config) {
.success(function () {
Wait('stop');
var base = $location.path().replace(/^\//,'').split('/')[0];
(base == 'teams') ? ReturnToCaller() : ReturnToCaller(1);
var base = $location.path().replace(/^\//, '').split('/')[0];
if (base === 'teams') {
ReturnToCaller();
}
else {
ReturnToCaller(1);
}
})
.error( function(data, status, headers, config) {
.error(function (data, status) {
Wait('stop');
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update team: ' + $routeParams.team_id + '. PUT status: ' + status });
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to update team: ' + $routeParams.team_id + '. PUT status: ' + status });
});
};
// Cancel
scope.formReset = function() {
$scope.formReset = function () {
$rootScope.flashMessage = null;
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
$scope[fld] = master[fld];
}
};
// Related set: Add button
scope.add = function(set) {
$scope.add = function (set) {
$rootScope.flashMessage = null;
if (set == 'permissions') {
if (scope.PermissionAddAllowed) {
if (set === 'permissions') {
if ($scope.PermissionAddAllowed) {
$location.path('/' + base + '/' + $routeParams.team_id + '/' + set + '/add');
}
else {
} else {
Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
}
}
else {
} else {
$location.path('/' + base + '/' + $routeParams.team_id + '/' + set);
}
};
// Related set: Edit button
scope.edit = function(set, id, name) {
$scope.edit = function (set, id) {
$rootScope.flashMessage = null;
if (set == 'permissions') {
if (set === 'permissions') {
$location.path('/' + base + '/' + $routeParams.team_id + '/' + set + '/' + id);
}
else {
} else {
$location.path('/' + set + '/' + id);
}
};
// Related set: Delete button
scope['delete'] = function(set, itm_id, name, title) {
$scope['delete'] = function (set, itm_id, name, title) {
$rootScope.flashMessage = null;
var action = function() {
var action = function () {
var url;
if (set == 'permissions') {
if (scope.PermissionAddAllowed) {
if (set === 'permissions') {
if ($scope.PermissionAddAllowed) {
url = GetBasePath('base') + 'permissions/' + itm_id + '/';
Rest.setUrl(url);
Rest.destroy()
.success( function(data, status, headers, config) {
.success(function () {
$('#prompt-modal').modal('hide');
scope.search(form.related[set].iterator);
$scope.search(form.related[set].iterator);
})
.error( function(data, status, headers, config) {
.error(function (data, status) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url +
' failed. DELETE returned status: ' + status });
});
}
else {
} else {
Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
}
}
else {
var url = defaultUrl + $routeParams.team_id + '/' + set + '/';
} else {
url = defaultUrl + $routeParams.team_id + '/' + set + '/';
Rest.setUrl(url);
Rest.post({ id: itm_id, disassociate: 1 })
.success( function(data, status, headers, config) {
.success(function () {
$('#prompt-modal').modal('hide');
scope.search(form.related[set].iterator);
$scope.search(form.related[set].iterator);
})
.error( function(data, status, headers, config) {
.error(function (data, status) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url +
' failed. POST returned status: ' + status });
});
}
};
Prompt({ hdr: 'Delete',
body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?',
Prompt({
hdr: 'Delete',
body: 'Are you sure you want to remove ' + name + ' from ' + $scope.name + ' ' + title + '?',
action: action
});
}
};
}
TeamsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'TeamForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'LookUpInit', 'Prompt',
'GetBasePath', 'CheckAccess', 'OrganizationList', 'Wait', 'Stream'
];
TeamsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'TeamForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit',
'ReturnToCaller', 'ClearScope', 'LookUpInit', 'Prompt', 'GetBasePath', 'CheckAccess', 'OrganizationList', 'Wait', 'Stream'
];

View File

@@ -1,7 +1,6 @@
/************************************
/********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
*
* Users.js
*
* Controller functions for User model.
@@ -10,98 +9,113 @@
'use strict';
function UsersList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, UserList,
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
ClearScope, ProcessErrors, GetBasePath, SelectionInit, Wait, Stream)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
function UsersList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, UserList, GenerateList, LoadBreadCrumbs,
Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, SelectionInit, Wait, Stream) {
var list = UserList;
var defaultUrl = GetBasePath('users');
var view = GenerateList;
var base = $location.path().replace(/^\//,'').split('/')[0];
var mode = (base == 'users') ? 'edit' : 'select'; // if base path 'users', we're here to add/edit users
var scope = view.inject(UserList, { mode: mode }); // Inject our view
scope.selected = [];
ClearScope();
var url = (base == 'organizations') ? GetBasePath('organizations') + $routeParams.organization_id + '/users/' :
var list = UserList,
defaultUrl = GetBasePath('users'),
generator = GenerateList,
base = $location.path().replace(/^\//, '').split('/')[0],
mode = (base === 'users') ? 'edit' : 'select',
url = (base === 'organizations') ? GetBasePath('organizations') + $routeParams.organization_id + '/users/' :
GetBasePath('teams') + $routeParams.team_id + '/users/';
SelectionInit({ scope: scope, list: list, url: url, returnToCaller: 1 });
if (scope.removePostRefresh) {
scope.removePostRefresh();
generator.inject(UserList, { mode: mode, scope: $scope });
$scope.selected = [];
if (mode === 'select') {
SelectionInit({ scope: $scope, list: list, url: url, returnToCaller: 1 });
}
scope.removePostRefresh = scope.$on('PostRefresh', function() {
if ($scope.removePostRefresh) {
$scope.removePostRefresh();
}
$scope.removePostRefresh = $scope.$on('PostRefresh', function () {
// Cleanup after a delete
Wait('stop');
$('#prompt-modal').off();
});
$rootScope.flashMessage = null;
SearchInit({ scope: scope, set: 'users', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
SearchInit({
scope: $scope,
set: 'users',
list: list,
url: defaultUrl
});
PaginateInit({
scope: $scope,
list: list,
url: defaultUrl
});
$scope.search(list.iterator);
LoadBreadCrumbs();
scope.showActivity = function() { Stream({ scope: scope }); }
$scope.showActivity = function () {
Stream({ scope: $scope });
};
scope.addUser = function() {
$scope.addUser = function () {
$location.path($location.path() + '/add');
}
};
scope.editUser = function(id) {
$scope.editUser = function (id) {
$location.path($location.path() + '/' + id);
}
};
scope.deleteUser = function(id, name) {
$scope.deleteUser = function (id, name) {
var action = function() {
$('#prompt-modal').on('hidden.bs.modal', function(){ Wait('start'); });
var action = function () {
$('#prompt-modal').on('hidden.bs.modal', function () {
Wait('start');
});
$('#prompt-modal').modal('hide');
var url = defaultUrl + id + '/';
Rest.setUrl(url);
Rest.destroy()
.success( function(data, status, headers, config) {
scope.search(list.iterator);
.success(function () {
$scope.search(list.iterator);
})
.error( function(data, status, headers, config) {
Wait('stop');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
};
Prompt({ hdr: 'Delete',
Prompt({
hdr: 'Delete',
body: 'Are you sure you want to delete ' + name + '?',
action: action
});
}
};
}
UsersList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'UserList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
'GetBasePath', 'SelectionInit', 'Wait', 'Stream'];
UsersList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'UserList', 'GenerateList',
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors', 'GetBasePath',
'SelectionInit', 'Wait', 'Stream'
];
function UsersAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
GetBasePath, LookUpInit, OrganizationList, ResetForm, Wait)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
function UsersAdd($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm, GenerateForm, Rest, Alert, ProcessErrors,
LoadBreadCrumbs, ReturnToCaller, ClearScope, GetBasePath, LookUpInit, OrganizationList, ResetForm, Wait) {
ClearScope();
// Inject dynamic view
var defaultUrl = GetBasePath('organizations');
var form = UserForm;
ResetForm();
var generator = GenerateForm;
var scope = generator.inject(form, {mode: 'add', related: false});
var defaultUrl = GetBasePath('organizations'),
form = UserForm,
generator = GenerateForm;
scope.ldap_user = false;
scope.not_ldap_user = !scope.ldap_user;
scope.ldap_dn = null;
generator.inject(form, { mode: 'add', related: false, scope: $scope });
ResetForm();
$scope.ldap_user = false;
$scope.not_ldap_user = !$scope.ldap_user;
$scope.ldap_dn = null;
generator.reset();
@@ -110,7 +124,7 @@ function UsersAdd ($scope, $rootScope, $compile, $location, $log, $routeParams,
// Configure the lookup dialog. If we're adding a user through the Organizations tab,
// default the Organization value.
LookUpInit({
scope: scope,
scope: $scope,
form: form,
current_item: ($routeParams.organization_id !== undefined) ? $routeParams.organization_id : null,
list: OrganizationList,
@@ -118,40 +132,37 @@ function UsersAdd ($scope, $rootScope, $compile, $location, $log, $routeParams,
});
if ($routeParams.organization_id) {
scope.organization = $routeParams.organization_id;
$scope.organization = $routeParams.organization_id;
Rest.setUrl(GetBasePath('organizations') + $routeParams.organization_id + '/');
Rest.get()
.success( function(data, status, headers, config) {
scope['organization_name'] = data.name;
.success(function (data) {
$scope.organization_name = data.name;
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to lookup Organization: ' + data.id + '. GET returned status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to lookup Organization: ' + data.id + '. GET returned status: ' + status });
});
}
// Save
scope.formSave = function() {
$scope.formSave = function () {
generator.clearApiErrors();
if (scope.organization !== undefined && scope.organization !== null && scope.organization !== '') {
Rest.setUrl(defaultUrl + scope.organization + '/users/');
var data = {}
for (var fld in form.fields) {
var fld, data = {};
if ($scope.organization !== undefined && $scope.organization !== null && $scope.organization !== '') {
Rest.setUrl(defaultUrl + $scope.organization + '/users/');
for (fld in form.fields) {
if (form.fields[fld].realName) {
data[form.fields[fld].realName] = scope[fld];
}
else {
data[fld] = scope[fld];
data[form.fields[fld].realName] = $scope[fld];
} else {
data[fld] = $scope[fld];
}
}
data.is_superuser = (data.is_superuser == null || data.is_superuser == undefined || data.is_superuser == '') ? false :
data.is_superuser;
data.is_superuser = data.is_superuser || false;
Wait('start');
Rest.post(data)
.success( function(data, status, headers, config) {
var base = $location.path().replace(/^\//,'').split('/')[0];
if (base == 'users') {
.success(function (data) {
var base = $location.path().replace(/^\//, '').split('/')[0];
if (base === 'users') {
$rootScope.flashMessage = 'New user successfully created!';
$location.path('/users/' + data.id);
}
@@ -159,242 +170,250 @@ function UsersAdd ($scope, $rootScope, $compile, $location, $log, $routeParams,
ReturnToCaller(1);
}
})
.error( function(data, status, headers, config) {
Wait('stop');
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to add new user. POST returned status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, form, { hdr: 'Error!', msg: 'Failed to add new user. POST returned status: ' + status });
});
}
else {
scope.organization_name_api_error = 'A value is required';
} else {
$scope.organization_name_api_error = 'A value is required';
}
};
// Cancel
scope.formReset = function() {
$scope.formReset = function () {
// Defaults
generator.reset();
scope.ldap_user = false;
$scope.ldap_user = false;
};
// Password change
scope.clearPWConfirm = function(fld) {
$scope.clearPWConfirm = function (fld) {
// If password value changes, make sure password_confirm must be re-entered
scope[fld] = '';
scope[form.name + '_form'][fld].$setValidity('awpassmatch', false);
}
$scope[fld] = '';
$scope[form.name + '_form'][fld].$setValidity('awpassmatch', false);
};
}
UsersAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'UserForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GetBasePath',
'LookUpInit', 'OrganizationList', 'ResetForm', 'Wait' ];
UsersAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'UserForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GetBasePath', 'LookUpInit',
'OrganizationList', 'ResetForm', 'Wait'
];
function UsersEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
RelatedPaginateInit, ReturnToCaller, ClearScope, GetBasePath, Prompt, CheckAccess,
ResetForm, Wait, Stream)
{
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
//scope.
function UsersEdit($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm, GenerateForm, Rest, Alert,
ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, GetBasePath,
Prompt, CheckAccess, ResetForm, Wait, Stream) {
var defaultUrl=GetBasePath('users');
var generator = GenerateForm;
var form = UserForm;
var base = $location.path().replace(/^\//,'').split('/')[0];
var master = {};
var id = $routeParams.user_id;
var relatedSets = {};
ClearScope();
var defaultUrl = GetBasePath('users'),
generator = GenerateForm,
form = UserForm,
base = $location.path().replace(/^\//, '').split('/')[0],
master = {},
id = $routeParams.user_id,
relatedSets = {};
if ($scope.removeFormReady) {
$scope.removeFormReady();
}
$scope.removeFormReady = $scope.$on('formReady', function() {
var scope = generator.inject(form, {mode: 'edit', related: true});
$scope.removeFormReady = $scope.$on('formReady', function () {
generator.inject(form, { mode: 'edit', related: true, scope: $scope });
generator.reset();
if (scope.removePostRefresh) {
scope.removePostRefresh();
if ($scope.removePostRefresh) {
$scope.removePostRefresh();
}
scope.PermissionAddAllowed = false;
$scope.PermissionAddAllowed = false;
// After the Organization is loaded, retrieve each related set
if (scope.removeUserLoaded) {
scope.removeUserLoaded();
if ($scope.removeUserLoaded) {
$scope.removeUserLoaded();
}
scope.removeUserLoaded = scope.$on('userLoaded', function() {
$scope.removeUserLoaded = $scope.$on('userLoaded', function () {
for (var set in relatedSets) {
scope.search(relatedSets[set].iterator);
$scope.search(relatedSets[set].iterator);
}
CheckAccess({ scope: scope }); //Does the user have access to add/edit Permissions?
CheckAccess({ scope: $scope }); //Does the user have access to add/edit Permissions?
Wait('stop');
});
// Retrieve detail record and prepopulate the form
Rest.setUrl(defaultUrl + ':id/');
Rest.get({ params: {id: id} })
.success( function(data, status, headers, config) {
Rest.get({ params: { id: id } })
.success(function (data) {
LoadBreadCrumbs({ path: '/users/' + id, title: data.username });
for (var fld in form.fields) {
var fld, related, set;
for (fld in form.fields) {
if (data[fld]) {
if (fld == 'is_superuser') {
scope[fld] = (data[fld] == 'true' || data[fld] == true) ? 'true' : 'false';
if (fld === 'is_superuser') {
$scope[fld] = (data[fld] === 'true' || data[fld] === true) ? 'true' : 'false';
} else {
$scope[fld] = data[fld];
}
else {
scope[fld] = data[fld];
}
master[fld] = scope[fld];
master[fld] = $scope[fld];
}
}
var related = data.related;
for (var set in form.related) {
related = data.related;
for (set in form.related) {
if (related[set]) {
relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
relatedSets[set] = {
url: related[set],
iterator: form.related[set].iterator
};
}
}
scope.ldap_user = (data.ldap_dn !== null && data.ldap_dn !== undefined && data.ldap_dn !== '') ? true : false;
scope.not_ldap_user = !scope.ldap_user;
master.ldap_user = scope.ldap_user;
$scope.ldap_user = (data.ldap_dn !== null && data.ldap_dn !== undefined && data.ldap_dn !== '') ? true : false;
$scope.not_ldap_user = !$scope.ldap_user;
master.ldap_user = $scope.ldap_user;
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
scope.$emit('userLoaded');
RelatedSearchInit({
scope: $scope,
form: form,
relatedSets: relatedSets
});
RelatedPaginateInit({
scope: $scope,
relatedSets: relatedSets
});
$scope.$emit('userLoaded');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve user: ' + $routeParams.id + '. GET status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve user: ' +
$routeParams.id + '. GET status: ' + status });
});
// Save changes to the parent
scope.formSave = function() {
$scope.formSave = function () {
var data = {}, fld;
generator.clearApiErrors();
$rootScope.flashMessage = null;
Rest.setUrl(defaultUrl + id + '/');
var data = {}
for (var fld in form.fields) {
for (fld in form.fields) {
if (form.fields[fld].realName) {
data[form.fields[fld].realName] = scope[fld];
}
else {
data[fld] = scope[fld];
data[form.fields[fld].realName] = $scope[fld];
} else {
data[fld] = $scope[fld];
}
}
data.is_superuser = (data.is_superuser == null || data.is_superuser == undefined || data.is_superuser == '') ? false :
data.is_superuser;
data.is_superuser = data.is_superuser || false;
Wait('start');
Rest.put(data)
.success( function(data, status, headers, config) {
.success(function () {
Wait('stop');
var base = $location.path().replace(/^\//,'').split('/')[0];
(base == 'users') ? ReturnToCaller() : ReturnToCaller(1);
var base = $location.path().replace(/^\//, '').split('/')[0];
if (base === 'users') {
ReturnToCaller();
}
else {
ReturnToCaller(1);
}
})
.error( function(data, status, headers, config) {
Wait('stop');
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update users: ' + $routeParams.id + '. PUT status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, form, { hdr: 'Error!', msg: 'Failed to update users: ' + $routeParams.id +
'. PUT status: ' + status });
});
};
scope.showActivity = function() { Stream({ scope: scope }); }
$scope.showActivity = function () {
Stream({ scope: $scope });
};
// Cancel
scope.formReset = function() {
$scope.formReset = function () {
$rootScope.flashMessage = null;
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
$scope[fld] = master[fld];
}
scope['password_confirm'] = scope['password'];
$scope.password_confirm = $scope.password;
};
// Password change
scope.clearPWConfirm = function(fld) {
$scope.clearPWConfirm = function (fld) {
// If password value changes, make sure password_confirm must be re-entered
scope[fld] = '';
scope[form.name + '_form'][fld].$setValidity('awpassmatch', false);
$scope[fld] = '';
$scope[form.name + '_form'][fld].$setValidity('awpassmatch', false);
$rootScope.flashMessage = null;
}
};
// Related set: Add button
scope.add = function(set) {
$scope.add = function (set) {
$rootScope.flashMessage = null;
if (set == 'permissions') {
if (scope.PermissionAddAllowed) {
if (set === 'permissions') {
if ($scope.PermissionAddAllowed) {
$location.path('/' + base + '/' + $routeParams.user_id + '/' + set + '/add');
}
else {
} else {
Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
}
}
else {
} else {
$location.path('/' + base + '/' + $routeParams.user_id + '/' + set);
}
};
// Related set: Edit button
scope.edit = function(set, id, name) {
$scope.edit = function (set, id) {
$rootScope.flashMessage = null;
if (set == 'permissions') {
if (set === 'permissions') {
$location.path('/users/' + $routeParams.user_id + '/permissions/' + id);
}
else {
} else {
$location.path('/' + set + '/' + id);
}
};
// Related set: Delete button
scope['delete'] = function(set, itm_id, name, title) {
$scope['delete'] = function (set, itm_id, name, title) {
$rootScope.flashMessage = null;
var action = function() {
var action = function () {
var url;
if (set == 'permissions') {
if (scope.PermissionAddAllowed) {
if (set === 'permissions') {
if ($scope.PermissionAddAllowed) {
url = GetBasePath('base') + 'permissions/' + itm_id + '/';
Rest.setUrl(url);
Rest.destroy()
.success( function(data, status, headers, config) {
.success(function () {
$('#prompt-modal').modal('hide');
scope.search(form.related[set].iterator);
$scope.search(form.related[set].iterator);
})
.error( function(data, status, headers, config) {
.error(function (data, status) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
}
else {
} else {
Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
}
}
else {
} else {
url = defaultUrl + $routeParams.user_id + '/' + set + '/';
Rest.setUrl(url);
Rest.post({ id: itm_id, disassociate: 1 })
.success( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
scope.search(form.related[set].iterator);
Rest.post({
id: itm_id,
disassociate: 1
})
.error( function(data, status, headers, config) {
.success(function () {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
$scope.search(form.related[set].iterator);
})
.error(function (data, status) {
$('#prompt-modal').modal('hide');
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
});
}
}
};
Prompt({ hdr: 'Delete',
body: 'Are you sure you want to remove ' + name + ' from ' + scope.username + ' ' + title + '?',
Prompt({
hdr: 'Delete',
body: 'Are you sure you want to remove ' + name + ' from ' + $scope.username + ' ' + title + '?',
action: action
});
}
};
}); // $scope.$on
// Put form back to its original state
@@ -404,18 +423,18 @@ function UsersEdit ($scope, $rootScope, $compile, $location, $log, $routeParams,
if ($scope.removeModifyForm) {
$scope.removeModifyForm();
}
$scope.removeModifyForm = $scope.$on('modifyForm', function() {
$scope.removeModifyForm = $scope.$on('modifyForm', function () {
// Modify form based on LDAP settings
Rest.setUrl(GetBasePath('config'));
Rest.get()
.success( function(data, status, headers, config) {
if (data['user_ldap_fields']) {
var fld;
for (var i=0; i < data['user_ldap_fields'].length; i++) {
fld = data['user_ldap_fields'][i];
.success(function (data) {
var i, fld;
if (data.user_ldap_fields) {
for (i = 0; i < data.user_ldap_fields.length; i++) {
fld = data.user_ldap_fields[i];
if (form.fields[fld]) {
form.fields[fld]['readonly'] = true;
form.fields[fld]['editRequired'] = false;
form.fields[fld].readonly = true;
form.fields[fld].editRequired = false;
if (form.fields[fld].awRequiredWhen) {
delete form.fields[fld].awRequiredWhen;
}
@@ -424,32 +443,30 @@ function UsersEdit ($scope, $rootScope, $compile, $location, $log, $routeParams,
}
$scope.$emit('formReady');
})
.error( function(data, status, headers, config) {
ProcessErrors($scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to retrieve application config. GET status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve application config. GET status: ' + status });
});
});
Wait('start');
Rest.setUrl(defaultUrl + id + '/');
Rest.get()
.success( function(data, status, headers, config) {
.success(function (data) {
if (data.ldap_dn !== null && data.ldap_dn !== undefined && data.ldap_dn !== '') {
//this is an LDAP user
$scope.$emit('modifyForm');
}
else {
} else {
$scope.$emit('formReady');
}
})
.error( function(data, status, headers, config) {
ProcessErrors($scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to retrieve user: ' + id + '. GET status: ' + status });
.error(function (data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve user: ' + id + '. GET status: ' + status });
});
}
UsersEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'UserForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'GetBasePath', 'Prompt', 'CheckAccess',
'ResetForm', 'Wait', 'Stream'];
UsersEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'UserForm', 'GenerateForm',
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope',
'GetBasePath', 'Prompt', 'CheckAccess', 'ResetForm', 'Wait', 'Stream'
];

View File

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

View File

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

View File

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

View File

@@ -7,13 +7,12 @@
*
*/
angular.module('HostFormDefinition', [])
.value(
'HostForm', {
.value('HostForm', {
addTitle: 'Create Host', //Legend in add mode
editTitle: '{{ name }}', //Legend in edit mode
name: 'host', //Form name attribute
well: false, //Wrap the form with TB well
addTitle: 'Create Host',
editTitle: '{{ name }}',
name: 'host',
well: false,
formLabelSize: 'col-lg-3',
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', [])
.value(
'InventoryForm', {
.value('InventoryForm', {
addTitle: 'Create Inventory',
editTitle: '{{ inventory_name | capitalize }}',
@@ -49,7 +48,10 @@ angular.module('InventoryFormDefinition', [])
sourceModel: 'organization',
sourceField: 'name',
ngClick: 'lookUpOrganization()',
awRequiredWhen: {variable: "organizationrequired", init: "true" }
awRequiredWhen: {
variable: "organizationrequired",
init: "true"
}
},
inventory_variables: {
realName: 'variables',
@@ -74,14 +76,14 @@ angular.module('InventoryFormDefinition', [])
}
},
buttons: { //for now always generates <button> tags
buttons: {
save: {
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
ngClick: 'formSave()',
ngDisabled: true
},
reset: {
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

@@ -2,13 +2,12 @@
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* InventoryStatus.js
* Form definition for Inventory Status -JSON view
*
* Use to show inventory sync status
*
*/
angular.module('InventoryStatusDefinition', [])
.value(
'InventoryStatusForm', {
.value('InventoryStatusForm', {
name: 'inventory_update',
editTitle: 'Inventory Status',

View File

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

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', [])
.value(
'JobSummary', {
.value('JobSummary', {
editTitle: '{{ id }} - {{ name }}',
name: 'jobs',
@@ -46,5 +45,4 @@ angular.module('JobSummaryDefinition', [])
ngShow: 'result_traceback != ""'
}
}
});

View File

@@ -7,14 +7,18 @@
*
*/
angular.module('JobTemplateFormDefinition', [])
.value(
'JobTemplateForm', {
.value('JobTemplateForm', {
addTitle: 'Create Job Templates', //Legend in add mode
editTitle: '{{ name }}', //Legend in edit mode
addTitle: 'Create Job Templates',
editTitle: '{{ name }}',
name: 'job_templates',
twoColumns: true,
well: true,
base: 'job_templates',
collapse: true,
collapseTitle: "Properties",
collapseMode: 'edit',
collapseOpenFirst: true, //Always open first panel
actions: {
stream: {
@@ -153,7 +157,7 @@ angular.module('JobTemplateFormDefinition', [])
column: 1,
awPopOver: "<p>Provide a host pattern to further constrain the list of hosts that will be managed or affected by the playbook. " +
"Multiple patterns can be separated by &#59; &#58; or &#44;</p><p>For more information and examples see " +
"<a href=\"http://docs.ansible.com/intro_patterns.html\" target=\"_blank\">the Patters top at docs.ansible.com</a>.</p>",
"<a href=\"http://docs.ansible.com/intro_patterns.html\" target=\"_blank\">the Patters topic at docs.ansible.com</a>.</p>",
dataTitle: 'Limit',
dataPlacement: 'right',
dataContainer: "body"
@@ -203,8 +207,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. " +
"Suppose the actions have been assigned tag values of &quot;configuration&quot;, &quot;packages&quot; and &quot;install&quot;.</p>" +
"<p>If you just want to run the &quot;configuration&quot; and &quot;packages&quot; actions, you would enter the following here " +
"in the Job Tags field:<\p>\n" +
"<blockquote>configuration,packages</blockquote>\n",
"in the Job Tags field:</p>\n<blockquote>configuration,packages</blockquote>\n",
dataTitle: "Job Tags",
dataPlacement: "right",
dataContainer: "body"
@@ -277,7 +280,7 @@ angular.module('JobTemplateFormDefinition', [])
}
},
related: { //related colletions (and maybe items?)
related: {
jobs: {
type: 'collection',
@@ -312,9 +315,9 @@ angular.module('JobTemplateFormDefinition', [])
},
status: {
label: 'Status',
"class": 'job-\{\{ job.status \}\}',
"class": 'job-{{ job.status }}',
searchType: 'select',
linkTo: "\{\{ job.statusLinkTo \}\}",
linkTo: "{{}} job.statusLinkTo }}",
searchOptions: [
{ name: "new", value: "new" },
{ name: "waiting", value: "waiting" },
@@ -323,13 +326,14 @@ angular.module('JobTemplateFormDefinition', [])
{ name: "successful", value: "successful" },
{ name: "error", value: "error" },
{ name: "failed", value: "failed" },
{ name: "canceled", value: "canceled" } ],
badgeIcon: 'fa icon-job-\{\{ job.status \}\}',
{ name: "canceled", value: "canceled" }
],
badgeIcon: 'fa icon-job-{{ job.status }}',
badgePlacement: 'left',
badgeToolTip: "\{\{ job.statusBadgeToolTip \}\}",
badgeToolTip: "{{ job.statusBadgeToolTip }}",
badgeTipPlacement: 'top',
badgeNgHref: "\{\{ job.statusLinkTo \}\}",
awToolTip: "\{\{ job.statusBadgeToolTip \}\}",
badgeNgHref: "{{ job.statusLinkTo }}",
awToolTip: "{{ job.statusBadgeToolTip }}",
dataPlacement: 'top'
}
},
@@ -337,7 +341,7 @@ angular.module('JobTemplateFormDefinition', [])
fieldActions: {
edit: {
label: 'View',
ngClick: "edit('jobs', \{\{ job.id \}\}, '\{\{ job.name \}\}')",
ngClick: "edit('jobs', job.id, job.name)",
icon: 'icon-zoom-in'
}
}

View File

@@ -7,17 +7,17 @@
* @dict
*/
angular.module('JobFormDefinition', [])
.value(
'JobForm', {
.value('JobForm', {
addTitle: 'Create Job',
editTitle: '{{ id }} - {{ name }}',
name: 'jobs',
well: true,
base: 'jobs',
collapse: true,
collapseMode: 'edit',
collapseTitle: 'Job Template',
twoColumns: true,
collapseTitle: 'Job Status',
collapseOpenFirst: true, //Always open first panel
navigationLinks: {
details: {
@@ -40,269 +40,10 @@ angular.module('JobFormDefinition', [])
},
fields: {
name: {
label: 'Job Template',
type: 'text',
addRequired: false,
editRequired: false,
readonly: true,
column: 1
},
description: {
label: 'Description',
type: 'text',
addRequired: false,
editRequired: false,
column: 1
},
job_type: {
label: 'Job Type',
type: 'select',
ngOptions: 'type.label for type in job_type_options',
"default": 'run',
addRequired: true,
editRequired: true,
awPopOver: "<p>When this template is submitted as a job, setting the type to <em>run</em> will execute the playbook, running tasks " +
" on the selected hosts.</p> <p>Setting the type to <em>check</em> will not execute the playbook. Instead, ansible will check playbook " +
" syntax, test environment setup and report problems.</p>",
dataTitle: 'Job Type',
dataPlacement: 'right',
dataContainer: 'body',
column: 1
},
inventory: {
label: 'Inventory',
type: 'lookup',
sourceModel: 'inventory',
sourceField: 'name',
addRequired: true,
editRequired: true,
ngClick: 'lookUpInventory()',
column: 1,
awPopOver: "<p>Select the inventory containing the hosts you want this job to manage.</p>",
dataTitle: 'Inventory',
dataPlacement: 'right',
dataContainer: "body"
},
project: {
label: 'Project',
type: 'lookup',
sourceModel: 'project',
sourceField: 'name',
addRequired: true,
editRequired: true,
ngClick: 'lookUpProject()',
column: 1,
awPopOver: "<p>Select the project containing the playbook you want this job to execute.</p>",
dataTitle: 'Project',
dataPlacement: 'right',
dataContainer: "body"
},
playbook: {
label: 'Playbook',
type:'select',
ngOptions: 'book for book in playbook_options',
id: 'playbook-select',
addRequired: true,
editRequired: true,
column: 1,
awPopOver: "<p>Select the playbook to be executed by this job.</p>",
dataTitle: 'Playbook',
dataPlacement: 'right',
dataContainer: "body"
},
credential: { // FIXME: Lookup only credentials with kind=ssh
label: 'Credential',
type: 'lookup',
sourceModel: 'credential',
sourceField: 'name',
ngClick: 'lookUpCredential()',
addRequired: false,
editRequired: false,
column: 1,
awPopOver: "<p>Select the credential you want the job to use when accessing the remote hosts. Choose the credential containing " +
" the username and SSH key or password that Ansbile will need to log into the remote hosts.</p>",
dataTitle: 'Credential',
dataPlacement: 'right',
dataContainer: "body"
},
cloud_credential: { // FIXME: Lookup only credentials with kind=aws/rax
label: 'Cloud Credential',
type: 'lookup',
sourceModel: 'cloud_credential',
sourceField: 'name',
ngClick: 'lookUpCredential()',
addRequired: false,
editRequired: false,
column: 1,
awPopOver: "<p>Selecting an optional cloud credential in the job template will pass along the access credentials to the " +
"running playbook, allowing provisioning into the cloud without manually passing parameters to the included modules.</p>",
dataTitle: 'Cloud Credential',
dataPlacement: 'right',
dataContainer: "body"
},
forks: {
label: 'Forks',
id: 'forks-number',
type: 'number',
integer: true,
min: 0,
spinner: true,
"class": 'input-small',
"default": '0',
addRequired: false,
editRequired: false,
column: 1,
disabled: true,
awPopOver: "<p>The number of parallel or simultaneous processes to use while executing the playbook.</p>",
dataContainer: 'body',
dataTitle: 'Forks',
dataPlacement: 'right'
},
limit: {
label: 'Limit',
type: 'text',
addRequired: false,
editRequired: false,
column: 1,
awPopOver: "<p>Provide a host pattern to further constrain the list of hosts that will be managed or affected by the playbook. " +
"Multiple patterns can be separated by &#59; &#58; or &#44;</p><p>For more information and examples see the " +
"<a href=\"http://ansible.cc/docs/patterns.html#selecting-targets\" target=\"_blank\">Selecting Targets section</a> under Inventory and Patterns " +
" in the Ansible documentation.</p>",
dataContainer: 'body',
dataTitle: 'Limit',
dataPlacement: 'right'
},
verbosity: {
label: 'Verbosity',
type: 'select',
ngOptions: 'v.label for v in verbosity_options',
"default": 0,
addRequired: true,
editRequired: true,
column: 1,
awPopOver: "<p>Control the level of output ansible will produce as the playbook executes.</p>",
dataTitle: 'Verbosity',
dataPlacement: 'right',
dataContainer: 'body'
},
variables: {
label: 'Extra Variables',
type: 'textarea',
rows: 6,
"class": 'span12',
addRequired: false,
editRequired: false,
column: 2,
awPopOver: "<p>Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter " +
"for ansible-playbook. Provide key/value pairs using either YAML or JSON.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n",
dataTitle: 'Extra Variables',
dataContainer: 'body',
dataPlacement: 'right'
},
job_tags: {
label: 'Job Tags',
type: 'textarea',
rows: 1,
addRequired: false,
editRequired: false,
'class': 'span12',
column: 2,
awPopOver: "<p>Provide a comma separated list of tags.</p>\n" +
"<p>Tags are useful when you have a large playbook, and you want to run a specific part of a play or task.</p>" +
"<p>For example, you might have a task consisiting of a long list of actions. Tag values can be assigned to each action. " +
"Suppose the actions have been assigned tag values of &quot;configuration&quot;, &quot;packages&quot; and &quot;install&quot;.</p>" +
"<p>If you just want to run the &quot;configuration&quot; and &quot;packages&quot; actions, you would enter the following here " +
"in the Job Tags field:<\p>\n" +
"<blockquote>configuration,packages</blockquote>\n",
dataTitle: "Job Tags",
dataContainer: 'body',
dataPlacement: "right"
},
allow_callbacks: {
label: 'Allow Callbacks',
type: 'checkbox',
addRequired: false,
editRequird: false,
trueValue: 'true',
falseValue: 'false',
ngChange: "toggleCallback('host_config_key')",
"class": "span12",
column: 2,
awPopOver: "<p>Create a callback URL a host can use to contact Tower and request a configuration update " +
"using the job template. The URL will look like the following:</p>\n" +
"<p class=\"code-breakable\">http://your.server.com:999/api/v1/job_templates/1/callback/</p>" +
"<p>The request from the host must be a POST. Here is an example using curl:</p>\n" +
"<p class=\"code-breakable\">curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
"http://your.server.com:999/api/v1/job_templates/1/callback/</p>\n" +
"<p>Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address " +
"in one of your defined inventories, the request will be denied.</p>" +
"<p>Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.</p>",
dataPlacement: 'right',
dataContainer: 'body',
dataTitle: 'Callback URL'
},
callback_url: {
label: 'Callback URL',
type: 'text',
addRequired: false,
editRequired: false,
readonly: true,
column: 2,
required: false,
'class': 'span12',
awPopOver: "<p>Using this URL a host can contact Tower and request a configuration update using the job " +
"template. The request from the host must be a POST. Here is an example using curl:</p>\n" +
"<p class=\"code-breakable\">curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
"http://your.server.com:999/api/v1/job_templates/1/callback/</p>\n" +
"<p>Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address " +
"in one of your defined inventories, the request will be denied.</p>" +
"<p>Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.</p>",
dataPlacement: 'right',
dataContainer: 'body',
dataTitle: 'Callback URL'
},
host_config_key: {
label: 'Host Config Key',
type: 'text',
ngShow: "allow_callbacks",
genMD5: true,
column: 2,
awPopOver: "<p>When contacting Tower using the callback URL, the calling host must authenticate by including " +
"this key in the POST data of the request. Here's an example using curl:</p>\n" +
"<p class=\"code-breakable\">curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
"http://your.server.com:999/api/v1/job_templates/1/callback/</p>\n",
dataPlacement: 'right',
dataContainer: 'body'
}
},
buttons: { //for now always generates <button> tags
save: {
label: 'Save',
icon: 'icon-ok',
"class": 'btn-success',
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
},
reset: {
ngClick: 'formReset()',
label: 'Reset',
icon: 'icon-undo',
'class': 'btn btn-default',
ngDisabled: true //Disabled when $pristine
}
},
statusFields: {
status: {
//label: 'Job Status',
type: 'custom',
control: '<div class=\"job-detail-status\"><span style="padding-right: 15px; font-weight: bold;">Status</span> <i class=\"fa icon-job-\{\{ status \}\}\"></i> \{\{ status \}\}</div>',
control: "<div class=\"job-detail-status\"><span style=\"padding-right: 15px; font-weight: bold;\">Status</span> " +
"<i class=\"fa icon-job-{{ status }}\"></i> {{ status }}</div>",
readonly: true
},
created: {
@@ -315,7 +56,7 @@ angular.module('JobFormDefinition', [])
type: 'textarea',
readonly: true,
xtraWide: true,
rows: "\{\{ stdout_rows \}\}",
rows: "{{ stdout_rows }}",
"class": 'nowrap mono-space',
ngShow: "result_stdout != ''"
},
@@ -324,13 +65,13 @@ angular.module('JobFormDefinition', [])
type: 'textarea',
xtraWide: true,
readonly: true,
rows: "\{\{ traceback_rows \}\}",
rows: "{{ traceback_rows }}",
"class": 'nowrap mono-space',
ngShow: "result_traceback != ''"
}
},
statusActions: {
actions: {
refresh: {
dataPlacement: 'top',
icon: "icon-refresh",
@@ -341,7 +82,17 @@ angular.module('JobFormDefinition', [])
awToolTip: "Refresh the page",
ngClick: "refresh()"
}
},
related: {
job_template: {
type: 'collection',
title: 'Job Tempate',
iterator: 'job',
index: false,
open: false,
fields: { }
}
}); //Form
}
});

View File

@@ -0,0 +1,94 @@
/*********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* LicenseForm.js
*
*
*/
'use strict';
angular.module('LicenseFormDefinition', [])
.value('LicenseForm', {
name: 'license',
well: false,
tabs: [{
name: 'license',
label: 'License'
}, {
name: 'managed',
label: 'Managed Hosts'
},{
name: 'contact',
label: 'Contact Info'
}],
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,
tab: 'license'
},
license_key: {
label: 'Key',
type: 'textarea',
'class': 'modal-input-xlarge',
readonly: true,
tab: 'license'
},
license_date: {
label: 'Expires On',
type: 'text',
readonly: true,
tab: 'license'
},
time_remaining: {
label: 'Time Left',
type: 'text',
readonly: true,
tab: 'license'
},
available_instances: {
label: 'Available',
type: 'text',
readonly: true,
tab: 'managed'
},
current_instances: {
label: 'Used',
type: 'text',
readonly: true,
tab: 'managed'
},
free_instances: {
label: 'Remaining',
type: 'text',
readonly: true,
controlNGClass: 'free_instances_class',
labelNGClass: 'free_instances_class',
tab: 'managed'
},
company_name: {
label: 'Company',
type: 'text',
readonly: true,
tab: 'contact'
},
contact_name: {
label: 'Contact',
type: 'text',
readonly: true,
tab: 'contact'
},
contact_email: {
label: 'Contact Email',
type: 'text',
readonly: true,
tab: 'contact'
}
}
});

View File

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

View File

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

View File

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

View File

@@ -8,14 +8,17 @@
*
*/
angular.module('ProjectFormDefinition', [])
.value(
'ProjectsForm', {
.value('ProjectsForm', {
addTitle: 'Create Project', // Title in add mode
editTitle: '{{ name }}', // Title in edit mode
name: 'project', // entity or model name in singular form
well: true, // Wrap the form with TB well
addTitle: 'Create Project',
editTitle: '{{ name }}',
name: 'project',
forceListeners: true,
well: true,
collapse: true,
collapseTitle: "Properties",
collapseMode: 'edit',
collapseOpen: true,
actions: {
stream: {
@@ -52,7 +55,10 @@ angular.module('ProjectFormDefinition', [])
editRequired: false,
excludeMode: 'edit',
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 ' +
'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 ' +
@@ -99,7 +105,10 @@ angular.module('ProjectFormDefinition', [])
type: 'select',
id: 'local-path-select',
ngOptions: 'path.label for path in project_local_paths',
awRequiredWhen: { variable: "pathRequired", init: false },
awRequiredWhen: {
variable: "pathRequired",
init: false
},
ngShow: "scm_type.value == '' && !showMissingPlaybooksAlert",
awPopOver: '<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>' +
@@ -112,29 +121,34 @@ angular.module('ProjectFormDefinition', [])
label: 'SCM URL',
type: 'text',
ngShow: "scm_type && scm_type.value !== ''",
awRequiredWhen: { variable: "scmRequired", init: false },
helpCollapse: [
{ hdr: 'GIT URLs',
awRequiredWhen: {
variable: "scmRequired",
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>' +
'<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, ' +
'do not enter a username (other than git). Additionally, GitHub and Bitbucket do not support password authentication when using ' +
'SSH protocol. GIT read only protocol (git://) does not use username or password information.',
show: "scm_type.value == 'git'" },
{ hdr: 'SVN URLs',
show: "scm_type.value == 'git'"
}, {
hdr: 'SVN URLs',
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>' +
'<li>svn+ssh://servername.example.com/path</li></ul>',
show: "scm_type.value == 'svn'" },
{ hdr: 'Mercurial URLs',
show: "scm_type.value == 'svn'"
}, {
hdr: 'Mercurial URLs',
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>' +
'<li>ssh://server.example.com/path</li></ul>' +
'<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 using Bitbucket and SSH, do not supply your Bitbucket username.',
show: "scm_type.value == 'hg'" }
]
show: "scm_type.value == 'hg'"
}]
},
scm_branch: {
labelBind: "scmBranchLabel",
@@ -157,8 +171,7 @@ angular.module('ProjectFormDefinition', [])
label: 'SCM Update Options',
type: 'checkbox_group',
ngShow: "scm_type && scm_type.value !== ''",
fields: [
{
fields: [{
name: 'scm_clean',
label: 'Clean',
type: 'checkbox',
@@ -169,8 +182,7 @@ angular.module('ProjectFormDefinition', [])
dataContainer: 'body',
dataPlacement: 'right',
labelClass: 'checkbox-options'
},
{
}, {
name: 'scm_delete_on_update',
label: 'Delete on Update',
type: 'checkbox',
@@ -182,8 +194,7 @@ angular.module('ProjectFormDefinition', [])
dataContainer: 'body',
dataPlacement: 'right',
labelClass: 'checkbox-options'
},
{
}, {
name: 'scm_update_on_launch',
label: 'Update on Launch',
type: 'checkbox',
@@ -194,23 +205,22 @@ angular.module('ProjectFormDefinition', [])
dataContainer: 'body',
dataPlacement: 'right',
labelClass: 'checkbox-options'
}
]
}]
}
},
buttons: { //for now always generates <button> tags
buttons: {
save: {
ngClick: 'formSave()', //$scope.function to call on click, optional
ngDisabled: true //Disable when $pristine or $invalid, optional
ngClick: 'formSave()',
ngDisabled: true
},
reset: {
ngClick: 'formReset()',
ngDisabled: true //Disabled when $pristine
ngDisabled: true
}
},
related: { //related colletions (and maybe items?)
related: {
organizations: {
type: 'collection',
title: 'Organizations',
@@ -239,14 +249,14 @@ angular.module('ProjectFormDefinition', [])
fieldActions: {
edit: {
label: 'Edit',
ngClick: "edit('organizations', \{\{ organization.id \}\}, '\{\{ organization.name \}\}')",
ngClick: "edit('organizations', organization.id, organization.name)",
icon: 'icon-edit',
awToolTip: 'Edit the organization',
'class': 'btn btn-default'
},
"delete": {
label: 'Delete',
ngClick: "delete('organizations', \{\{ organization.id \}\}, '\{\{ organization.name \}\}', 'organizations')",
ngClick: "delete('organizations', organization.id, organization.name, 'organizations')",
icon: 'icon-trash',
"class": 'btn-danger',
awToolTip: 'Delete the organization'
@@ -256,5 +266,3 @@ angular.module('ProjectFormDefinition', [])
}
}); // Form

View File

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

View File

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

View File

@@ -8,58 +8,79 @@
* @dict
*/
'use strict';
angular.module('InventoryGroupsHelpDefinition', [])
.value(
'InventoryGroupsHelp', {
.value('InventoryGroupsHelp', {
story: {
hdr: 'Building your inventory',
width: 510,
height: 560,
steps: [
{
steps: [{
intro: 'Start by creating a group:',
img: { src: 'groups001.png', maxWidth: 338 , maxHeight: 222 },
img: {
src: 'groups001.png',
maxWidth: 338,
maxHeight: 222
},
box: "Click <i class=\"fa fa-plus\"></i> on the groups list (the left side of the page) to add a new group.",
autoOffNotice: true
},
{
}, {
intro: 'Enter group properties:',
img: { src: 'groups002.png', maxWidth: 443, maxHeight: 251 },
img: {
src: 'groups002.png',
maxWidth: 443,
maxHeight: 251
},
box: 'Enter the group name, a description and any inventory variables. Variables can be entered using either JSON or YAML syntax. ' +
'For more on inventory variables, see <a href=\"http://docs.ansible.com/intro_inventory.html\" target="_blank"> ' +
'docs.ansible.com/intro_inventory.html</a>'
},
{
}, {
intro: 'Cloud inventory: select cloud source',
img: { src: 'groups003.png', maxWidth: 412, maxHeight: 215 },
img: {
src: 'groups003.png',
maxWidth: 412,
maxHeight: 215
},
box: "For a cloud inventory, choose the cloud provider from the list and select your credentials. If you have not already setup " +
"credentials for the provider, you will need to do that first on the <a href=\"/#/credentials\" " +
"target=\"_blank\">Credentials</a> tab."
},
{
}, {
intro: 'Cloud inventory: synchronize Tower with the cloud',
img: { 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>."
img: {
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:",
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 " +
"will be added to the selected group.</div>"
},
{
}, {
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 " +
"asking if the group should be coppied or moved.</div>"
},
{
}, {
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. " +
"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>"
}
]
}]
}
});

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'])
.factory('CheckAccess', ['$rootScope', 'Alert', 'Rest', 'GetBasePath','ProcessErrors',
function($rootScope, Alert, Rest, GetBasePath, ProcessErrors) {
return function(params) {
.factory('CheckAccess', ['$rootScope', 'Alert', 'Rest', 'GetBasePath', 'ProcessErrors',
function ($rootScope, Alert, Rest, GetBasePath, ProcessErrors) {
return function (params) {
// set PermissionAddAllowed to true or false based on user access. admins and org admins are granted
// accesss.
var me = $rootScope.current_user;
var scope = params.scope;
var me = $rootScope.current_user,
scope = params.scope;
if (me.is_superuser) {
scope.PermissionAddAllowed = true;
}
else {
} else {
if (me.related.admin_of_organizations) {
Rest.setUrl(me.related.admin_of_organizations);
Rest.get()
.success( function(data, status, headers, config) {
.success(function (data) {
if (data.results.length > 0) {
scope.PermissionAddAllowed = true;
}
else {
} else {
scope.PermissionAddAllowed = false;
}
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + me.related.admin_of_organizations +
' failed. DELETE returned status: ' + status });
.error(function (data, status) {
ProcessErrors(scope, data, status, null, {
hdr: 'Error!',
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.');
//}
//return access;
};
}
}])
])
.factory('CheckLicense', ['$rootScope', '$cookieStore', 'Alert', '$location', 'Authorization',
function($rootScope, $cookieStore, Alert, $location, Authorization) {
return function() {
.factory('CheckLicense', ['$rootScope', 'Store', 'Alert', '$location', 'Authorization',
function ($rootScope, Store, Alert, $location, Authorization) {
return function () {
// Check license status and alert the user, if needed
var status = 'success';
var hdr, msg;
var license = $cookieStore.get('license');
var purchase_msg = '<p>To purchase a license or extend an existing license ' +
var status = 'success',
hdr, msg,
license = Store('license'),
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>, ' +
'or visit <strong><a href="https://support.ansible.com" target="_blank">support.ansible.com</a></strong> for assistance.</p>';
if (license && !Authorization.licenseTested()) {
// This is our first time evaluating the license
license['tested'] = true;
$cookieStore.remove('license');
$cookieStore.put('license', license);
license.tested = true;
Store('license',license); //update with tested flag
$rootScope.license_tested = true;
if (license['valid_key'] !== undefined && license['valid_key'] == false) {
$rootScope.version = license.version;
if (license.valid_key !== undefined && license.valid_key === false) {
// The license is invalid. Stop the user from logging in.
status = 'alert-danger';
hdr = 'License Error';
msg = '<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;
Alert(hdr, msg, status, null, false, true);
}
else if (license['demo'] !== undefined && license['demo'] == true) {
} else if (license.demo !== undefined && license.demo === true) {
// demo
status = 'alert-info';
hdr = 'Tower Demo';
@@ -79,21 +80,20 @@ angular.module('AccessHelper', ['RestServices', 'Utilities', 'ngCookies'])
purchase_msg;
Alert(hdr, msg, status);
}
if (license['date_expired'] !== undefined && license['date_expired'] == true) {
if (license.date_expired !== undefined && license.date_expired === true) {
// expired
status = 'alert-info';
hdr = 'License Expired';
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;
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';
hdr = 'License Warning';
msg = '<p>Your Ansible Tower license is about to expire!</p>' + purchase_msg;
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';
hdr = 'License Warning';
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);
}
}
};
}
}]);
]);

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,8 @@
/* jshint loopfunc: true */
'use strict';
angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'HostListDefinition',
'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'AuthService', 'HostsHelper',
'InventoryHelper', 'RelatedSearchHelper', 'InventoryFormDefinition', 'SelectionHelper',
@@ -334,8 +336,9 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
scope.formModalActionLabel = 'Save';
scope.formModalHeader = 'Create New Host';
scope.formModalCancelShow = true;
scope.parseType = 'yaml';
ParseTypeChange(scope);
ParseTypeChange({ scope: scope, field_id: 'host_variables' });
if (scope.removeHostsReload) {
scope.removeHostsReload();
@@ -464,7 +467,15 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
scope.formModalHeader = 'Host Properties';
scope.formModalCancelShow = true;
scope.parseType = 'yaml';
ParseTypeChange(scope);
if (scope.hostVariablesLoadedRemove) {
scope.hostVariablesLoadedRemove();
}
scope.hostVariablesLoadedRemove = scope.$on('hostVariablesLoaded', function() {
var callback = function() { Wait('stop'); };
$('#form-modal').modal('show');
ParseTypeChange({ scope: scope, field_id: 'host_variables', onReady: callback });
});
if (scope.hostLoadedRemove) {
scope.hostLoadedRemove();
@@ -481,8 +492,7 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
else {
scope.variables = jsyaml.safeDump(data);
}
Wait('stop');
$('#form-modal').modal('show');
scope.$emit('hostVariablesLoaded');
})
.error( function(data, status) {
scope.variables = null;
@@ -492,8 +502,7 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
}
else {
scope.variables = "---";
Wait('stop');
$('#form-modal').modal('show');
scope.$emit('hostVariablesLoaded');
}
master.variables = scope.variables;
});
@@ -541,7 +550,7 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
// Update any titles attributes created by ApplyEllipsis
if (old_name) {
setTimeout(function() {
$('#hosts_table .host-name a[title="' + old_name + '"').attr('title', host.name);
$('#hosts_table .host-name a[title="' + old_name + '"]').attr('title', host.name);
ApplyEllipsis('#hosts_table .host-name a');
// Close modal
Wait('stop');

View File

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

View File

@@ -7,10 +7,13 @@
*
*/
'use strict';
angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinition', 'InventoryHelper'])
.factory('JobStatusToolTip', [ function() {
return function(status) {
.factory('JobStatusToolTip', [
function () {
return function (status) {
var toolTip;
switch (status) {
case 'successful':
@@ -38,43 +41,40 @@ angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinitio
}
return toolTip;
};
}])
}
])
.factory('ShowJobSummary', ['Rest', 'Wait', 'GetBasePath', 'FormatDate', 'ProcessErrors', 'GenerateForm', 'JobSummary',
.factory('ShowJobSummary', ['Rest', 'Wait', 'GetBasePath', 'FormatDate', 'ProcessErrors', 'GenerateForm', 'JobSummary',
'WatchInventoryWindowResize',
function(Rest, Wait, GetBasePath, FormatDate, ProcessErrors, GenerateForm, JobSummary, WatchInventoryWindowResize) {
return function(params) {
function (Rest, Wait, GetBasePath, FormatDate, ProcessErrors, GenerateForm, JobSummary, WatchInventoryWindowResize) {
return function (params) {
// Display status info in a modal dialog- called from inventory edit page
var job_id = params.job_id;
var job_id = params.job_id,
generator = GenerateForm,
form = JobSummary,
scope, ww, wh, x, y, maxrows, url, html;
var generator = GenerateForm;
var form = JobSummary;
// Using jquery dialog for its expandable property
var html = '<div id=\"status-modal-dialog\" title=\"Job ' + job_id + '\">' +
html = '<div id=\"status-modal-dialog\" title=\"Job ' + job_id + '\">' +
'<div id=\"form-container\" style=\"width: 100%;\"></div></div>\n';
$('#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
var ww = $(document).width();
var wh = $('body').height();
var x, y, maxrows;
ww = $(document).width();
wh = $('body').height();
if (ww > 1199) {
// desktop
x = 675;
y = (750 > wh) ? wh - 20 : 750;
maxrows = 20;
}
else if (ww <= 1199 && ww >= 768) {
} else if (ww <= 1199 && ww >= 768) {
x = 550;
y = (620 > wh) ? wh - 15 : 620;
maxrows = 15;
}
else {
} else {
x = (ww - 20);
y = (500 > wh) ? wh : 500;
maxrows = 10;
@@ -82,7 +82,11 @@ angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinitio
// Create the modal
$('#status-modal-dialog').dialog({
buttons: { 'OK': function() { $( this ).dialog( 'close' ); } },
buttons: {
'OK': function () {
$(this).dialog('close');
}
},
modal: true,
width: x,
height: y,
@@ -90,24 +94,28 @@ angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinitio
create: function () {
// fix the close 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
$('.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%
var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]');
var content = dialog.find('#status-modal-dialog');
content.width( dialog.width() - 28 );
var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]'),
content = dialog.find('#status-modal-dialog');
content.width(dialog.width() - 28);
},
close: function() {
close: function () {
// Destroy on close
$('.tooltip').each( function() {
$('.tooltip').each(function () {
// Remove any lingering tooltip <div> elements
$(this).remove();
});
$('.popover').each(function() {
$('.popover').each(function () {
// remove lingering popover <div> elements
$(this).remove();
});
@@ -115,22 +123,23 @@ angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinitio
$('#inventory-modal-container').empty();
WatchInventoryWindowResize();
},
open: function() {
open: function () {
Wait('stop');
}
});
function calcRows (content) {
var n = content.match(/\n/g);
var rows = (n) ? n.length : 1;
function calcRows(content) {
var n = content.match(/\n/g),
rows = (n) ? n.length : 1;
return (rows > maxrows) ? 20 : rows;
}
Wait('start');
var url = GetBasePath('jobs') + job_id + '/';
url = GetBasePath('jobs') + job_id + '/';
Rest.setUrl(url);
Rest.get()
.success( function(data) {
.success(function (data) {
var cDate;
scope.id = data.id;
scope.name = data.name;
scope.status = data.status;
@@ -138,15 +147,15 @@ angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinitio
scope.result_traceback = data.result_traceback;
scope.stdout_rows = calcRows(scope.result_stdout);
scope.traceback_rows = calcRows(scope.result_traceback);
var cDate = new Date(data.created);
cDate = new Date(data.created);
scope.created = FormatDate(cDate);
$('#status-modal-dialog').dialog('open');
})
.error( function(data, status) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Attempt to load job failed. GET returned status: ' + status });
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Attempt to load job failed. GET returned status: ' + status });
});
};
}]);
}
]);

View File

@@ -21,11 +21,11 @@ angular.module('LookUpHelper', ['RestServices', 'Utilities', 'SearchHelper', 'Pa
function (Alert, Rest, GenerateList, SearchInit, PaginateInit, GetBasePath, FormatDate, Empty) {
return function (params) {
var scope = params.scope, // form scope
form = params.form, // form object
list = params.list, // list object
field = params.field, // form field
postAction = params.postAction, //action to perform post user selection
var scope = params.scope,
form = params.form,
list = params.list,
field = params.field,
postAction = params.postAction,
defaultUrl, name, hdr, watchUrl;
if (params.url) {
@@ -72,6 +72,7 @@ angular.module('LookUpHelper', ['RestServices', 'Utilities', 'SearchHelper', 'Pa
});
listScope.selectAction = function () {
var i, found = false;
for (i = 0; i < listScope[list.name].length; i++) {
if (listScope[list.name][i].checked === '1') {
@@ -102,7 +103,8 @@ angular.module('LookUpHelper', ['RestServices', 'Utilities', 'SearchHelper', 'Pa
};
listScope['toggle_' + list.iterator] = function (id) {
for (var i = 0; i < scope[list.name].length; i++) {
var i;
for (i = 0; i < listScope[list.name].length; i++) {
if (listScope[list.name][i].id === id) {
listScope[list.name][i].checked = '1';
listScope[list.name][i].success_class = 'success';
@@ -133,13 +135,14 @@ angular.module('LookUpHelper', ['RestServices', 'Utilities', 'SearchHelper', 'Pa
listScope.lookupPostRefreshRemove = scope.$on('PostRefresh', function () {
var fld, i;
for (fld in list.fields) {
if (list.fields[fld].type === 'date') {
if (list.fields[fld].type && list.fields[fld].type === 'date') {
//convert dates to our standard format
for (i = 0; i < scope[list.name].length; i++) {
scope[list.name][i][fld] = FormatDate(new Date(scope[list.name][i][fld]));
}
}
}
// List generator creates the form, resetting it and losing the previously selected value.
// If it's in the current set, find it and marke it as selected.
if (scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] !== '' &&

View File

@@ -5,16 +5,20 @@
*
*/
'use strict';
angular.module('PaginationHelpers', ['Utilities', 'RefreshHelper', 'RefreshRelatedHelper'])
.factory('PageRangeSetup', ['Empty', function(Empty) {
return function(params) {
.factory('PageRangeSetup', ['Empty',
function (Empty) {
return function (params) {
var scope = params.scope;
var count = params.count;
var next = params.next;
var previous = params.previous;
var iterator = params.iterator;
var scope = params.scope,
count = params.count,
next = params.next,
previous = params.previous,
iterator = params.iterator,
i, first, last;
scope[iterator + '_page'] = 1;
scope[iterator + '_num_pages'] = Math.ceil((count / scope[iterator + '_page_size']));
@@ -22,72 +26,64 @@ angular.module('PaginationHelpers', ['Utilities', 'RefreshHelper', 'RefreshRelat
scope[iterator + '_total_rows'] = count;
// Which page are we on?
if ( Empty(next) && previous ) {
if (Empty(next) && previous) {
// no next page, but there is a previous page
scope[iterator + '_page'] = parseInt(previous.match(/page=\d+/)[0].replace(/page=/,'')) + 1;
}
else if ( next && Empty(previous) ) {
scope[iterator + '_page'] = parseInt(previous.match(/page=\d+/)[0].replace(/page=/, '')) + 1;
} else if (next && Empty(previous)) {
// next page available, but no previous page
scope[iterator + '_page'] = 1;
}
else if ( next && previous ) {
} else if (next && 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
scope[iterator + '_page_range'] = new Array();
var first = (scope[iterator + '_page'] > 5) ? scope[iterator + '_page'] - 5 : 1;
scope[iterator + '_page_range'] = [];
first = (scope[iterator + '_page'] > 5) ? scope[iterator + '_page'] - 5 : 1;
if (scope[iterator + '_page'] < 6) {
var last = (10 <= scope[iterator + '_num_pages']) ? 10 : scope[iterator + '_num_pages'];
}
else {
var last = (scope[iterator + '_page'] + 4 < scope[iterator + '_num_pages']) ?
last = (10 <= scope[iterator + '_num_pages']) ? 10 : scope[iterator + '_num_pages'];
} else {
last = (scope[iterator + '_page'] + 4 < scope[iterator + '_num_pages']) ?
scope[iterator + '_page'] + 4 : scope[iterator + '_num_pages'];
}
for (var i=first; i <= last; i++) {
for (i = first; i <= last; i++) {
scope[iterator + '_page_range'].push(i);
}
};
}
}])
])
.factory('RelatedPaginateInit', [ 'RefreshRelated', '$cookieStore', 'Wait',
function(RefreshRelated, $cookieStore, Wait) {
return function(params) {
.factory('RelatedPaginateInit', ['RefreshRelated', '$cookieStore', 'Wait',
function (RefreshRelated, $cookieStore, Wait) {
return function (params) {
var scope = params.scope;
var relatedSets = params.relatedSets;
var pageSize = (params.pageSize) ? params.pageSize : 10;
var scope = params.scope,
relatedSets = params.relatedSets,
pageSize = (params.pageSize) ? params.pageSize : 10,
key;
for (var key in relatedSets){
cookieSize = $cookieStore.get(relatedSets[key].iterator + '_page_size');
for (key in relatedSets) {
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'] = 1;
scope[relatedSets[key].iterator + '_page'] = 0;
scope[relatedSets[key].iterator + '_page_size'] = pageSize;
}
}
scope.getPage = function(page, set, iterator) {
var new_url = scope[iterator + '_url'].replace(/.page\=\d+/,'');
var connect = (/\/$/.test(new_url)) ? '?' : '&';
scope.getPage = function (page, set, iterator) {
var new_url = scope[iterator + '_url'].replace(/.page\=\d+/, ''),
connect = (/\/$/.test(new_url)) ? '?' : '&';
new_url += connect + 'page=' + page;
new_url += (scope[iterator + 'SearchParams']) ? '&' + scope[iterator + 'SearchParams'] +
'&page_size=' + scope[iterator + '_page_size' ] : 'page_size=' + scope[iterator + 'PageSize' ];
'&page_size=' + scope[iterator + '_page_size'] : 'page_size=' + scope[iterator + 'PageSize'];
Wait('start');
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: new_url });
}
};
scope.pageIsActive = function(page, iterator) {
return (page == scope[iterator + '_page']) ? 'active' : '';
}
scope.pageIsActive = function (page, iterator) {
return (page === scope[iterator + '_page']) ? 'active' : '';
};
scope.changePageSize = function(set, iterator) {
scope.changePageSize = function (set, iterator) {
// Called when a new page size is selected
scope[iterator + '_page'] = 1;
@@ -96,74 +92,68 @@ angular.module('PaginationHelpers', ['Utilities', 'RefreshHelper', 'RefreshRelat
// Using the session cookie, keep track of user rows per page selection
$cookieStore.put(iterator + '_page_size', scope[iterator + '_page_size']);
url = url.replace(/\/\?.*$/,'/');
url += (scope[iterator + 'SearchParams']) ? '?' + scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + '_page_size' ] :
'?page_size=' + scope[iterator + '_page_size' ];
url = url.replace(/\/\?.*$/, '/');
url += (scope[iterator + 'SearchParams']) ? '?' + scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + '_page_size'] :
'?page_size=' + scope[iterator + '_page_size'];
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: url });
RefreshRelated({
scope: scope,
set: set,
iterator: iterator,
url: url
});
};
};
}
}
}])
])
.factory('PaginateInit', [ 'Refresh', '$cookieStore', 'Wait',
function(Refresh, $cookieStore, Wait) {
return function(params) {
.factory('PaginateInit', ['Refresh', '$cookieStore', 'Wait',
function (Refresh, $cookieStore, Wait) {
return function (params) {
var scope = params.scope;
var list = params.list;
var iterator = (params.iterator) ? params.iterator : list.iterator;
var mode = (params.mode) ? params.mode : null;
var cookieSize = $cookieStore.get(iterator + '_page_size');
var scope = params.scope,
list = params.list,
iterator = (params.iterator) ? params.iterator : list.iterator,
mode = (params.mode) ? params.mode : null;
scope[iterator + '_page'] = (params.page) ? params.page : 1;
scope[iterator + '_url'] = params.url;
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) {
scope[iterator + '_page_size'] = params.pageSize;
}
else if (mode == 'lookup') {
} else if (mode === 'lookup') {
scope[iterator + '_page_size'] = 5;
}
else {
} else {
scope[iterator + '_page_size'] = 20;
}
}
scope.getPage = function(page, set, iterator) {
var new_url = scope[iterator + '_url'].replace(/.page\=\d+/,'');
var connect = (/\/$/.test(new_url)) ? '?' : '&';
scope.getPage = function (page, set, iterator) {
var new_url = scope[iterator + '_url'].replace(/.page\=\d+/, ''),
connect = (/\/$/.test(new_url)) ? '?' : '&';
new_url += connect + 'page=' + page;
new_url += (scope[iterator + 'SearchParams']) ? '&' + scope[iterator + 'SearchParams'] +
'&page_size=' + scope[iterator + '_page_size' ] : 'page_size=' + scope[iterator + 'PageSize' ];
'&page_size=' + scope[iterator + '_page_size'] : 'page_size=' + scope[iterator + 'PageSize'];
Wait('start');
Refresh({ scope: scope, set: set, iterator: iterator, url: new_url });
}
};
scope.pageIsActive = function(page, iterator) {
return (page == scope[iterator + '_page']) ? 'active' : '';
}
scope.pageIsActive = function (page, iterator) {
return (page === scope[iterator + '_page']) ? 'active' : '';
};
scope.changePageSize = function(set, iterator) {
scope.changePageSize = function (set, iterator) {
// Called whenever a new page size is selected
// 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;
var new_url = scope[iterator + '_url'].replace(/\?page_size\=\d+/,'');
var connect = (/\/$/.test(new_url)) ? '?' : '&';
new_url += (scope[iterator + 'SearchParams']) ? connect + scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + '_page_size' ] :
connect + 'page_size=' + scope[iterator + '_page_size' ];
var new_url = scope[iterator + '_url'].replace(/\?page_size\=\d+/, ''),
connect = (/\/$/.test(new_url)) ? '?' : '&';
new_url += (scope[iterator + 'SearchParams']) ? connect + scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + '_page_size'] :
connect + 'page_size=' + scope[iterator + '_page_size'];
Wait('start');
Refresh({ scope: scope, set: set, iterator: iterator, url: new_url });
};
};
}
}
}]);
]);

View File

@@ -3,61 +3,83 @@
*
* ParseHelper
*
* Routines for parsing variable data and toggling
* between JSON and YAML.
* Show the CodeMirror variable editor and allow
* toggle between JSON and YAML
*
*/
angular.module('ParseHelper', [])
.factory('ParseTypeChange', [function() {
return function(scope, varName, parseTypeName) {
'use strict';
angular.module('ParseHelper', ['Utilities', 'AngularCodeMirrorModule'])
.factory('ParseTypeChange', ['Alert', 'AngularCodeMirror', function (Alert, AngularCodeMirror) {
return function (params) {
var scope = params.scope,
field_id = params.field_id,
fld = (params.variable) ? params.variable : 'variables',
pfld = (params.parse_variable) ? params.parse_variable : 'parseType',
onReady = params.onReady,
onChange = params.onChange,
codeMirror;
function removeField() {
//set our model to the last change in CodeMirror and then destroy CodeMirror
scope[fld] = codeMirror.getValue();
codeMirror.destroy();
}
function createField(onChange, onReady) {
//hide the textarea and show a fresh CodeMirror with the current mode (json or yaml)
codeMirror = AngularCodeMirror();
codeMirror.addModes($AnsibleConfig.variable_edit_modes);
codeMirror.showTextArea({ scope: scope, model: fld, element: field_id, mode: scope[pfld], onReady: onReady, onChange: onChange });
}
// Hide the textarea and show a CodeMirror editor
createField(onChange, onReady);
// Toggle displayed variable string between JSON and YAML
var fld = (varName) ? varName : 'variables';
var pfld = (parseTypeName) ? parseTypeName : 'parseType';
scope.blockParseTypeWatch = false;
scope.blockVariableDataWatch = false;
if (scope['remove' + fld + 'Watch']) {
scope['remove' + fld + 'Watch']();
}
scope['remove' + fld + 'Watch'] = scope.$watch(pfld, function(newVal, oldVal) {
if (newVal !== oldVal) {
if (newVal == 'json') {
if ( scope[fld] && !/^---$/.test(scope[fld])) {
// convert YAML to JSON
scope.parseTypeChange = function() {
var json_obj;
if (scope[pfld] === 'json') {
// converting yaml to json
try {
var json_obj = jsyaml.load(scope[fld]); //parse yaml into an obj
removeField();
json_obj = jsyaml.load(scope[fld]);
if ($.isEmptyObject(json_obj)) {
scope[fld] = "{}";
}
else {
scope[fld] = JSON.stringify(json_obj, null, " ");
}
catch (err) {
// ignore parse errors. allow the user to paste values in and sync the
// radio button later. parse errors will be flagged on save.
createField();
}
catch (e) {
Alert('Parse Error', 'Failed to parse valid YAML. ' + e.message);
setTimeout( function() { scope.$apply( function() { scope[pfld] = 'yaml'; createField(); }); }, 500);
}
}
else {
scope[fld] = "\{\}";
}
}
else {
if ( scope[fld] && !/^\{\}$/.test(scope[fld]) ) {
// convert JSON to YAML
// convert json to yaml
try {
var json_obj = JSON.parse(scope[fld]);
removeField();
json_obj = JSON.parse(scope[fld]);
if ($.isEmptyObject(json_obj)) {
scope[fld] = '---';
}
else {
scope[fld] = jsyaml.safeDump(json_obj);
}
catch (err) {
// ignore the errors. allow the user to paste values in and sync the
// radio button later. parse errors will be flagged on save.
createField();
}
catch (e) {
Alert('Parse Error', 'Failed to parse valid JSON. ' + e.message);
setTimeout( function() { scope.$apply( function() { scope[pfld] = 'json'; createField(); }); }, 500 );
}
}
else {
scope[fld] = "---";
};
};
}
}
}
});
}
}]);
]);

View File

@@ -8,13 +8,14 @@
*/
angular.module('PermissionsHelper', [])
// Handle category change event
.factory('PermissionCategoryChange', [ function() {
return function(params) {
var scope = params.scope;
var reset = params.reset;
// Handle category change event
.factory('PermissionCategoryChange', [
function () {
return function (params) {
var scope = params.scope,
reset = params.reset;
if (scope.category == 'Inventory') {
if (scope.category === 'Inventory') {
scope.projectrequired = false;
scope.permissionTypeHelp =
"<dl>\n" +
@@ -25,8 +26,7 @@ angular.module('PermissionsHelper', [])
"<dt>Admin</dt>\n" +
"<dd>Allow the user or team full access to the inventory. This includes reading, writing, deletion of the inventory and inventory sync operations.</dd>\n" +
"</dl>\n";
}
else {
} else {
scope.projectrequired = true;
scope.permissionTypeHelp =
"<dl>\n" +
@@ -40,9 +40,8 @@ angular.module('PermissionsHelper', [])
}
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).
*
*/
angular.module('ProjectPathHelper', ['RestServices', 'Utilities'])
.factory('GetProjectPath', ['Alert', 'Rest', 'GetBasePath','ProcessErrors',
function(Alert, Rest, GetBasePath, ProcessErrors) {
return function(params) {
.factory('GetProjectPath', ['Alert', 'Rest', 'GetBasePath', 'ProcessErrors',
function (Alert, Rest, GetBasePath, ProcessErrors) {
return function (params) {
var scope = params.scope;
var master = params.master;
var scope = params.scope,
master = params.master;
function arraySort(data) {
//Sort nodes by name
var names = [];
var newData = [];
for (var i=0; i < data.length; i++) {
var i, j, names = [],
newData = [];
for (i = 0; i < data.length; i++) {
names.push(data[i].value);
}
names.sort();
for (var j=0; j < names.length; j++) {
for (i=0; i < data.length; i++) {
if (data[i].value == names[j]) {
for (j = 0; j < names.length; j++) {
for (i = 0; i < data.length; i++) {
if (data[i].value === names[j]) {
newData.push(data[i]);
}
}
@@ -37,22 +36,28 @@ angular.module('ProjectPathHelper', ['RestServices', 'Utilities'])
scope.showMissingPlaybooksAlert = false;
Rest.setUrl( GetBasePath('config') );
Rest.setUrl(GetBasePath('config'));
Rest.get()
.success( function(data, status, headers, config) {
var opts = [];
for (var i=0; i < data.project_local_paths.length; i++) {
opts.push({ label: data.project_local_paths[i], value: data.project_local_paths[i] });
.success(function (data) {
var opts = [], i;
for (i = 0; i < data.project_local_paths.length; i++) {
opts.push({
label: data.project_local_paths[i],
value: data.project_local_paths[i]
});
}
if (scope.local_path) {
// List only includes paths not assigned to projects, so add the
// path assigned to the current project.
opts.push({ label: scope.local_path, value: scope.local_path });
opts.push({
label: scope.local_path,
value: scope.local_path
});
}
scope.project_local_paths = arraySort(opts);
if (scope.local_path) {
for (var i=0; scope.project_local_paths.length; i++) {
if (scope.project_local_paths[i].value == scope.local_path) {
for (i = 0; scope.project_local_paths.length; i++) {
if (scope.project_local_paths[i].value === scope.local_path) {
scope.local_path = scope.project_local_paths[i];
break;
}
@@ -62,14 +67,15 @@ angular.module('ProjectPathHelper', ['RestServices', 'Utilities'])
master.local_path = scope.local_path;
master.base_dir = scope.base_dir; // Keep in master object so that it doesn't get
// wiped out on form reset.
if (opts.length == 0) {
if (opts.length === 0) {
// trigger display of alert block when scm_type == manual
scope.showMissingPlaybooksAlert = true;
}
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to access API config. GET status: ' + status });
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to access API config. GET status: ' + status });
});
};
}
}]);
]);

View File

@@ -9,84 +9,91 @@
*
*/
'use strict';
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',
'Prompt', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'ProjectStatusForm', 'Wait',
function($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath,
function ($rootScope, $location, $log, $routeParams, Rest, Alert, GenerateForm, Prompt, ProcessErrors, GetBasePath,
FormatDate, ProjectStatusForm, Wait) {
return function(params) {
return function (params) {
var project_id = params.project_id;
var last_update = params.last_update;
var generator = GenerateForm;
var form = ProjectStatusForm;
var project_id = params.project_id,
last_update = params.last_update,
generator = GenerateForm,
form = ProjectStatusForm,
html, scope, ww, wh, x, y, maxrows;
Wait('start');
// 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);
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();
// Set modal dimensions based on viewport width
var ww = $(document).width();
var wh = $('body').height();
var x, y, maxrows;
ww = $(document).width();
wh = $('body').height();
if (ww > 1199) {
// desktop
x = 675;
y = (750 > wh) ? wh - 20 : 750;
maxrows = 20;
}
else if (ww <= 1199 && ww >= 768) {
} else if (ww <= 1199 && ww >= 768) {
x = 550;
y = (620 > wh) ? wh - 15 : 620;
maxrows = 15;
}
else {
} else {
x = (ww - 20);
y = (500 > wh) ? wh : 500;
maxrows = 10;
}
// Create the modal
$('#status-modal-dialog').dialog({
buttons: { "OK": function() { $( this ).dialog( "close" ); } },
buttons: {
"OK": function () {
$(this).dialog("close");
}
},
modal: true,
width: x,
height: y,
autoOpen: false,
create: function (e, ui) {
create: function () {
// 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
$('.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%
var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]');
var content = dialog.find('#status-modal-dialog');
content.width( dialog.width() - 28 );
var dialog = $('.ui-dialog[aria-describedby="status-modal-dialog"]'),
content = dialog.find('#status-modal-dialog');
content.width(dialog.width() - 28);
},
close: function(e, ui) {
close: function () {
// Destroy on close
// Destroy on close
$('.tooltip').each( function(index) {
$('.tooltip').each(function () {
// Remove any lingering tooltip <div> elements
$(this).remove();
});
$('.popover').each(function(index) {
$('.popover').each(function () {
// remove lingering popover <div> elements
$(this).remove();
});
$('#status-modal-dialog').dialog('destroy');
$('#projects-modal-container').empty();
},
open: function(e, ui) {
open: function () {
Wait('stop');
}
});
@@ -94,34 +101,35 @@ angular.module('ProjectsHelper', ['RestServices', 'Utilities', 'ProjectStatusDef
// Retrieve detail record and prepopulate the form
Rest.setUrl(last_update);
Rest.get()
.success( function(data, status, headers, config) {
var results = data;
for (var fld in form.fields) {
.success(function (data) {
var results = data, fld;
for (fld in form.fields) {
if (results[fld]) {
if (fld == 'created') {
if (fld === 'created') {
scope[fld] = FormatDate(new Date(results[fld]));
}
else {
} else {
scope[fld] = results[fld];
}
}
else {
} else {
if (results.summary_fields.project[fld]) {
scope[fld] = results.summary_fields.project[fld]
scope[fld] = results.summary_fields.project[fld];
}
}
}
$('#status-modal-dialog')
.dialog({ title: results.summary_fields.project.name + ' Status'})
.dialog({
title: results.summary_fields.project.name + ' Status'
})
.dialog('open');
})
.error( function(data, status, headers, config) {
.error(function (data, status) {
$('#form-modal').modal("hide");
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve status of project: ' + project_id + '. GET status: ' + status });
ProcessErrors(scope, data, status, form, {
hdr: 'Error!',
msg: 'Failed to retrieve status of project: ' + project_id + '. GET status: ' + status
});
});
};
}
}]);
]);

View File

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

View File

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

View File

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

View File

@@ -8,54 +8,57 @@
*
*/
angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationListDefinition', 'ListGenerator', 'AuthService',
'InventoryHelper', 'InventoryFormDefinition', 'ParseHelper', 'SearchHelper'
])
'use strict';
.factory('WatchInventoryWindowResize', ['ApplyEllipsis', function(ApplyEllipsis) {
return function() {
angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationListDefinition', 'ListGenerator', 'AuthService',
'InventoryHelper', 'InventoryFormDefinition', 'ParseHelper', 'SearchHelper'
])
.factory('WatchInventoryWindowResize', ['ApplyEllipsis',
function (ApplyEllipsis) {
return function () {
// Call to set or restore window resize
var timeOut;
$(window).resize(function() {
$(window).resize(function () {
clearTimeout(timeOut);
timeOut = setTimeout(function() {
timeOut = setTimeout(function () {
// Hack to stop group-name div slipping to a new line
$('#groups_table .name-column').each( function() {
var td_width = $(this).width();
var level_width = $(this).find('.level').width();
var level_padding = parseInt($(this).find('.level').css('padding-left').replace(/px/,''));
var level = level_width + level_padding;
var pct = ( 100 - Math.ceil((level / td_width)*100) ) + '%';
$('#groups_table .name-column').each(function () {
var td_width = $(this).width(),
level_width = $(this).find('.level').width(),
level_padding = parseInt($(this).find('.level').css('padding-left').replace(/px/, '')),
level = level_width + level_padding,
pct = (100 - Math.ceil((level / td_width) * 100)) + '%';
$(this).find('.group-name').css({ width: pct });
});
ApplyEllipsis('#groups_table .group-name a');
ApplyEllipsis('#hosts_table .host-name a');
}, 100);
});
};
}
}])
])
.factory('SaveInventory', ['InventoryForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList',
.factory('SaveInventory', ['InventoryForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList',
'GetBasePath', 'ParseTypeChange', 'Wait',
function(InventoryForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, Wait) {
return function(params) {
function (InventoryForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, Wait) {
return function (params) {
// Save inventory property modifications
var scope = params.scope;
var form = InventoryForm;
var defaultUrl=GetBasePath('inventory');
var scope = params.scope,
form = InventoryForm,
defaultUrl = GetBasePath('inventory'),
fld, json_data, data;
Wait('start');
try {
// Make sure we have valid variable data
if (scope.inventoryParseType == 'json') {
var json_data = JSON.parse(scope.inventory_variables); //make sure JSON parses
}
else {
var json_data = jsyaml.load(scope.inventory_variables); //parse yaml
if (scope.inventoryParseType === 'json') {
json_data = JSON.parse(scope.inventory_variables); //make sure JSON parses
} else {
json_data = jsyaml.load(scope.inventory_variables); //parse yaml
}
// Make sure our JSON is actually an object
@@ -63,76 +66,77 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
throw "failed to return an object!";
}
var data = {}
for (var fld in form.fields) {
if (fld != 'inventory_variables') {
data = {};
for (fld in form.fields) {
if (fld !== 'inventory_variables') {
if (form.fields[fld].realName) {
data[form.fields[fld].realName] = scope[fld];
}
else {
} else {
data[fld] = scope[fld];
}
}
}
Rest.setUrl(defaultUrl + scope['inventory_id'] + '/');
Rest.setUrl(defaultUrl + scope.inventory_id + '/');
Rest.put(data)
.success( function(data, status, headers, config) {
.success(function (data) {
if (scope.inventory_variables) {
Rest.setUrl(data.related.variable_data);
Rest.put(json_data)
.success( function(data, status, headers, config) {
.success(function () {
Wait('stop');
scope.$emit('InventorySaved');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update inventory varaibles. PUT returned status: ' + status });
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to update inventory varaibles. PUT returned status: ' + status
});
}
else {
});
} else {
scope.$emit('InventorySaved');
}
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update inventory. POST returned status: ' + status });
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to update inventory. POST returned status: ' + status });
});
}
catch(err) {
} catch (err) {
Wait('stop');
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',
'GetBasePath', 'ParseTypeChange', 'SaveInventory', 'Wait', 'Store', 'SearchInit',
function(InventoryForm, GenerateForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, SaveInventory,
function (InventoryForm, GenerateForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, SaveInventory,
Wait, Store, SearchInit) {
return function(params) {
return function (params) {
var parent_scope = params.scope
var inventory_id = params.inventory_id;
var generator = GenerateForm;
var form = InventoryForm;
var defaultUrl=GetBasePath('inventory');
var master = {};
// Hang onto current search params
var PreviousSearchParams = Store('CurrentSearchParams');
var parent_scope = params.scope,
inventory_id = params.inventory_id,
generator = GenerateForm,
form = InventoryForm,
master = {},
PreviousSearchParams = Store('CurrentSearchParams'),
scope;
form.well = false;
var scope = generator.inject(form, {mode: 'edit', modal: true, related: false, modal_show: false });
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 */
form.well = true;
ParseTypeChange(scope,'inventory_variables', 'inventoryParseType');
scope.$on('inventoryPropertiesLoaded', function() {
var callback = function() { Wait('stop'); };
$('#form-modal').modal('show');
scope.inventoryParseType = 'yaml';
ParseTypeChange({ scope: scope, variable: 'inventory_variables', parse_variable: 'inventoryParseType',
field_id: 'inventory_inventory_variables', onReady: callback });
});
scope.formModalActionLabel = 'Save';
scope.formModalCancelShow = true;
scope.formModalInfo = false;
@@ -141,41 +145,32 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
Wait('start');
Rest.setUrl(GetBasePath('inventory') + inventory_id + '/');
Rest.get()
.success( function(data, status, headers, config) {
for (var fld in form.fields) {
if (fld == 'inventory_variables') {
.success(function (data) {
var fld, json_obj;
for (fld in form.fields) {
if (fld === 'inventory_variables') {
// Parse variables, converting to YAML.
if ($.isEmptyObject(data.variables) || data.variables == "\{\}" ||
data.variables == "null" || data.variables == "") {
if ($.isEmptyObject(data.variables) || data.variables === "{}" ||
data.variables === "null" || data.variables === "") {
scope.inventory_variables = "---";
}
else {
} else {
try {
var json_obj = JSON.parse(data.variables);
json_obj = JSON.parse(data.variables);
scope.inventory_variables = jsyaml.safeDump(json_obj);
}
catch(err) {
} catch (err) {
Alert('Variable Parse Error', 'Attempted to parse variables for inventory: ' + inventory_id +
'. Parse returned: ' + err);
if (console) {
console.log(err);
console.log('data:');
console.log(data.variables);
}
scope.inventory_variables = '---';
}
}
master.inventory_variables = scope.variables;
}
else if (fld == 'inventory_name') {
} else if (fld === 'inventory_name') {
scope[fld] = data.name;
master[fld] = scope[fld];
}
else if (fld == 'inventory_description') {
} else if (fld === 'inventory_description') {
scope[fld] = data.description;
master[fld] = scope[fld];
}
else if (data[fld]) {
} else if (data[fld]) {
scope[fld] = data[fld];
master[fld] = scope[fld];
}
@@ -197,19 +192,18 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
field: 'organization'
});
Wait('stop');
$('#form-modal').modal('show');
scope.$emit('inventoryPropertiesLoaded');
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status });
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status });
});
if (scope.removeInventorySaved) {
scope.removeInventorySaved();
}
scope.removeInventorySaved = scope.$on('InventorySaved', function() {
scope.removeInventorySaved = scope.$on('InventorySaved', function () {
$('#form-modal').modal('hide');
// Restore prior search state
if (scope.searchCleanp) {
@@ -227,7 +221,7 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
parent_scope.$emit('RefreshInventories');
});
scope.cancelModal = function() {
scope.cancelModal = function () {
// Restore prior search state
if (scope.searchCleanp) {
scope.searchCleanup();
@@ -241,14 +235,14 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
sort_order: PreviousSearchParams.sort_order,
setWidgets: false
});
}
};
scope.formModalAction = function() {
parent_scope.inventory_id = inventory_id;
scope.formModalAction = function () {
scope.inventory_id = inventory_id;
parent_scope.inventory_name = scope.inventory_name;
SaveInventory({ scope: scope });
}
};
};
}
}]);
]);

View File

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

View File

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

View File

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

View File

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

View File

@@ -15,11 +15,13 @@
*
*/
'use strict';
angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
.factory('SearchInit', ['Alert', 'Rest', 'Refresh', '$location', 'GetBasePath', 'Empty', '$timeout', 'Wait', 'Store',
function(Alert, Rest, Refresh, $location, GetBasePath, Empty, $timeout, Wait, Store) {
return function(params) {
.factory('SearchInit', ['Alert', 'Rest', 'Refresh', '$location', 'GetBasePath', 'Empty', '$timeout', 'Wait', 'Store',
function (Alert, Rest, Refresh, $location, GetBasePath, Empty, $timeout, Wait, Store) {
return function (params) {
var scope = params.scope,
set = params.set,
@@ -30,17 +32,6 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
sort_order = params.sort_order || '',
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) {
// Set default values
var f, fld, fka, modifier;
@@ -54,8 +45,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
if (list.fields[fld].sourceModel) {
fka = list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField;
sort_order = (list.fields[fld].desc) ? '-' + fka : fka;
}
else {
} else {
sort_order = (list.fields[fld].desc) ? '-' + fld : fld;
}
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 set to a scope variable
scope[iterator + 'SearchPlaceholder' + modifier] = scope[list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder];
}
else {
} else {
// Set to a string value in the list definition
scope[iterator + 'SearchPlaceholder' + modifier] = list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder;
}
}
else {
} else {
// Default value
scope[iterator + 'SearchPlaceholder' + modifier] = 'Search';
}
@@ -114,8 +102,8 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
f = scope[iterator + 'SearchField' + modifier];
if (list.fields[f]) {
if ( list.fields[f].searchType && (list.fields[f].searchType === 'boolean' ||
list.fields[f].searchType === 'select') ) {
if (list.fields[f].searchType && (list.fields[f].searchType === 'boolean' ||
list.fields[f].searchType === 'select')) {
scope[iterator + 'SelectShow' + modifier] = true;
scope[iterator + 'SearchSelectOpts' + modifier] = list.fields[f].searchOptions;
}
@@ -131,9 +119,9 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
if (setWidgets) {
// Set default values for each search widget on the page
widgets = (list.searchWidgets) ? list.searchWidgets : 1;
for (i=1; i <= widgets; i++) {
for (i = 1; i <= widgets; i++) {
modifier = (i === 1) ? '' : i;
if ( $('#search-widget-container' + modifier) ) {
if ($('#search-widget-container' + modifier)) {
setDefaults(i);
}
}
@@ -151,7 +139,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
// Functions to handle search widget changes
scope.setSearchField = function(iterator, fld, label, widget) {
scope.setSearchField = function (iterator, fld, label, widget) {
var modifier = (widget === undefined || widget === 1) ? '' : widget;
scope[iterator + 'SearchFieldLabel' + modifier] = label;
@@ -168,14 +156,14 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder) {
if (scope[list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder]) {
// if set to a scope variable
scope[iterator + 'SearchPlaceholder' + modifier] = scope[list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder];
}
else {
scope[iterator + 'SearchPlaceholder' + modifier] = scope[list.fields[scope[iterator + 'SearchField' +
modifier]].searchPlaceholder];
} else {
// 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
scope[iterator + 'SearchPlaceholder' + modifier] = 'Search';
}
@@ -184,8 +172,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
scope[iterator + "InputDisable" + modifier] = true;
scope[iterator + 'ShowStartBtn' + modifier] = false;
scope.search(iterator);
}
else if (list.fields[fld].searchSingleValue){
} else if (list.fields[fld].searchSingleValue) {
// Query a specific attribute for one specific value
// searchSingleValue: true
// searchType: 'boolean|int|etc.'
@@ -194,32 +181,32 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
scope[iterator + "SearchValue" + modifier] = list.fields[fld].searchValue;
// For boolean type, SearchValue must be an object
if (list.fields[fld].searchType === 'boolean' && list.fields[fld].searchValue === 'true') {
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 {
scope[iterator + "SearchSelectValue" + modifier] = { value: list.fields[fld].searchValue };
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 {
scope[iterator + "SearchSelectValue" + modifier] = {
value: list.fields[fld].searchValue
};
}
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 + "SearchValue" + modifier] = list.fields[fld].searchValue;
scope[iterator + "InputDisable" + modifier] = true;
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')) {
scope[iterator + 'SelectShow' + modifier] = true;
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 + '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 + 'InputDisable' + modifier] = true;
scope[iterator + 'SearchValue' + modifier] = 'true';
@@ -230,12 +217,12 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
};
scope.resetSearch = function(iterator) {
scope.resetSearch = function (iterator) {
// Respdond to click of reset button
var i,
widgets = (list.searchWidgets) ? list.searchWidgets : 1;
for (i=1; i <= widgets; i++) {
for (i = 1; i <= widgets; i++) {
// Clear each search widget
setDefaults(i);
}
@@ -247,20 +234,20 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
if (scope.removeDoSearch) {
scope.removeDoSearch();
}
scope.removeDoSearch = scope.$on('doSearch', function(e, iterator, page, load) {
scope.removeDoSearch = scope.$on('doSearch', function (e, iterator, page, load) {
//
// Execute the search
//
scope[iterator + 'Loading'] = (load === undefined || load === true) ? true : false;
var url = defaultUrl, connect;
var url = defaultUrl,
connect;
//finalize and execute the query
scope[iterator + 'Page'] = (page) ? parseInt(page) - 1 : 0;
if (scope[iterator + 'SearchParams']) {
if (/\/$/.test(url)) {
url += '?' + scope[iterator + 'SearchParams'];
}
else {
} else {
url += '&' + scope[iterator + 'SearchParams'];
}
}
@@ -274,15 +261,20 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
connect = (/\/$/.test(url)) ? '?' : '&';
url += connect + scope[iterator + 'ExtraParms'];
}
url = url.replace(/\&\&/,'&');
Refresh({ scope: scope, set: set, iterator: iterator, url: url });
url = url.replace(/\&\&/, '&');
Refresh({
scope: scope,
set: set,
iterator: iterator,
url: url
});
});
if (scope.removePrepareSearch) {
scope.removePrepareSearch();
}
scope.removePrepareSearch = scope.$on('prepareSearch', function(e, iterator, page, load, spin) {
scope.removePrepareSearch = scope.$on('prepareSearch', function (e, iterator, page, load, spin) {
//
// Start building the search key/value pairs. This will process each search widget, if the
// selected field is an object type (used on activity stream).
@@ -292,9 +284,9 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
var i, modifier,
widgets = (list.searchWidgets) ? list.searchWidgets : 1;
for (i=1; i <= widgets; i++) {
for (i = 1; i <= widgets; i++) {
modifier = (i === 1) ? '' : i;
if ( $('#search-widget-container' + modifier) ) {
if ($('#search-widget-container' + modifier)) {
if (list.fields[scope[iterator + 'SearchField' + modifier]] &&
list.fields[scope[iterator + 'SearchField' + modifier]].searchObject) {
// Search field of object type
@@ -308,23 +300,20 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
scope[iterator + 'SearchParams'] += '&' +
list.fields[scope[iterator + 'SearchField' + modifier]].searchObject +
'__id=' + scope[iterator + 'SearchValue' + modifier];
}
else {
} else {
scope[iterator + 'SearchParams'] += '&' +
list.fields[scope[iterator + 'SearchField' + modifier]].searchObject +
'__name__icontains=' +
scope[iterator + 'SearchValue' + modifier];
}
}
else {
} else {
// Search value is empty
scope[iterator + 'ShowStartBtn' + modifier] = true;
scope[iterator + 'SearchParams'] += '&' +
list.fields[scope[iterator + 'SearchField' + modifier]].searchField +
'=' + list.fields[scope[iterator + 'SearchField' + modifier]].searchObject;
}
}
else {
} else {
// Object Type set to All
scope[iterator + 'HideAllStartBtn' + modifier] = true;
}
@@ -337,78 +326,69 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
if (scope.removePrepareSearch2) {
scope.removePrepareSearch2();
}
scope.removePrepareSearch2 = scope.$on('prepareSearch2', function(e, iterator, page, load, spin) {
scope.removePrepareSearch2 = scope.$on('prepareSearch2', function (e, iterator, page, load, spin) {
// Continue building the search by examining the remaining search widgets. If we're looking at activity_stream,
// there's more than one.
var i, modifier,
widgets = (list.searchWidgets) ? list.searchWidgets : 1;
for (i=1; i <= widgets; i++) {
for (i = 1; i <= widgets; i++) {
modifier = (i === 1) ? '' : i;
scope[iterator + 'HoldInput' + modifier] = true;
if ($('#search-widget-container' + modifier) &&
list.fields[scope[iterator + 'SearchField' + modifier]] &&
!list.fields[scope[iterator + 'SearchField' + modifier]].searchObject) {
list.fields[scope[iterator + 'SearchField' + modifier]] && !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 (scope[iterator + 'SearchValue' + modifier]) {
// if user typed a value in the input box, show the reset link
scope[iterator + 'ShowStartBtn' + modifier] = false;
}
else {
} else {
scope[iterator + 'ShowStartBtn' + modifier] = true;
}
if ( (!scope[iterator + 'SelectShow' + modifier] && !Empty(scope[iterator + 'SearchValue' + modifier])) ||
if ((!scope[iterator + 'SelectShow' + modifier] && !Empty(scope[iterator + 'SearchValue' + modifier])) ||
(scope[iterator + 'SelectShow' + modifier] && scope[iterator + 'SearchSelectValue' + modifier]) ||
(list.fields[scope[iterator + 'SearchField' + modifier]] &&
list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'gtzero') ) {
list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'gtzero')) {
if (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
scope[iterator + 'SearchParams'] += '&' + list.fields[scope[iterator + 'SearchField' + modifier]].sourceModel + '__' +
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 === null) ) {
scope[iterator + 'SearchSelectValue' + modifier].value === null)) {
scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchField' + modifier] + '__';
}
else {
} else {
scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchField' + modifier] + '__';
}
if ( list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
if (list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
(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=';
}
else if ( list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'gtzero' ) {
} else if (list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'gtzero') {
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 === null) ) {
scope[iterator + 'SearchSelectValue' + modifier].value === null)) {
scope[iterator + 'SearchParams'] += 'iexact=';
}
else {
} else {
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchType' + modifier] + '=';
}
if ( list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
if (list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
(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;
}
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 &&
list.fields[scope[iterator + 'SearchField' + modifier]].searchType !== 'or' &&
list.fields[scope[iterator + 'SearchField' + modifier]].searchType !== 'gtzero') ) {
list.fields[scope[iterator + 'SearchField' + modifier]].searchType !== 'gtzero')) {
scope[iterator + 'SearchParams'] += encodeURI(scope[iterator + 'SearchValue' + modifier]);
}
}
@@ -416,8 +396,8 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
}
}
if ( (iterator === 'inventory' && scope.inventoryFailureFilter) ||
(iterator === 'host' && scope.hostFailureFilter) ) {
if ((iterator === 'inventory' && scope.inventoryFailureFilter) ||
(iterator === 'host' && scope.hostFailureFilter)) {
//Things that bypass the search widget. Should go back and add a second widget possibly on
//inventory pages and eliminate this
scope[iterator + 'SearchParams'] += '&has_active_failures=true';
@@ -431,14 +411,14 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
scope.$emit('doSearch', iterator, page, load, spin);
});
scope.startSearch = function(e,iterator) {
scope.startSearch = function (e, iterator) {
// If use clicks enter while on input field, start the search
if (e.keyCode === 13) {
scope.search(iterator);
}
};
scope.search = function(iterator, page, load) {
scope.search = function (iterator, page, load) {
// Called to initiate a searh.
// Page is optional. Added to accomodate back function on Job Events detail.
// Spin optional -set to false if spin not desired.
@@ -451,13 +431,13 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
};
scope.sort = function(fld) {
scope.sort = function (fld) {
// reset sort icons back to 'icon-sort' on all columns
// except the one clicked
$('.list-header').each(function() {
$('.list-header').each(function () {
if ($(this).attr('id') !== fld + '-header') {
var icon = $(this).find('i');
icon.attr('class','fa fa-sort');
icon.attr('class', 'fa fa-sort');
}
});
@@ -468,13 +448,11 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
if (icon.hasClass('fa-sort')) {
icon.removeClass('fa-sort');
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.addClass('fa-sort-down');
direction = '-';
}
else if (icon.hasClass('fa-sort-down')) {
} else if (icon.hasClass('fa-sort-down')) {
icon.removeClass('fa-sort-down');
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
if (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;
}
else {
} else {
if (list.fields[fld].sourceModel) {
sort_order = direction + list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField;
}
else {
} else {
sort_order = direction + fld;
}
}
@@ -498,11 +473,12 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
};
// Call after modal dialogs to remove any lingering callbacks
scope.searchCleanup = function() {
scope.searchCleanup = function () {
scope.removeDoSearch();
scope.removePrepareSearch();
scope.removePrepareSearch2();
};
};
}]);
}
]);

View File

@@ -5,24 +5,29 @@
* Routines shared amongst the team controllers
*/
angular.module('TeamHelper', [ 'RestServices', 'Utilities', 'OrganizationListDefinition',
'SearchHelper', 'PaginationHelpers', 'ListGenerator' ])
.factory('SetTeamListeners', ['Alert', 'Rest', function(Alert, Rest) {
return function(params) {
'use strict';
var scope = params.scope;
var set = params.set;
var iterator = params.iterator;
angular.module('TeamHelper', ['RestServices', 'Utilities', 'OrganizationListDefinition', 'SearchHelper',
'PaginationHelpers', 'ListGenerator'
])
.factory('SetTeamListeners', ['Alert', 'Rest',
function (Alert, Rest) {
return function (params) {
var scope = params.scope,
set = params.set,
iterator = params.iterator;
// Listeners to perform lookups after main inventory list loads
scope.$on('TeamResultFound', function(e, results, lookup_results) {
if ( lookup_results.length == results.length ) {
scope.$on('TeamResultFound', function (e, results, lookup_results) {
var i, j, key, property;
if (lookup_results.length === results.length) {
key = 'organization';
property = 'organization_name';
for (var i=0; i < results.length; i++) {
for (var j=0; j < lookup_results.length; j++) {
if (results[i][key] == lookup_results[j].id) {
for (i = 0; i < results.length; i++) {
for (j = 0; j < lookup_results.length; j++) {
if (results[i][key] === lookup_results[j].id) {
results[i][property] = lookup_results[j].value;
}
}
@@ -32,76 +37,91 @@ angular.module('TeamHelper', [ 'RestServices', 'Utilities', 'OrganizationListDef
}
});
scope.$on('TeamRefreshFinished', function(e, results) {
scope.$on('TeamRefreshFinished', function (e, results) {
// Loop through the result set (sent to us by the search helper) and
// lookup the id and name of each organization. After each lookup
// completes, call resultFound.
var lookup_results = [];
var i, lookup_results = [], url;
for (var i = 0; i < results.length; i++) {
Rest.setUrl('/api/v1/organizations/' + results[i].organization + '/');
function getOrganization(url) {
Rest.setUrl(url);
Rest.get()
.success( function( data, status, headers, config) {
.success(function (data) {
lookup_results.push({ id: data.id, value: data.name });
scope.$emit('TeamResultFound', results, lookup_results);
})
.error( function( data, status, headers, config) {
.error(function () {
lookup_results.push({ id: 'error' });
scope.$emit('TeamResultFound', results, lookup_results);
});
}
});
}
}])
.factory('TeamLookUpOrganizationInit', ['Alert', 'Rest', 'OrganizationList', 'GenerateList', 'SearchInit', 'PaginateInit',
function(Alert, Rest, OrganizationList, GenerateList, SearchInit, PaginateInit) {
return function(params) {
for (i = 0; i < results.length; i++) {
url = '/api/v1/organizations/' + results[i].organization + '/';
getOrganization(url);
}
});
};
}
])
.factory('TeamLookUpOrganizationInit', ['Alert', 'Rest', 'OrganizationList', 'GenerateList', 'SearchInit', 'PaginateInit',
function (Alert, Rest, OrganizationList, GenerateList, SearchInit, PaginateInit) {
return function (params) {
var scope = params.scope;
// Show pop-up to select organization
scope.lookUpOrganization = function() {
var list = OrganizationList;
var listGenerator = GenerateList;
var listScope = listGenerator.inject(list, { mode: 'lookup', hdr: 'Select Organization' });
var defaultUrl = '/api/v1/organizations/';
scope.lookUpOrganization = function () {
var list = OrganizationList,
listGenerator = GenerateList,
listScope = listGenerator.inject(list, { mode: 'lookup', hdr: 'Select Organization' }),
defaultUrl = '/api/v1/organizations/';
listScope.selectAction = function() {
var found = false;
for (var i=0; i < listScope[list.name].length; i++) {
if (listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] == "success") {
listScope.selectAction = function () {
var i, found = false;
for (i = 0; i < listScope[list.name].length; i++) {
if (listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] === "success") {
found = true;
scope['organization'] = listScope[list.name][i].id;
scope['organization_name'] = listScope[list.name][i].name;
scope['team_form'].$setDirty();
scope.organization = listScope[list.name][i].id;
scope.organization_name = listScope[list.name][i].name;
scope.team_form.$setDirty();
listGenerator.hide();
}
}
if (found == false) {
if (found === false) {
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
if (listScope[list.name]) {
for (var i=0; i < listScope[list.name].length; i++) {
for (var i = 0; i < listScope[list.name].length; i++) {
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";
}
}
};
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'
});
scope.search(list.iterator);
listScope.toggle_organization(scope.organization);
};
};
}
}
}]);
]);

View File

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

View File

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

View File

@@ -6,16 +6,19 @@
*
* @dict
*/
'use strict';
angular.module('CredentialsListDefinition', [])
.value(
'CredentialList', {
.value('CredentialList', {
name: 'credentials',
iterator: 'credential',
selectTitle: 'Add Credentials',
editTitle: 'Credentials',
selectInstructions: '<p>Select existing credentials by clicking each credential or checking the related checkbox. When 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>',
selectInstructions: "<p>Select existing credentials by clicking each credential or checking the related checkbox. When " +
"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,
hover: true,
@@ -35,22 +38,6 @@ angular.module('CredentialsListDefinition', [])
excludeModal: 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: {
@@ -62,13 +49,13 @@ angular.module('CredentialsListDefinition', [])
stream: {
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
mode: 'all'
mode: 'edit'
}
},
fieldActions: {
edit: {
ngClick: "editCredential(\{\{ credential.id \}\})",
ngClick: "editCredential(credential.id)",
icon: 'fa-edit',
label: 'Edit',
"class": 'btn-sm',
@@ -77,7 +64,7 @@ angular.module('CredentialsListDefinition', [])
},
"delete": {
ngClick: "deleteCredential(\{\{ credential.id \}\},'\{\{ credential.name \}\}')",
ngClick: "deleteCredential(credential.id, credential.name)",
icon: 'fa-trash',
label: 'Delete',
"class": 'btn-sm',

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,15 +5,18 @@
* List view object for Inventories data model.
*
*/
'use strict';
angular.module('InventoriesListDefinition', [])
.value(
'InventoryList', {
.value('InventoryList', {
name: 'inventories',
iterator: 'inventory',
selectTitle: 'Add 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,
hover: true,
@@ -62,23 +65,23 @@ angular.module('InventoriesListDefinition', [])
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
icon: "icon-comments-alt",
mode: 'all'
mode: 'edit'
}
},
fieldActions: {
status: {
//label: 'Status',
ngHref: "\{\{ inventory.status_link \}\}",
iconClass: "\{\{ 'fa fa-cloud icon-cloud-' + inventory.status_class \}\}",
awToolTip: "\{\{ inventory.status_tip \}\}",
ngHref: "{{ inventory.status_link }}",
iconClass: "{{ 'fa fa-cloud icon-cloud-' + inventory.status_class }}",
awToolTip: "{{ inventory.status_tip }}",
dataPlacement: "top"
},
failed_hosts: {
//label: 'Failures',
ngHref: "\{\{ inventory.failed_hosts_link \}\}",
iconClass: "\{\{ 'fa icon-failures-' + inventory.failed_hosts_class \}\}",
awToolTip: "\{\{ inventory.failed_hosts_tip \}\}",
ngHref: "{{ inventory.failed_hosts_link }}",
iconClass: "{{ 'fa icon-failures-' + inventory.failed_hosts_class }}",
awToolTip: "{{ inventory.failed_hosts_tip }}",
dataPlacement: "top"
},
edit: {
@@ -89,7 +92,7 @@ angular.module('InventoriesListDefinition', [])
},
"delete": {
label: 'Delete',
ngClick: "deleteInventory(\{\{ inventory.id \}\},'\{\{ inventory.name \}\}')",
ngClick: "deleteInventory(inventory.id, inventory.names)",
awToolTip: 'Delete inventory',
dataPlacement: 'top'
}

View File

@@ -99,7 +99,7 @@ angular.module('InventoryGroupsDefinition', [])
cancel: {
//label: 'Cancel',
mode: 'all',
ngClick: "cancelUpdate({{ group.id }})",
ngClick: "cancelUpdate(group.id)",
awToolTip: "Cancel sync process",
'class': 'red-txt',
ngShow: "group.id > 1 && (group.status == 'running' || group.status == 'pending' || group.status == 'updating')",
@@ -108,7 +108,7 @@ angular.module('InventoryGroupsDefinition', [])
edit: {
//label: 'Edit',
mode: 'all',
ngClick: "editGroup({{ group.group_id + ',' + group.id }})",
ngClick: "editGroup(group.group_id, group.id)",
awToolTip: 'Edit group',
ngShow: "group.id > 1", // hide for all hosts
dataPlacement: "top"
@@ -116,7 +116,7 @@ angular.module('InventoryGroupsDefinition', [])
"delete": {
//label: 'Delete',
mode: 'all',
ngClick: "deleteGroup({{ group.id + ',' + group.group_id }})",
ngClick: "deleteGroup(group.id, group.group_id)",
awToolTip: 'Delete group',
ngShow: "group.id != 1", // hide for all hosts
dataPlacement: "top"

View File

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

View File

@@ -6,9 +6,11 @@
*
*
*/
'use strict';
angular.module('JobEventsListDefinition', [])
.value(
'JobEventList', {
.value('JobEventList', {
name: 'jobevents',
iterator: 'jobevent',
@@ -53,17 +55,23 @@ angular.module('JobEventsListDefinition', [])
columnClass: 'col-sm-1 col-xs-2 text-center',
searchField: 'failed',
searchType: 'boolean',
searchOptions: [{ name: 'success', value: 0 }, { name: 'error', value: 1 }],
searchOptions: [{
name: 'success',
value: 0
}, {
name: 'error',
value: 1
}],
nosort: true,
searchable: false,
ngClick: 'viewJobEvent({{ jobevent.id }})',
ngClick: 'viewJobEvent(jobevent.id)',
awToolTip: '{{ jobevent.statusBadgeToolTip }}',
dataPlacement: 'top',
badgeIcon: 'fa icon-job-{{ jobevent.status }}',
badgePlacement: 'left',
badgeToolTip: '{{ jobevent.statusBadgeToolTip }}',
badgeTipPlacement: 'top',
badgeNgClick: 'viewJobEvent({{ jobevent.id }})'
badgeNgClick: 'viewJobEvent(jobevent.id)'
},
event_display: {
label: 'Event',

View File

@@ -6,6 +6,9 @@
*
*
*/
'use strict';
angular.module('JobHostDefinition', [])
.value('JobHostList', {
@@ -50,7 +53,7 @@ angular.module('JobHostDefinition', [])
sourceModel: 'host',
sourceField: 'name',
ngBind: 'jobhost.host_name',
ngHref: "jobhost.hostLinkTo"
ngHref: "{{ jobhost.hostLinkTo }}"
},
status: {
label: 'Status',
@@ -64,7 +67,13 @@ angular.module('JobHostDefinition', [])
dataPlacement: 'top',
searchField: 'failed',
searchType: 'boolean',
searchOptions: [{ name: "success", value: 0 }, { name: "error", value: 1 }]
searchOptions: [{
name: "success",
value: 0
}, {
name: "error",
value: 1
}]
},
failed: {
label: 'Job failed?',

View File

@@ -6,15 +6,18 @@
*
*
*/
'use strict';
angular.module('JobTemplatesListDefinition', [])
.value(
'JobTemplateList', {
.value('JobTemplateList', {
name: 'job_templates',
iterator: 'job_template',
selectTitle: 'Add Job Template',
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,
hover: true,
@@ -39,14 +42,14 @@ angular.module('JobTemplatesListDefinition', [])
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
icon: "icon-comments-alt",
mode: 'all'
mode: 'edit'
}
},
fieldActions: {
edit: {
label: 'Edit',
ngClick: "editJobTemplate(\{\{ job_template.id \}\})",
ngClick: "editJobTemplate(job_template.id)",
icon: 'icon-edit',
awToolTip: 'Edit template',
"class": 'btn-default btn-xs',
@@ -57,13 +60,13 @@ angular.module('JobTemplatesListDefinition', [])
icon: 'icon-rocket',
mode: 'all',
"class": 'btn-xs btn-success',
ngClick: 'submitJob(\{\{ job_template.id \}\})',
ngClick: 'submitJob(job_template.id)',
awToolTip: 'Start a job using this template',
dataPlacement: 'top'
},
"delete": {
label: 'Delete',
ngClick: "deleteJobTemplate(\{\{ job_template.id \}\},'\{\{ job_template.name \}\}')",
ngClick: "deleteJobTemplate(job_template.id, job_template.name)",
icon: 'icon-trash',
"class": 'btn-danger btn-xs',
awToolTip: 'Delete template',

View File

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

View File

@@ -6,16 +6,18 @@
*
*
*/
'use strict';
angular.module('OrganizationListDefinition', [])
.value(
'OrganizationList', {
.value('OrganizationList', {
name: 'organizations',
iterator: 'organization',
selectTitle: 'Add Organizations',
editTitle: 'Organizations',
hover: true,
index: true,
index: false,
fields: {
name: {
@@ -36,7 +38,7 @@ angular.module('OrganizationListDefinition', [])
stream: {
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
mode: 'all'
mode: 'edit'
}
},

View File

@@ -6,14 +6,17 @@
*
*
*/
'use strict';
angular.module('PermissionListDefinition', [])
.value(
'PermissionList', {
.value('PermissionList', {
name: 'permissions',
iterator: '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',
index: true,
well: true,
@@ -22,7 +25,7 @@ angular.module('PermissionListDefinition', [])
name: {
key: true,
label: 'Name',
ngClick: 'editPermission(\{\{ permission.id \}\})'
ngClick: 'editPermission(permission.id)'
},
inventory: {
label: 'Inventory',
@@ -51,14 +54,14 @@ angular.module('PermissionListDefinition', [])
stream: {
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
mode: 'all'
mode: 'edit'
}
},
fieldActions: {
edit: {
label: 'Edit',
ngClick: "editPermission(\{\{ permission.id \}\})",
ngClick: "editPermission(permission.id)",
icon: 'icon-edit',
"class": 'btn-xs btn-default',
awToolTip: 'Edit permission',
@@ -67,7 +70,7 @@ angular.module('PermissionListDefinition', [])
"delete": {
label: 'Delete',
ngClick: "deletePermission(\{\{ permission.id \}\},'\{\{ permission.name \}\}')",
ngClick: "deletePermission(permission.id, permission.name)",
icon: 'icon-trash',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete permission',

View File

@@ -6,9 +6,11 @@
*
*
*/
'use strict';
angular.module('ProjectsListDefinition', [])
.value(
'ProjectList', {
.value('ProjectList', {
name: 'projects',
iterator: 'project',
@@ -38,10 +40,10 @@ angular.module('ProjectsListDefinition', [])
},
status: {
label: 'Status',
ngClick: 'showSCMStatus(\{\{ project.id \}\})',
ngClick: 'showSCMStatus(project.id)',
awToolTip: 'View details of last SCM Update',
dataPlacement: 'top',
badgeIcon: "\{\{ 'fa icon-failures-' + project.badge \}\}",
badgeIcon: "{{ 'fa icon-failures-' + project.badge }}",
badgePlacement: 'left',
searchType: 'select',
searchOptions: [], // will be set by Options call to projects resource
@@ -72,7 +74,7 @@ angular.module('ProjectsListDefinition', [])
"</dl>\n",
dataPlacement: 'left',
dataContainer: 'body',
mode: 'all',
mode: 'edit',
awToolTip: 'Click for help',
awTipPlacement: 'top'
},
@@ -84,34 +86,34 @@ angular.module('ProjectsListDefinition', [])
stream: {
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
mode: 'all'
mode: 'edit'
}
},
fieldActions: {
edit: {
label: 'Edit',
ngClick: "editProject(\{\{ project.id \}\})",
ngClick: "editProject(project.id)",
awToolTip: 'Edit project properties',
dataPlacement: 'top'
},
scm_update: {
label: 'Update',
ngClick: 'SCMUpdate(\{\{ project.id \}\})',
awToolTip: "\{\{ project.scm_update_tooltip \}\}",
ngClick: 'SCMUpdate(project.id)',
awToolTip: "{{ project.scm_update_tooltip }}",
ngClass: "project.scm_type_class",
dataPlacement: 'top'
},
cancel: {
label: 'Stop',
ngClick: "cancelUpdate(\{\{ project.id \}\}, '\{\{ project.name \}\}')",
ngClick: "cancelUpdate(project.id, project.name)",
awToolTip: 'Cancel a running SCM update process',
ngShow: "project.status == 'updating'",
dataPlacement: 'top'
},
"delete": {
label: 'Delete',
ngClick: "deleteProject(\{\{ project.id \}\},'\{\{ project.name \}\}')",
ngClick: "deleteProject(project.id, project.name)",
awToolTip: 'Permanently remove project from the database',
ngShow: "project.status !== 'updating'",
dataPlacement: 'top'

View File

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

View File

@@ -4,17 +4,19 @@
* Teams.js
* List view object for Team data model.
*
*
*/
'use strict';
angular.module('TeamsListDefinition', [])
.value(
'TeamList', {
.value('TeamList', {
name: 'teams',
iterator: 'team',
selectTitle: 'Add Team',
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,
hover: true,
@@ -43,14 +45,14 @@ angular.module('TeamsListDefinition', [])
stream: {
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
mode: 'all'
mode: 'edit'
}
},
fieldActions: {
edit: {
label: 'Edit',
ngClick: "editTeam(\{\{ team.id \}\})",
ngClick: "editTeam(team.id)",
icon: 'icon-edit',
"class": 'btn-xs btn-default',
awToolTip: 'Edit team',
@@ -59,7 +61,7 @@ angular.module('TeamsListDefinition', [])
"delete": {
label: 'Delete',
ngClick: "deleteTeam(\{\{ team.id \}\},'\{\{ team.name \}\}')",
ngClick: "deleteTeam(team.id, team.name)",
icon: 'icon-trash',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete team',

View File

@@ -4,11 +4,12 @@
* Users.js
* List view object for Users data model.
*
*
*/
'use strict';
angular.module('UserListDefinition', [])
.value(
'UserList', {
.value('UserList', {
name: 'users',
iterator: 'user',
@@ -38,21 +39,21 @@ angular.module('UserListDefinition', [])
label: 'Create New',
mode: 'all', // One of: edit, select, all
ngClick: 'addUser()',
basePaths: ['organizations','users'], // base path must be in list, or action not available
basePaths: ['organizations', 'users'], // base path must be in list, or action not available
"class": 'btn-xs',
awToolTip: 'Create a new user'
},
stream: {
ngClick: "showActivity()",
awToolTip: "View Activity Stream",
mode: 'all'
mode: 'edit'
}
},
fieldActions: {
edit: {
label: 'Edit',
ngClick: "editUser(\{\{ user.id \}\})",
ngClick: "editUser(user.id)",
icon: 'icon-edit',
"class": 'btn-xs btn-default',
awToolTip: 'Edit user',
@@ -61,7 +62,7 @@ angular.module('UserListDefinition', [])
"delete": {
label: 'Delete',
ngClick: "deleteUser(\{\{ user.id \}\},'\{\{ user.username \}\}')",
ngClick: "deleteUser(user.id, user.username)",
icon: 'icon-trash',
"class": 'btn-xs btn-danger',
awToolTip: 'Delete user',

View File

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

View File

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

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