mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 01:57:35 -03:30
Merge remote-tracking branch 'origin/javascript-cleanup'
Conflicts: awx/ui/static/js/helpers/Lookup.js awx/ui/static/js/helpers/PaginationHelpers.js awx/ui/static/js/helpers/related-search.js
This commit is contained in:
commit
a3e48849d8
3
.gitignore
vendored
3
.gitignore
vendored
@ -4,9 +4,10 @@ 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
|
||||
|
||||
44
Gruntfile.js
Normal file
44
Gruntfile.js
Normal 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']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
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']);
|
||||
}
|
||||
384
awx/ui/static/css/bootstrap-theme.css
vendored
384
awx/ui/static/css/bootstrap-theme.css
vendored
@ -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);
|
||||
}
|
||||
1
awx/ui/static/css/bootstrap-theme.min.css
vendored
1
awx/ui/static/css/bootstrap-theme.min.css
vendored
File diff suppressed because one or more lines are too long
6805
awx/ui/static/css/bootstrap.css
vendored
6805
awx/ui/static/css/bootstrap.css
vendored
File diff suppressed because it is too large
Load Diff
9
awx/ui/static/css/bootstrap.min.css
vendored
9
awx/ui/static/css/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
@ -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 |
@ -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 |
@ -4,23 +4,25 @@
|
||||
* Our main application mdoule. Declare application routes and perform initialization chores.
|
||||
*
|
||||
*/
|
||||
|
||||
var urlPrefix = $basePath;
|
||||
|
||||
angular.module('ansible', [
|
||||
'ngRoute',
|
||||
'ngSanitize',
|
||||
'ngCookies',
|
||||
'RestServices',
|
||||
'AuthService',
|
||||
'Utilities',
|
||||
'OrganizationFormDefinition',
|
||||
'OrganizationFormDefinition',
|
||||
'UserFormDefinition',
|
||||
'FormGenerator',
|
||||
'OrganizationListDefinition',
|
||||
'UserListDefinition',
|
||||
'UserListDefinition',
|
||||
'UserHelper',
|
||||
'ListGenerator',
|
||||
'ListGenerator',
|
||||
'PromptDialog',
|
||||
'ApiLoader',
|
||||
'RelatedSearchHelper',
|
||||
'ApiLoader',
|
||||
'RelatedSearchHelper',
|
||||
'SearchHelper',
|
||||
'PaginationHelpers',
|
||||
'RefreshHelper',
|
||||
@ -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,253 +86,368 @@ angular.module('ansible', [
|
||||
'HomeGroupListDefinition',
|
||||
'HomeHostListDefinition',
|
||||
'ActivityDetailDefinition'
|
||||
])
|
||||
.config(['$routeProvider', function($routeProvider) {
|
||||
$routeProvider.
|
||||
when('/jobs',
|
||||
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobsListCtrl }).
|
||||
])
|
||||
.config(['$routeProvider',
|
||||
function ($routeProvider) {
|
||||
$routeProvider.
|
||||
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/:job_id/job_events/:event_id',
|
||||
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobEventsEdit }).
|
||||
when('/jobs/:id/job_host_summaries', {
|
||||
templateUrl: urlPrefix + 'partials/jobs.html',
|
||||
controller: 'JobHostSummaryList'
|
||||
}).
|
||||
|
||||
when('/job_templates',
|
||||
{ templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesList }).
|
||||
|
||||
when('/job_templates/add',
|
||||
{ templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesAdd }).
|
||||
when('/jobs/:job_id/job_events/:event_id', {
|
||||
templateUrl: urlPrefix + 'partials/jobs.html',
|
||||
controller: 'JobEventsEdit'
|
||||
}).
|
||||
|
||||
when('/job_templates/:id',
|
||||
{ templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesEdit }).
|
||||
when('/job_templates', {
|
||||
templateUrl: urlPrefix + 'partials/job_templates.html',
|
||||
controller: 'JobTemplatesList'
|
||||
}).
|
||||
|
||||
when('/projects',
|
||||
{ templateUrl: urlPrefix + 'partials/projects.html', controller: ProjectsList }).
|
||||
when('/job_templates/add', {
|
||||
templateUrl: urlPrefix + 'partials/job_templates.html',
|
||||
controller: 'JobTemplatesAdd'
|
||||
}).
|
||||
|
||||
when('/projects/add',
|
||||
{ templateUrl: urlPrefix + 'partials/projects.html', controller: ProjectsAdd }).
|
||||
when('/job_templates/:id', {
|
||||
templateUrl: urlPrefix + 'partials/job_templates.html',
|
||||
controller: 'JobTemplatesEdit'
|
||||
}).
|
||||
|
||||
when('/projects/:id',
|
||||
{ templateUrl: urlPrefix + 'partials/projects.html', controller: ProjectsEdit }).
|
||||
when('/projects', {
|
||||
templateUrl: urlPrefix + 'partials/projects.html',
|
||||
controller: 'ProjectsList'
|
||||
}).
|
||||
|
||||
when('/projects/:project_id/organizations',
|
||||
{ templateUrl: urlPrefix + 'partials/projects.html', controller: OrganizationsList }).
|
||||
when('/projects/add', {
|
||||
templateUrl: urlPrefix + 'partials/projects.html',
|
||||
controller: 'ProjectsAdd'
|
||||
}).
|
||||
|
||||
when('/projects/:project_id/organizations/add',
|
||||
{ templateUrl: urlPrefix + 'partials/projects.html', controller: OrganizationsAdd }).
|
||||
when('/projects/:id', {
|
||||
templateUrl: urlPrefix + 'partials/projects.html',
|
||||
controller: 'ProjectsEdit'
|
||||
}).
|
||||
|
||||
when('/hosts/:id/job_host_summaries',
|
||||
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobHostSummaryList }).
|
||||
when('/projects/:project_id/organizations', {
|
||||
templateUrl: urlPrefix + 'partials/projects.html',
|
||||
controller: 'OrganizationsList'
|
||||
}).
|
||||
|
||||
when('/inventories',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: InventoriesList }).
|
||||
when('/projects/:project_id/organizations/add', {
|
||||
templateUrl: urlPrefix + 'partials/projects.html',
|
||||
controller: 'OrganizationsAdd'
|
||||
}).
|
||||
|
||||
when('/inventories/add',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: InventoriesAdd }).
|
||||
when('/hosts/:id/job_host_summaries', {
|
||||
templateUrl: urlPrefix + 'partials/jobs.html',
|
||||
controller: 'JobHostSummaryList'
|
||||
}).
|
||||
|
||||
when('/inventories/:inventory_id',
|
||||
{ templateUrl: urlPrefix + 'partials/inventory-edit.html', controller: InventoriesEdit }).
|
||||
when('/inventories', {
|
||||
templateUrl: urlPrefix + 'partials/inventories.html',
|
||||
controller: 'InventoriesList'
|
||||
}).
|
||||
|
||||
when('/organizations', { templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: OrganizationsList }).
|
||||
when('/inventories/add', {
|
||||
templateUrl: urlPrefix + 'partials/inventories.html',
|
||||
controller: 'InventoriesAdd'
|
||||
}).
|
||||
|
||||
when('/organizations/add', { templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: OrganizationsAdd }).
|
||||
when('/inventories/:inventory_id', {
|
||||
templateUrl: urlPrefix + 'partials/inventory-edit.html',
|
||||
controller: 'InventoriesEdit'
|
||||
}).
|
||||
|
||||
when('/organizations/:organization_id', { templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: OrganizationsEdit }).
|
||||
when('/organizations', {
|
||||
templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: 'OrganizationsList'
|
||||
}).
|
||||
|
||||
when('/organizations/:organization_id/admins', { templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: AdminsList }).
|
||||
when('/organizations/add', {
|
||||
templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: 'OrganizationsAdd'
|
||||
}).
|
||||
|
||||
when('/organizations/:organization_id/users', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersList }).
|
||||
when('/organizations/:organization_id', {
|
||||
templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: 'OrganizationsEdit'
|
||||
}).
|
||||
|
||||
when('/organizations/:organization_id/users/add', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersAdd }).
|
||||
when('/organizations/:organization_id/admins', {
|
||||
templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: 'AdminsList'
|
||||
}).
|
||||
|
||||
when('/organizations/:organization_id/users/:user_id', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersEdit }).
|
||||
when('/organizations/:organization_id/users', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: 'UsersList'
|
||||
}).
|
||||
|
||||
when('/teams', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: TeamsList }).
|
||||
when('/organizations/:organization_id/users/add', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: 'UsersAdd'
|
||||
}).
|
||||
|
||||
when('/teams/add', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: TeamsAdd }).
|
||||
when('/organizations/:organization_id/users/:user_id', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: 'UsersEdit'
|
||||
}).
|
||||
|
||||
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', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'TeamsList'
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/permissions', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: PermissionsList }).
|
||||
when('/teams/add', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'TeamsAdd'
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/permissions/:permission_id', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: PermissionsEdit }).
|
||||
when('/teams/:team_id', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'TeamsEdit'
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/users', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: UsersList }).
|
||||
when('/teams/:team_id/permissions/add', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'PermissionsAdd'
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/users/:user_id', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: UsersEdit }).
|
||||
when('/teams/:team_id/permissions', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'PermissionsList'
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/projects', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: ProjectsList }).
|
||||
when('/teams/:team_id/permissions/:permission_id', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'PermissionsEdit'
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/projects/add', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: ProjectsAdd }).
|
||||
when('/teams/:team_id/users', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'UsersList'
|
||||
}).
|
||||
|
||||
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/users/:user_id', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'UsersEdit'
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/credentials/add', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: CredentialsAdd }).
|
||||
when('/teams/:team_id/projects', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'ProjectsList'
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/credentials/:credential_id', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: CredentialsEdit }).
|
||||
when('/teams/:team_id/projects/add', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'ProjectsAdd'
|
||||
}).
|
||||
|
||||
when('/credentials', { templateUrl: urlPrefix + 'partials/credentials.html',
|
||||
controller: CredentialsList }).
|
||||
when('/teams/:team_id/projects/:project_id', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'ProjectsEdit'
|
||||
}).
|
||||
|
||||
when('/credentials/add', { templateUrl: urlPrefix + 'partials/credentials.html',
|
||||
controller: CredentialsAdd }).
|
||||
when('/teams/:team_id/credentials', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'CredentialsList'
|
||||
}).
|
||||
|
||||
when('/credentials/:credential_id', { templateUrl: urlPrefix + 'partials/credentials.html',
|
||||
controller: CredentialsEdit }).
|
||||
|
||||
when('/users', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersList }).
|
||||
when('/teams/:team_id/credentials/add', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'CredentialsAdd'
|
||||
}).
|
||||
|
||||
when('/users/add', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersAdd }).
|
||||
when('/teams/:team_id/credentials/:credential_id', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'CredentialsEdit'
|
||||
}).
|
||||
|
||||
when('/users/:user_id', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersEdit }).
|
||||
when('/credentials', {
|
||||
templateUrl: urlPrefix + 'partials/credentials.html',
|
||||
controller: 'CredentialsList'
|
||||
}).
|
||||
|
||||
when('/users/:user_id/credentials', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: CredentialsList }).
|
||||
when('/credentials/add', {
|
||||
templateUrl: urlPrefix + 'partials/credentials.html',
|
||||
controller: 'CredentialsAdd'
|
||||
}).
|
||||
|
||||
when('/users/:user_id/permissions/add', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: PermissionsAdd }).
|
||||
when('/credentials/:credential_id', {
|
||||
templateUrl: urlPrefix + 'partials/credentials.html',
|
||||
controller: 'CredentialsEdit'
|
||||
}).
|
||||
|
||||
when('/users/:user_id/permissions', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: PermissionsList }).
|
||||
when('/users', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: 'UsersList'
|
||||
}).
|
||||
|
||||
when('/users/:user_id/permissions/:permission_id', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: PermissionsEdit }).
|
||||
when('/users/add', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: 'UsersAdd'
|
||||
}).
|
||||
|
||||
when('/users/:user_id/credentials/add', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: CredentialsAdd }).
|
||||
when('/users/:user_id', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: 'UsersEdit'
|
||||
}).
|
||||
|
||||
when('/teams/:user_id/credentials/:credential_id', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: CredentialsEdit }).
|
||||
when('/users/:user_id/credentials', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: 'CredentialsList'
|
||||
}).
|
||||
|
||||
when('/login', { templateUrl: urlPrefix + 'partials/home.html', controller: Authenticate }).
|
||||
when('/users/:user_id/permissions/add', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: 'PermissionsAdd'
|
||||
}).
|
||||
|
||||
when('/logout', { templateUrl: urlPrefix + 'partials/home.html', controller: Authenticate }).
|
||||
when('/users/:user_id/permissions', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: 'PermissionsList'
|
||||
}).
|
||||
|
||||
when('/home', { templateUrl: urlPrefix + 'partials/home.html', controller: Home }).
|
||||
when('/users/:user_id/permissions/:permission_id', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: 'PermissionsEdit'
|
||||
}).
|
||||
|
||||
when('/home/groups', { templateUrl: urlPrefix + 'partials/subhome.html', controller: HomeGroups }).
|
||||
when('/users/:user_id/credentials/add', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'CredentialsAdd'
|
||||
}).
|
||||
|
||||
when('/home/hosts', { templateUrl: urlPrefix + 'partials/subhome.html', controller: HomeHosts }).
|
||||
|
||||
otherwise({redirectTo: '/home'});
|
||||
}])
|
||||
.run(['$cookieStore', '$rootScope', 'CheckLicense', '$location', 'Authorization','LoadBasePaths', 'ViewLicense',
|
||||
'Timer', 'ClearScope', 'HideStream',
|
||||
function($cookieStore, $rootScope, CheckLicense, $location, Authorization, LoadBasePaths, ViewLicense,
|
||||
Timer, ClearScope, HideStream) {
|
||||
|
||||
LoadBasePaths();
|
||||
|
||||
$rootScope.breadcrumbs = new Array();
|
||||
$rootScope.crumbCache = new Array();
|
||||
$rootScope.sessionTimer = Timer.init();
|
||||
when('/teams/:user_id/credentials/:credential_id', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: 'CredentialsEdit'
|
||||
}).
|
||||
|
||||
$rootScope.$on("$routeChangeStart", function(event, next, current) {
|
||||
when('/login', {
|
||||
templateUrl: urlPrefix + 'partials/home.html',
|
||||
controller: 'Authenticate'
|
||||
}).
|
||||
|
||||
// Before navigating away from current tab, make sure the primary view is visible
|
||||
if ($('#stream-container').is(':visible')) {
|
||||
HideStream();
|
||||
}
|
||||
when('/logout', {
|
||||
templateUrl: urlPrefix + 'partials/home.html',
|
||||
controller: 'Authenticate'
|
||||
}).
|
||||
|
||||
// On each navigation request, check that the user is logged in
|
||||
if ( !/^\/(login|logout)/.test($location.path()) ) {
|
||||
// capture most recent URL, excluding login/logout
|
||||
$rootScope.lastPath = $location.path();
|
||||
$cookieStore.put('lastPath', $location.path());
|
||||
}
|
||||
when('/home', {
|
||||
templateUrl: urlPrefix + 'partials/home.html',
|
||||
controller: 'Home'
|
||||
}).
|
||||
|
||||
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') ) {
|
||||
$rootScope.sessionTimer.expireSession();
|
||||
$location.path('/login');
|
||||
}
|
||||
}
|
||||
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 == '') {
|
||||
base = 'home';
|
||||
}
|
||||
else {
|
||||
base.replace(/\_/g,' ');
|
||||
}
|
||||
$('.nav-tabs a[href="#' + base + '"]').tab('show');
|
||||
when('/home/groups', {
|
||||
templateUrl: urlPrefix + 'partials/subhome.html',
|
||||
controller: 'HomeGroups'
|
||||
}).
|
||||
|
||||
when('/home/hosts', {
|
||||
templateUrl: urlPrefix + 'partials/subhome.html',
|
||||
controller: 'HomeHosts'
|
||||
}).
|
||||
|
||||
otherwise({
|
||||
redirectTo: '/home'
|
||||
});
|
||||
}
|
||||
])
|
||||
.run(['$cookieStore', '$rootScope', 'CheckLicense', '$location', 'Authorization', 'LoadBasePaths', 'ViewLicense',
|
||||
'Timer', 'ClearScope', 'HideStream',
|
||||
function ($cookieStore, $rootScope, CheckLicense, $location, Authorization, LoadBasePaths, ViewLicense,
|
||||
Timer, ClearScope, HideStream) {
|
||||
|
||||
LoadBasePaths();
|
||||
|
||||
$rootScope.breadcrumbs = [];
|
||||
$rootScope.crumbCache = [];
|
||||
$rootScope.sessionTimer = Timer.init();
|
||||
|
||||
$rootScope.$on("$routeChangeStart", function (event, next) {
|
||||
|
||||
// Before navigating away from current tab, make sure the primary view is visible
|
||||
if ($('#stream-container').is(':visible')) {
|
||||
HideStream();
|
||||
}
|
||||
|
||||
// On each navigation request, check that the user is logged in
|
||||
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')) {
|
||||
$location.path('/login');
|
||||
}
|
||||
} 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) {
|
||||
Authorization.restoreUserInfo(); //user must have hit browser refresh
|
||||
}
|
||||
CheckLicense();
|
||||
}
|
||||
|
||||
// Make the correct tab active
|
||||
var base = $location.path().replace(/^\//, '').split('/')[0];
|
||||
if (base === '') {
|
||||
base = 'home';
|
||||
} else {
|
||||
base.replace(/\_/g, ' ');
|
||||
}
|
||||
$('.nav-tabs a[href="#' + base + '"]').tab('show');
|
||||
});
|
||||
|
||||
if (!Authorization.getToken()) {
|
||||
// When the app first loads, redirect to login page
|
||||
$rootScope.sessionExpired = false;
|
||||
$cookieStore.put('sessionExpired', false);
|
||||
$location.path('/login');
|
||||
}
|
||||
else {
|
||||
// If browser refresh, set the user_is_superuser value
|
||||
$rootScope['user_is_superuser'] = Authorization.getUserInfo('is_superuser');
|
||||
}
|
||||
|
||||
// If browser refresh, activate the correct tab
|
||||
var base = ($location.path().replace(/^\//,'').split('/')[0]);
|
||||
if (base == '') {
|
||||
base = 'home';
|
||||
$location.path('/home');
|
||||
}
|
||||
else {
|
||||
base.replace(/\_/g,' ');
|
||||
}
|
||||
$('.nav-tabs a[href="#' + base + '"]').tab('show');
|
||||
|
||||
$rootScope.viewCurrentUser = function() {
|
||||
$location.path('/users/' + $rootScope.current_user.id);
|
||||
if (!Authorization.getToken()) {
|
||||
// When the app first loads, redirect to login page
|
||||
$rootScope.sessionExpired = false;
|
||||
$cookieStore.put('sessionExpired', false);
|
||||
$location.path('/login');
|
||||
} else {
|
||||
// If browser refresh, set the user_is_superuser value
|
||||
$rootScope.user_is_superuser = Authorization.getUserInfo('is_superuser');
|
||||
}
|
||||
|
||||
$rootScope.viewLicense = function() {
|
||||
//$location.path('/license');
|
||||
ViewLicense();
|
||||
}
|
||||
}]);
|
||||
// If browser refresh, activate the correct tab
|
||||
var base = ($location.path().replace(/^\//, '').split('/')[0]);
|
||||
if (base === '') {
|
||||
base = 'home';
|
||||
$location.path('/home');
|
||||
} else {
|
||||
base.replace(/\_/g, ' ');
|
||||
}
|
||||
$('.nav-tabs a[href="#' + base + '"]').tab('show');
|
||||
|
||||
$rootScope.viewCurrentUser = function () {
|
||||
$location.path('/users/' + $rootScope.current_user.id);
|
||||
};
|
||||
|
||||
$rootScope.viewLicense = function () {
|
||||
//$location.path('/license');
|
||||
ViewLicense();
|
||||
};
|
||||
}
|
||||
]);
|
||||
50
awx/ui/static/js/awx-min.js
vendored
Normal file
50
awx/ui/static/js/awx-min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
||||
/************************************
|
||||
/**********************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
@ -8,19 +8,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
var $AnsibleConfig =
|
||||
{
|
||||
tooltip_delay: {show: 500, hide: 100}, // Default number of milliseconds to delay displaying/hiding tooltips
|
||||
/*jshint unused:false */
|
||||
|
||||
debug_mode: true, // Enable console logging messages
|
||||
|
||||
password_strength: 45, // User password strength. Integer between 0 and 100, 100 being impossibly strong.
|
||||
// This value controls progress bar colors:
|
||||
// 0 to password_strength - 15 = red;
|
||||
// password_strength - 15 to password_strength = yellow
|
||||
// > password_strength = green
|
||||
// It also controls password validation. Passwords are rejected if the score is not > password_strength.
|
||||
var $AnsibleConfig = {
|
||||
|
||||
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.
|
||||
}
|
||||
tooltip_delay: {show: 500, hide: 100}, // Default number of milliseconds to delay displaying/hiding tooltips
|
||||
|
||||
debug_mode: true, // Enable console logging messages
|
||||
|
||||
password_strength: 45, // User password strength. Integer between 0 and 100, 100 being impossibly strong.
|
||||
// This value controls progress bar colors:
|
||||
// 0 to password_strength - 15 = red;
|
||||
// password_strength - 15 to password_strength = yellow
|
||||
// > 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.
|
||||
// Separate from time out value set in API.
|
||||
};
|
||||
@ -3,33 +3,35 @@
|
||||
*
|
||||
*
|
||||
* Admins.js
|
||||
*
|
||||
*
|
||||
* Controller functions for ading Admins to an Organization.
|
||||
*
|
||||
*/
|
||||
|
||||
'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'
|
||||
];
|
||||
@ -8,139 +8,145 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* globals console:false */
|
||||
|
||||
'use strict';
|
||||
|
||||
function Authenticate($cookieStore, $window, $scope, $rootScope, $location, Authorization, ToggleClass, Alert, Wait,
|
||||
Timer, Empty)
|
||||
{
|
||||
var setLoginFocus = function() {
|
||||
$('#login-username').focus();
|
||||
};
|
||||
function Authenticate($cookieStore, $window, $scope, $rootScope, $location, Authorization, ToggleClass, Alert, Wait,
|
||||
Timer, Empty) {
|
||||
|
||||
var setLoginFocus, lastPath, sessionExpired, scope;
|
||||
|
||||
var sessionExpired = (Empty($rootScope.sessionExpired)) ? $cookieStore.get('sessionExpired') : $rootScope.sessionExpired;
|
||||
|
||||
var lastPath = function() {
|
||||
return (Empty($rootScope.lastPath)) ? $cookieStore.get('lastPath') : $rootScope.lastPath;
|
||||
}
|
||||
setLoginFocus = function () {
|
||||
$('#login-username').focus();
|
||||
};
|
||||
|
||||
if ($AnsibleConfig.debug_mode && console) {
|
||||
console.log('User session expired: ' + sessionExpired);
|
||||
console.log('Last URL: ' + lastPath());
|
||||
}
|
||||
|
||||
// Hide any lingering modal dialogs
|
||||
$('.modal[aria-hidden=false]').each( function() {
|
||||
if ($(this).attr('id') !== 'login-modal') {
|
||||
$(this).modal('hide');
|
||||
}
|
||||
});
|
||||
sessionExpired = (Empty($rootScope.sessionExpired)) ? $cookieStore.get('sessionExpired') : $rootScope.sessionExpired;
|
||||
|
||||
// Just in case, make sure the wait widget is not active
|
||||
Wait('stop');
|
||||
|
||||
// Display the login dialog
|
||||
$('#login-modal').modal({ show: true, keyboard: false, backdrop: 'static' });
|
||||
|
||||
// Set focus to username field
|
||||
$('#login-modal').on('shown.bs.modal', function() {
|
||||
setLoginFocus();
|
||||
});
|
||||
lastPath = function () {
|
||||
return (Empty($rootScope.lastPath)) ? $cookieStore.get('lastPath') : $rootScope.lastPath;
|
||||
};
|
||||
|
||||
var 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();
|
||||
if ($AnsibleConfig.debug_mode && console) {
|
||||
console.log('User session expired: ' + sessionExpired);
|
||||
console.log('Last URL: ' + lastPath());
|
||||
}
|
||||
|
||||
if ($location.path() == '/logout') {
|
||||
//if logout request, clear AuthToken and user session data
|
||||
Authorization.logout();
|
||||
}
|
||||
|
||||
$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().
|
||||
// Hide any lingering modal dialogs
|
||||
$('.modal[aria-hidden=false]').each(function () {
|
||||
if ($(this).attr('id') !== 'login-modal') {
|
||||
$(this).modal('hide');
|
||||
}
|
||||
});
|
||||
|
||||
$('#login-password').bind('keypress', function(e) {
|
||||
var code = (e.keyCode ? e.keyCode : e.which);
|
||||
if (code == 13) {
|
||||
$('#login-button').click();
|
||||
}
|
||||
});
|
||||
|
||||
scope.reset = function() {
|
||||
$('#login-form input').each( function(index) { $(this).val(''); });
|
||||
};
|
||||
// Just in case, make sure the wait widget is not active
|
||||
Wait('stop');
|
||||
|
||||
// Call the API to get an auth token
|
||||
scope.systemLogin = function(username, password) {
|
||||
$('.api-error').empty();
|
||||
var token;
|
||||
if (username == null || username == undefined || username == '' ||
|
||||
password == null || password == undefined || password == '' ) {
|
||||
Alert('Error!', 'Please provide a username and password before attempting to login.', 'alert-danger', setLoginFocus);
|
||||
}
|
||||
else {
|
||||
Wait('start');
|
||||
Authorization.retrieveToken(username, password)
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#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) {
|
||||
Authorization.setUserInfo(data);
|
||||
$rootScope['user_is_superuser'] = data.results[0].is_superuser;
|
||||
Authorization.getLicense()
|
||||
.success(function(data, status, headers, config) {
|
||||
Authorization.setLicense(data['license_info']);
|
||||
if (lastPath()) {
|
||||
// Go back to most recent navigation path
|
||||
$location.path(lastPath());
|
||||
}
|
||||
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) {
|
||||
Wait('stop');
|
||||
Alert('Error', 'Failed to access license information. GET returned status: ' + status, 'alert-danger', setLoginFocus);
|
||||
});
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
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) {
|
||||
scope[key + 'Error'] = data[key][0];
|
||||
// Display the login dialog
|
||||
$('#login-modal').modal({
|
||||
show: true,
|
||||
keyboard: false,
|
||||
backdrop: 'static'
|
||||
});
|
||||
|
||||
// Set focus to username field
|
||||
$('#login-modal').on('shown.bs.modal', function () {
|
||||
setLoginFocus();
|
||||
});
|
||||
|
||||
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();
|
||||
|
||||
if ($location.path() === '/logout') {
|
||||
//if logout request, clear AuthToken and user session data
|
||||
Authorization.logout();
|
||||
}
|
||||
|
||||
$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) {
|
||||
var code = (e.keyCode ? e.keyCode : e.which);
|
||||
if (code === 13) {
|
||||
$('#login-button').click();
|
||||
}
|
||||
});
|
||||
|
||||
scope.reset = function () {
|
||||
$('#login-form input').each(function () {
|
||||
$(this).val('');
|
||||
});
|
||||
};
|
||||
|
||||
// Call the API to get an auth token
|
||||
scope.systemLogin = function (username, password) {
|
||||
$('.api-error').empty();
|
||||
var token;
|
||||
if (Empty(username) || Empty(password)) {
|
||||
Alert('Error!', 'Please provide a username and password before attempting to login.', 'alert-danger', setLoginFocus);
|
||||
} else {
|
||||
Wait('start');
|
||||
Authorization.retrieveToken(username, password)
|
||||
.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) {
|
||||
Authorization.setUserInfo(data);
|
||||
$rootScope.user_is_superuser = data.results[0].is_superuser;
|
||||
Authorization.getLicense()
|
||||
.success(function (data) {
|
||||
Authorization.setLicense(data.license_info);
|
||||
if (lastPath()) {
|
||||
// Go back to most recent navigation path
|
||||
$location.path(lastPath());
|
||||
} else {
|
||||
$location.url('/home?login=true');
|
||||
}
|
||||
})
|
||||
.error(function () {
|
||||
Wait('stop');
|
||||
Alert('Error', 'Failed to access user information. GET returned status: ' + status, 'alert-danger', setLoginFocus);
|
||||
});
|
||||
})
|
||||
.error(function (data, status) {
|
||||
Wait('stop');
|
||||
Alert('Error', 'Failed to access license 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 (key in data) {
|
||||
scope[key + 'Error'] = data[key][0];
|
||||
}
|
||||
} else {
|
||||
if (data.non_field_errors && data.non_field_errors.length > 0) {
|
||||
hdr = 'Error';
|
||||
msg = data.non_field_errors[0];
|
||||
} else {
|
||||
hdr = 'Error';
|
||||
msg = 'The login attempt failed with a status of: ' + status;
|
||||
}
|
||||
scope.reset();
|
||||
Alert(hdr, msg, 'alert-danger', setLoginFocus);
|
||||
}
|
||||
}
|
||||
else {
|
||||
var hdr, msg;
|
||||
if ( data.non_field_errors && data.non_field_errors.length > 0 ) {
|
||||
hdr = 'Error';
|
||||
msg = data.non_field_errors[0];
|
||||
}
|
||||
else {
|
||||
hdr = 'Error';
|
||||
msg = 'The login attempt failed with a status of: ' + status;
|
||||
}
|
||||
scope.reset();
|
||||
Alert(hdr, msg, 'alert-danger', setLoginFocus);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Authenticate.$inject = ['$cookieStore', '$window', '$scope', '$rootScope', '$location', 'Authorization', 'ToggleClass', 'Alert', 'Wait',
|
||||
'Timer', 'Empty'];
|
||||
'Timer', 'Empty'
|
||||
];
|
||||
|
||||
|
||||
@ -1,510 +1,525 @@
|
||||
/************************************
|
||||
/*************************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
*
|
||||
* Credentials.js
|
||||
*
|
||||
*
|
||||
* Controller functions for the Credential model.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
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.
|
||||
function CredentialsList($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, CredentialList,
|
||||
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
|
||||
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 url = GetBasePath(base);
|
||||
url += (base == 'users') ? $routeParams.user_id + '/credentials/' : $routeParams.team_id + '/credentials/';
|
||||
|
||||
SelectionInit({ scope: scope, list: list, url: url, returnToCaller: 1 });
|
||||
var list = CredentialList,
|
||||
defaultUrl = GetBasePath('credentials'),
|
||||
view = GenerateList,
|
||||
base = $location.path().replace(/^\//, '').split('/')[0],
|
||||
mode = (base === 'credentials') ? 'edit' : 'select',
|
||||
url;
|
||||
|
||||
if (scope.removePostRefresh) {
|
||||
scope.removePostRefresh();
|
||||
view.inject(list, { mode: mode, scope: $scope });
|
||||
|
||||
$scope.selected = [];
|
||||
$scope.credentialLoading = true;
|
||||
|
||||
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;
|
||||
|
||||
// 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
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
list.fields.kind.searchOptions = $scope.credential_kind_options;
|
||||
|
||||
if (scope.removeChoicesReady) {
|
||||
scope.removeChoicesReady();
|
||||
// Translate the kind value
|
||||
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();
|
||||
}
|
||||
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',
|
||||
callback: 'choicesReadyCredential'
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
scope.showActivity = function() { Stream({ scope: scope }); }
|
||||
|
||||
scope.addCredential = function() {
|
||||
$location.path($location.path() + '/add');
|
||||
}
|
||||
$scope.showActivity = function () {
|
||||
Stream({ scope: $scope });
|
||||
};
|
||||
|
||||
scope.editCredential = function(id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
}
|
||||
|
||||
scope.deleteCredential = function(id, name) {
|
||||
|
||||
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);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||
});
|
||||
};
|
||||
$scope.addCredential = function () {
|
||||
$location.path($location.path() + '/add');
|
||||
};
|
||||
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete ' + name + '?',
|
||||
action: action
|
||||
$scope.editCredential = function (id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
};
|
||||
|
||||
$scope.deleteCredential = function (id, name) {
|
||||
|
||||
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 () {
|
||||
$scope.search(list.iterator);
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Prompt({
|
||||
hdr: 'Delete',
|
||||
body: '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');
|
||||
generator.reset();
|
||||
LoadBreadCrumbs();
|
||||
// Inject dynamic view
|
||||
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,
|
||||
// Load the list of options for Kind
|
||||
GetChoices({
|
||||
scope: $scope,
|
||||
url: defaultUrl,
|
||||
field: 'kind',
|
||||
variable: 'credential_kind_options'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: (!Empty($routeParams.user_id)) ? $routeParams.user_id : null,
|
||||
list: UserList,
|
||||
field: 'user'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: (!Empty($routeParams.team_id)) ? $routeParams.team_id : null,
|
||||
list: TeamList,
|
||||
field: 'team'
|
||||
});
|
||||
|
||||
if (!Empty($routeParams.user_id)) {
|
||||
// Get the username based on incoming route
|
||||
$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) {
|
||||
$scope.user_username = data.username;
|
||||
})
|
||||
.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)) {
|
||||
// Get the username based on incoming route
|
||||
$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) {
|
||||
$scope.team_name = data.name;
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve team. GET status: ' + status });
|
||||
});
|
||||
} else {
|
||||
// default type of owner to a user
|
||||
$scope.owner = 'user';
|
||||
OwnerChange({ scope: $scope });
|
||||
}
|
||||
|
||||
// Handle Kind change
|
||||
$scope.kindChange = function () {
|
||||
KindChange({ scope: $scope, form: form, reset: true });
|
||||
};
|
||||
|
||||
// Save
|
||||
$scope.formSave = function () {
|
||||
generator.clearApiErrors();
|
||||
FormSave({ scope: $scope, mode: 'add' });
|
||||
};
|
||||
|
||||
// Handle Owner change
|
||||
$scope.ownerChange = function () {
|
||||
OwnerChange({ scope: $scope });
|
||||
};
|
||||
|
||||
// Reset defaults
|
||||
$scope.formReset = function () {
|
||||
generator.reset();
|
||||
};
|
||||
|
||||
// Password change
|
||||
$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);
|
||||
};
|
||||
|
||||
// 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);
|
||||
}
|
||||
};
|
||||
|
||||
// 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();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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();
|
||||
$scope.id = id;
|
||||
|
||||
function setAskCheckboxes() {
|
||||
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").removeAttr("disabled");
|
||||
}
|
||||
master[fld + '_ask'] = $scope[fld + '_ask'];
|
||||
}
|
||||
|
||||
// Set kind field to the correct option
|
||||
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();
|
||||
}
|
||||
$scope.removeCredentialLoaded = $scope.$on('credentialLoaded', function () {
|
||||
LookUpInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: (!Empty($scope.user_id)) ? $scope.user_id : null,
|
||||
list: UserList,
|
||||
field: 'user'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: (!Empty($routeParams.user_id)) ? $routeParams.user_id : null,
|
||||
list: UserList,
|
||||
field: 'user'
|
||||
});
|
||||
LookUpInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: (!Empty($scope.team_id)) ? $scope.team_id : null,
|
||||
list: TeamList,
|
||||
field: 'team'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: (!Empty($routeParams.team_id)) ? $routeParams.team_id : null,
|
||||
list: TeamList,
|
||||
field: 'team'
|
||||
});
|
||||
setAskCheckboxes();
|
||||
KindChange({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
reset: false
|
||||
});
|
||||
OwnerChange({ scope: $scope });
|
||||
Wait('stop');
|
||||
});
|
||||
|
||||
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 + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
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 });
|
||||
});
|
||||
}
|
||||
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 + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
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 });
|
||||
});
|
||||
}
|
||||
else {
|
||||
// default type of owner to a user
|
||||
scope['owner'] = 'user';
|
||||
OwnerChange({ scope: scope });
|
||||
}
|
||||
|
||||
// Handle Kind change
|
||||
scope.kindChange = function () {
|
||||
KindChange({ scope: scope, form: form, reset: true });
|
||||
}
|
||||
|
||||
// Save
|
||||
scope.formSave = function() { generator.clearApiErrors(); FormSave({ scope: scope, mode: 'add' }) };
|
||||
|
||||
// Handle Owner change
|
||||
scope.ownerChange = function() {
|
||||
OwnerChange({ scope: scope });
|
||||
}
|
||||
|
||||
// Reset defaults
|
||||
scope.formReset = function() {
|
||||
generator.reset();
|
||||
//DebugForm({ form: CredentialForm, scope: scope });
|
||||
};
|
||||
|
||||
// Password change
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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'];
|
||||
|
||||
|
||||
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.
|
||||
|
||||
var defaultUrl=GetBasePath('credentials');
|
||||
var generator = GenerateForm;
|
||||
var form = CredentialForm;
|
||||
var scope = generator.inject(form, {mode: 'edit', related: true});
|
||||
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 = {};
|
||||
|
||||
function setAskCheckboxes() {
|
||||
for (var 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").removeAttr("disabled");
|
||||
}
|
||||
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];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scope.removeCredentialLoaded) {
|
||||
scope.removeCredentialLoaded();
|
||||
}
|
||||
scope.removeCredentialLoaded = scope.$on('credentialLoaded', function() {
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: (!Empty($scope['user_id'])) ? scope['user_id'] : null,
|
||||
list: UserList,
|
||||
field: 'user'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
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 });
|
||||
Wait('stop');
|
||||
});
|
||||
|
||||
if (scope.removeChoicesReady) {
|
||||
scope.removeChoicesReady();
|
||||
}
|
||||
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) {
|
||||
if (data[fld] !== null && data[fld] !== undefined) {
|
||||
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] =
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
if (!Empty(scope['user'])) {
|
||||
scope['owner'] = 'user';
|
||||
}
|
||||
else {
|
||||
scope['owner'] = 'team';
|
||||
}
|
||||
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];
|
||||
break;
|
||||
}
|
||||
}
|
||||
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'];
|
||||
break;
|
||||
case 'ssh':
|
||||
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'];
|
||||
break;
|
||||
}
|
||||
|
||||
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 });
|
||||
});
|
||||
});
|
||||
|
||||
Wait('start');
|
||||
|
||||
GetChoices({
|
||||
scope: scope,
|
||||
url: defaultUrl,
|
||||
field: 'kind',
|
||||
variable: 'credential_kind_options',
|
||||
callback: 'choicesReadyCredential'
|
||||
});
|
||||
|
||||
scope.showActivity = function() { Stream({ scope: scope }); }
|
||||
|
||||
// Save changes to the parent
|
||||
scope.formSave = function() { generator.clearApiErrors(); FormSave({ scope: scope, mode: 'edit' }) };
|
||||
|
||||
// Handle Owner change
|
||||
scope.ownerChange = function() {
|
||||
OwnerChange({ scope: scope });
|
||||
}
|
||||
|
||||
// Handle Kind change
|
||||
scope.kindChange = function () {
|
||||
KindChange({ scope: scope, form: form, reset: true });
|
||||
}
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
scope[fld] = master[fld];
|
||||
}
|
||||
setAskCheckboxes();
|
||||
KindChange({ scope: scope, form: form, reset: false });
|
||||
OwnerChange({ scope: scope });
|
||||
};
|
||||
|
||||
// Related set: Add button
|
||||
scope.add = function(set) {
|
||||
$rootScope.flashMessage = null;
|
||||
$location.path('/' + base + '/' + $routeParams.id + '/' + set + '/add');
|
||||
};
|
||||
|
||||
// Related set: Edit button
|
||||
scope.edit = function(set, id, name) {
|
||||
$rootScope.flashMessage = null;
|
||||
$location.path('/' + base + '/' + $routeParams.id + '/' + set + '/' + id);
|
||||
};
|
||||
|
||||
// Related set: Delete button
|
||||
scope['delete'] = function(set, itm_id, name, title) {
|
||||
$rootScope.flashMessage = null;
|
||||
|
||||
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);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
$('#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 + '?',
|
||||
action: action
|
||||
if ($scope.removeChoicesReady) {
|
||||
$scope.removeChoicesReady();
|
||||
}
|
||||
$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) {
|
||||
|
||||
var i, fld;
|
||||
|
||||
LoadBreadCrumbs({
|
||||
path: '/credentials/' + id,
|
||||
title: data.name
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Password change
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 {
|
||||
$("#" + fld + "-clear-btn").removeAttr("disabled");
|
||||
scope[fld] = '';
|
||||
scope[associated] = '';
|
||||
scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
|
||||
}
|
||||
}
|
||||
for (fld in form.fields) {
|
||||
if (data[fld] !== null && data[fld] !== undefined) {
|
||||
$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] =
|
||||
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.clear = function(fld, associated) {
|
||||
scope[fld] = '';
|
||||
scope[associated] = '';
|
||||
scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
|
||||
scope[form.name + '_form'].$setDirty();
|
||||
}
|
||||
if (!Empty($scope.user)) {
|
||||
$scope.owner = 'user';
|
||||
} else {
|
||||
$scope.owner = 'team';
|
||||
}
|
||||
master.owner = $scope.owner;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
break;
|
||||
case 'ssh':
|
||||
$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;
|
||||
break;
|
||||
}
|
||||
|
||||
$scope.$emit('credentialLoaded');
|
||||
})
|
||||
.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,
|
||||
url: defaultUrl,
|
||||
field: 'kind',
|
||||
variable: 'credential_kind_options',
|
||||
callback: 'choicesReadyCredential'
|
||||
});
|
||||
|
||||
$scope.showActivity = function () {
|
||||
Stream({ scope: $scope });
|
||||
};
|
||||
|
||||
// Save changes to the parent
|
||||
$scope.formSave = function () {
|
||||
generator.clearApiErrors();
|
||||
FormSave({ scope: $scope, mode: 'edit' });
|
||||
};
|
||||
|
||||
// Handle Owner change
|
||||
$scope.ownerChange = function () {
|
||||
OwnerChange({ scope: $scope });
|
||||
};
|
||||
|
||||
// Handle Kind change
|
||||
$scope.kindChange = function () {
|
||||
KindChange({ scope: $scope, form: form, reset: true });
|
||||
};
|
||||
|
||||
// Cancel
|
||||
$scope.formReset = function () {
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
$scope[fld] = master[fld];
|
||||
}
|
||||
setAskCheckboxes();
|
||||
KindChange({ scope: $scope, form: form, reset: false });
|
||||
OwnerChange({ scope: $scope });
|
||||
};
|
||||
|
||||
// Related set: Add button
|
||||
$scope.add = function (set) {
|
||||
$rootScope.flashMessage = null;
|
||||
$location.path('/' + base + '/' + $routeParams.id + '/' + set + '/add');
|
||||
};
|
||||
|
||||
// Related set: Edit button
|
||||
$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) {
|
||||
$rootScope.flashMessage = null;
|
||||
|
||||
var action = function () {
|
||||
var url = defaultUrl + id + '/' + set + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.post({
|
||||
id: itm_id,
|
||||
disassociate: 1
|
||||
})
|
||||
.success(function () {
|
||||
$('#prompt-modal').modal('hide');
|
||||
$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 + '?',
|
||||
action: action
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// Password change
|
||||
$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);
|
||||
};
|
||||
|
||||
// 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 {
|
||||
$("#" + fld + "-clear-btn").removeAttr("disabled");
|
||||
$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();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
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'
|
||||
];
|
||||
@ -3,43 +3,55 @@
|
||||
*
|
||||
*
|
||||
* Home.js
|
||||
*
|
||||
*
|
||||
* Controller functions for Home tab
|
||||
*
|
||||
*/
|
||||
|
||||
'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",
|
||||
ngClick: "refresh()"
|
||||
},
|
||||
},
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
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;
|
||||
|
||||
if (!$routeParams['login']) {
|
||||
waitCount = 4;
|
||||
loadedCount = 0;
|
||||
|
||||
if (!$routeParams.login) {
|
||||
// If we're not logging in, start the Wait widget. Otherwise, it's already running.
|
||||
Wait('start');
|
||||
}
|
||||
@ -47,297 +59,366 @@ 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 ) {
|
||||
loadedCount++;
|
||||
if (loadedCount === waitCount) {
|
||||
Wait('stop');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
$scope.showActivity = function() { Stream({ scope: $scope }); }
|
||||
InventorySyncStatus({
|
||||
scope: $scope,
|
||||
target: 'container2',
|
||||
dashboard: data
|
||||
});
|
||||
SCMSyncStatus({
|
||||
scope: $scope,
|
||||
target: 'container4',
|
||||
dashboard: data
|
||||
});
|
||||
ObjectCount({
|
||||
scope: $scope,
|
||||
target: 'container3',
|
||||
dashboard: data
|
||||
});
|
||||
});
|
||||
|
||||
$scope.refresh = function() {
|
||||
$scope.showActivity = function () {
|
||||
Stream({
|
||||
scope: $scope
|
||||
});
|
||||
};
|
||||
|
||||
$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.
|
||||
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['home_groups'][i]['inventory_name'] = scope['home_groups'][i]['summary_fields']['inventory']['name'];
|
||||
scope.removePostRefresh = scope.$on('PostRefresh', function () {
|
||||
var i, hosts_status, stat;
|
||||
for (i = 0; i < scope.home_groups.length; i++) {
|
||||
|
||||
stat = GetSyncStatusMsg({
|
||||
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
|
||||
}); // from helpers/Groups.js
|
||||
|
||||
}); // from helpers/Groups.js
|
||||
|
||||
hosts_status = GetHostsStatusMsg({
|
||||
active_failures: scope.home_groups[i].hosts_with_active_failures,
|
||||
total_hosts: scope.home_groups[i].total_hosts,
|
||||
inventory_id: scope.home_groups[i].inventory,
|
||||
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].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];
|
||||
break;
|
||||
}
|
||||
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];
|
||||
break;
|
||||
}
|
||||
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.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.search(list.iterator);
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
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.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,
|
||||
scope: scope,
|
||||
url: data.related.update,
|
||||
group_name: data.summary_fields.group.name,
|
||||
group_name: data.summary_fields.group.name,
|
||||
group_source: data.source,
|
||||
tree_id: group.id,
|
||||
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.
|
||||
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.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.toggle_host_enabled = function(id, sources) { ToggleHostEnabled({ host_id: id, external_source: sources, scope: scope }); }
|
||||
scope.showActivity = function () {
|
||||
Stream({
|
||||
scope: scope
|
||||
});
|
||||
};
|
||||
|
||||
scope.editHost = function(host_id, host_name) {
|
||||
var host = Find({ list: scope.hosts, key: 'id', val: host_id });
|
||||
scope.toggle_host_enabled = function (id, sources) {
|
||||
ToggleHostEnabled({
|
||||
host_id: id,
|
||||
external_source: sources,
|
||||
scope: scope
|
||||
});
|
||||
};
|
||||
|
||||
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'
|
||||
];
|
||||
];
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,180 +3,169 @@
|
||||
*
|
||||
*
|
||||
* JobEvents.js
|
||||
*
|
||||
*
|
||||
* Controller functions for the Job Events model.
|
||||
*
|
||||
*/
|
||||
|
||||
'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
|
||||
|
||||
if (scope.removeSetHostLinks) {
|
||||
scope.removeSetHostLinks();
|
||||
$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();
|
||||
}
|
||||
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);
|
||||
rows = (n) ? n.length : 1;
|
||||
rows = (rows > 10) ? 10 : rows;
|
||||
found = true;
|
||||
html += "<div class=\"form-group\">\n";
|
||||
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] !== '') ) {
|
||||
html += "<div class=\"form-group\">\n";
|
||||
html += "<label>";
|
||||
switch(fld) {
|
||||
case 'msg':
|
||||
case 'stdout':
|
||||
html += 'Output:';
|
||||
break;
|
||||
case 'stderr':
|
||||
html += 'Error:';
|
||||
break;
|
||||
}
|
||||
html += "</label>\n";
|
||||
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 ) {
|
||||
//html += "<textarea readonly class="
|
||||
var txt = '';
|
||||
for (var i=0; i < eventData.res[fld].length; i++) {
|
||||
txt += eventData.res[fld][i];
|
||||
}
|
||||
n = txt.match(/\n/g);
|
||||
rows = (n) ? n.length : 1;
|
||||
rows = (rows > 10) ? 10 : rows;
|
||||
if (txt !== '') {
|
||||
|
||||
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;
|
||||
html += "<div class=\"form-group\">\n";
|
||||
html += "<label>Traceback:</label>\n";
|
||||
html += "<textarea readonly class=\"form-control nowrap\" rows=\"" + rows + "\">" + eventData.res + "</textarea>\n";
|
||||
html += "</div>\n";
|
||||
} 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>Results:</label>\n";
|
||||
html += "<textarea readonly class=\"form-control nowrap mono-space\" rows=\"" + rows + "\">" + txt + "</textarea>\n";
|
||||
html += "<label>";
|
||||
switch (fld) {
|
||||
case 'msg':
|
||||
case 'stdout':
|
||||
html += 'Output:';
|
||||
break;
|
||||
case 'stderr':
|
||||
html += 'Error:';
|
||||
break;
|
||||
}
|
||||
html += "</label>\n";
|
||||
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 == "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";
|
||||
html += "</div>\n";
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
html = (found) ? "<form class=\"event-form\">\n" + html + "</form>\n" : '';
|
||||
}
|
||||
if (fld === "results" && Array.isArray(eventData.res[fld]) && eventData.res[fld].length > 0) {
|
||||
//html += "<textarea readonly class="
|
||||
txt = '';
|
||||
for (i = 0; i < eventData.res[fld].length; i++) {
|
||||
txt += eventData.res[fld][i];
|
||||
}
|
||||
n = txt.match(/\n/g);
|
||||
rows = (n) ? n.length : 1;
|
||||
rows = (rows > 10) ? 10 : rows;
|
||||
if (txt !== '') {
|
||||
html += "<div class=\"form-group\">\n";
|
||||
html += "<label>Results:</label>\n";
|
||||
html += "<textarea readonly class=\"form-control nowrap mono-space\" rows=\"" + rows + "\">" + txt + "</textarea>\n";
|
||||
html += "</div>\n";
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
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";
|
||||
html += "</div>\n";
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
scope.removePostRefresh = scope.$on('PostRefresh', function() {
|
||||
|
||||
if ($scope.removePostRefresh) {
|
||||
$scope.removePostRefresh();
|
||||
}
|
||||
$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';
|
||||
set[i]['class'] = 'parentNode';
|
||||
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].ngclick = "toggleChildren(" + set[i].id + ", \"" + set[i].related.children + "\")";
|
||||
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';
|
||||
set[i]['class'] = 'childNode';
|
||||
set[i].event_detail = formatJSON(set[i].event_data);
|
||||
}
|
||||
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]['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 (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";
|
||||
}
|
||||
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 ($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";
|
||||
}
|
||||
}
|
||||
//cDate = new Date(set[i].created);
|
||||
//set[i].created = FormatDate(cDate);
|
||||
@ -185,162 +174,179 @@ 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);
|
||||
})
|
||||
.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 });
|
||||
.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) {
|
||||
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 });
|
||||
|
||||
var page = ($routeParams.page) ? parseInt($routeParams.page) - 1 : null;
|
||||
PaginateInit({ scope: scope, list: list, url: defaultUrl, page: page });
|
||||
SearchInit({
|
||||
scope: $scope,
|
||||
set: 'jobevents',
|
||||
list: list,
|
||||
url: defaultUrl
|
||||
});
|
||||
|
||||
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.toggleChildren = function(id, children) {
|
||||
|
||||
$scope.search(list.iterator, $routeParams.page);
|
||||
|
||||
$scope.toggleChildren = function (id, children) {
|
||||
ToggleChildren({
|
||||
scope: scope,
|
||||
scope: $scope,
|
||||
list: list,
|
||||
id: id,
|
||||
children: children
|
||||
});
|
||||
}
|
||||
|
||||
scope.viewJobEvent = function(id) {
|
||||
EventView({ event_id: id });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
scope.refresh = function() {
|
||||
scope['jobSearchSpin'] = true;
|
||||
scope['jobLoading'] = true;
|
||||
Wait('start');
|
||||
Refresh({ scope: scope, set: 'jobevents', iterator: 'jobevent', url: scope['current_url'] });
|
||||
}
|
||||
$scope.viewJobEvent = function (id) {
|
||||
EventView({
|
||||
event_id: id
|
||||
});
|
||||
};
|
||||
|
||||
$scope.refresh = function () {
|
||||
$scope.jobSearchSpin = true;
|
||||
$scope.jobLoading = true;
|
||||
Wait('start');
|
||||
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});
|
||||
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) {
|
||||
case 'status':
|
||||
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);
|
||||
break;
|
||||
case 'host':
|
||||
if (data['summary_fields'] && data['summary_fields']['host']) {
|
||||
scope['host'] = data['summary_fields']['host']['name'];
|
||||
}
|
||||
break;
|
||||
case 'id':
|
||||
case 'task':
|
||||
case 'play':
|
||||
scope[fld] = data[fld];
|
||||
break;
|
||||
case 'start':
|
||||
case 'end':
|
||||
if (data['event_data'] && data['event_data']['res'] && data['event_data']['res'][fld] !== undefined) {
|
||||
var cDate = new Date(data['event_data']['res'][fld]);
|
||||
scope[fld] = FormatDate(cDate);
|
||||
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();
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Wait('start');
|
||||
Rest.setUrl(defaultUrl);
|
||||
Rest.get()
|
||||
.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';
|
||||
}
|
||||
break;
|
||||
case 'msg':
|
||||
case 'stdout':
|
||||
case 'stderr':
|
||||
case 'delta':
|
||||
case 'rc':
|
||||
if (data['event_data'] && data['event_data']['res'] && data['event_data']['res'][fld] !== undefined) {
|
||||
scope[fld] = data['event_data']['res'][fld];
|
||||
if (form.fields[fld].type == 'textarea') {
|
||||
var n = data['event_data']['res'][fld].match(/\n/g);
|
||||
var rows = (n) ? n.length : 1;
|
||||
rows = (rows > 15) ? 5 : rows;
|
||||
$('textarea[name="' + fld + '"]').attr('rows',rows);
|
||||
case 'created':
|
||||
cDate = new Date(data.created);
|
||||
$scope.created = FormatDate(cDate);
|
||||
break;
|
||||
case 'host':
|
||||
if (data.summary_fields && data.summary_fields.host) {
|
||||
$scope.host = data.summary_fields.host.name;
|
||||
}
|
||||
break;
|
||||
case 'id':
|
||||
case 'task':
|
||||
case 'play':
|
||||
$scope[fld] = data[fld];
|
||||
break;
|
||||
case 'start':
|
||||
case 'end':
|
||||
if (data.event_data && data.event_data.res && data.event_data.res[fld] !== undefined) {
|
||||
cDate = new Date(data.event_data.res[fld]);
|
||||
$scope[fld] = FormatDate(cDate);
|
||||
}
|
||||
break;
|
||||
case 'msg':
|
||||
case 'stdout':
|
||||
case 'stderr':
|
||||
case 'delta':
|
||||
case 'rc':
|
||||
if (data.event_data && data.event_data.res && data.event_data.res[fld] !== undefined) {
|
||||
$scope[fld] = data.event_data.res[fld];
|
||||
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);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'module_name':
|
||||
case 'module_args':
|
||||
if (data['event_data']['res'] && data['event_data']['res']['invocation']) {
|
||||
scope[fld] = data['event_data']['res']['invocation'][fld];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
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 });
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'module_name':
|
||||
case 'module_args':
|
||||
if (data.event_data.res && data.event_data.res.invocation) {
|
||||
$scope[fld] = data.event_data.res.invocation.fld;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
Wait('stop');
|
||||
})
|
||||
.error(function (data) {
|
||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve host: ' + $routeParams.event_id +
|
||||
'. GET status: ' + status });
|
||||
});
|
||||
|
||||
scope.navigateBack = function() {
|
||||
var url = '/jobs/' + $routeParams.job_id + '/job_events';
|
||||
if ($routeParams.page) {
|
||||
url += '?page=' + $routeParams.page;
|
||||
}
|
||||
$location.url(url);
|
||||
}
|
||||
$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'
|
||||
];
|
||||
@ -3,145 +3,165 @@
|
||||
*
|
||||
*
|
||||
* JobHosts.js
|
||||
*
|
||||
*
|
||||
* Controller functions for the Job Hosts Summary model.
|
||||
*
|
||||
*/
|
||||
|
||||
'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') {
|
||||
list.index = false;
|
||||
}
|
||||
else {
|
||||
list.index = true;
|
||||
if (base === 'hosts') {
|
||||
list.index = false;
|
||||
} 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;
|
||||
if (base === 'hosts') {
|
||||
$scope.job_id = null;
|
||||
$scope.host_id = $routeParams.id;
|
||||
} else {
|
||||
$scope.job_id = $routeParams.id;
|
||||
$scope.host_id = null;
|
||||
}
|
||||
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) +
|
||||
" Click to view details.";
|
||||
scope.jobhosts[i].statusLinkTo = '/#/jobs/' + scope.jobhosts[i].job + '/job_events/?host=' +
|
||||
escape(scope.jobhosts[i].summary_fields.host.name);
|
||||
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=' +
|
||||
encodeURI($scope.jobhosts[i].summary_fields.host.name);
|
||||
}
|
||||
|
||||
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.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')) {
|
||||
if ($rootScope.timer) {
|
||||
clearInterval($rootScope.timer);
|
||||
}
|
||||
}
|
||||
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 });
|
||||
});
|
||||
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.get()
|
||||
.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);
|
||||
})
|
||||
.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 {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
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']);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
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']) {
|
||||
scope[list.iterator + 'SearchField'] = 'host';
|
||||
scope[list.iterator + 'SearchValue'] = $routeParams['host_name'];
|
||||
scope[list.iterator + 'SearchFieldLabel'] = list.fields['host'].label;
|
||||
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.search(list.iterator);
|
||||
|
||||
|
||||
scope.showEvents = function(host_name, last_job) {
|
||||
|
||||
$scope.search(list.iterator);
|
||||
|
||||
|
||||
$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));
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to lookup last job: ' + last_job + '. GET status: ' + status });
|
||||
});
|
||||
}
|
||||
.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) {
|
||||
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.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.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
@ -3,7 +3,7 @@
|
||||
*
|
||||
*
|
||||
* Jobs.js
|
||||
*
|
||||
*
|
||||
* Controller functions for the Job model.
|
||||
*
|
||||
*/
|
||||
@ -12,148 +12,154 @@
|
||||
|
||||
'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;
|
||||
|
||||
generator.inject(list, { mode: 'edit', scope: $scope });
|
||||
|
||||
$rootScope.flashMessage = null;
|
||||
scope.selected = [];
|
||||
|
||||
if (scope.removePostRefresh) {
|
||||
scope.removePostRefresh();
|
||||
$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;
|
||||
|
||||
|
||||
if (data.status === 'pending' || data.status === 'running' || data.status === 'waiting') {
|
||||
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,128 +170,124 @@ 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',
|
||||
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
|
||||
'ProcessErrors','GetBasePath', 'LookUpInit', 'SubmitJob', 'FormatDate', 'Refresh', 'JobStatusToolTip',
|
||||
'Empty', 'Wait'
|
||||
];
|
||||
JobsListCtrl.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobList',
|
||||
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
|
||||
'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,
|
||||
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) {
|
||||
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
var defaultUrl= GetBasePath('jobs'),
|
||||
ClearScope();
|
||||
|
||||
var defaultUrl = GetBasePath('jobs'),
|
||||
generator = GenerateForm,
|
||||
form = JobForm,
|
||||
scope = generator.inject(form, {mode: 'edit', related: true}),
|
||||
master = {},
|
||||
id = $routeParams.id,
|
||||
relatedSets = {},
|
||||
loadingFinishedCount = 0;
|
||||
|
||||
generator.inject(form, { mode: 'edit', related: true, scope: $scope });
|
||||
generator.reset();
|
||||
|
||||
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) {
|
||||
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) {
|
||||
$scope.playbook_options = [];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
$scope.playbook_options.push(data[i]);
|
||||
}
|
||||
scope.$emit('jobTemplateLoadFinished');
|
||||
$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) {
|
||||
|
||||
getPlaybooks(scope.project);
|
||||
$scope.jobLoadedRemove = $scope.$on('jobLoaded', function (e, related_cloud_credential) {
|
||||
|
||||
scope[form.name + 'ReadOnly'] = (scope.status === 'new') ? false : true;
|
||||
|
||||
$('#forks-slider').slider("option", "value", scope.forks);
|
||||
getPlaybooks($scope.project);
|
||||
|
||||
$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');
|
||||
$('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) {
|
||||
// The initial template load finished. Now load related jobs, which
|
||||
@ -295,16 +297,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,88 +326,87 @@ 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) {
|
||||
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;
|
||||
LoadBreadCrumbs();
|
||||
for (fld in form.fields) {
|
||||
if (fld !== 'variables' && data[fld] !== null && data[fld] !== undefined) {
|
||||
if (form.fields[fld].type === 'select') {
|
||||
if (scope[fld + '_options'] && scope[fld + '_options'].length > 0) {
|
||||
for (i=0; i < scope[fld + '_options'].length; i++) {
|
||||
if (data[fld] === scope[fld + '_options'][i].value) {
|
||||
scope[fld] = scope[fld + '_options'][i];
|
||||
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];
|
||||
master[fld] = $scope[fld];
|
||||
}
|
||||
|
||||
scope.id = data.id;
|
||||
scope.name = (data.summary_fields && data.summary_fields.job_template) ? data.summary_fields.job_template.name : '';
|
||||
|
||||
$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);
|
||||
$scope.variables = jsyaml.safeDump(json_obj);
|
||||
}
|
||||
master.variables = scope.variables;
|
||||
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] =
|
||||
$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];
|
||||
}
|
||||
|
||||
|
||||
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.created = FormatDate(cDate);
|
||||
} else {
|
||||
$scope[fld] = data[fld];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scope.statusToolTip = JobStatusToolTip(data.status);
|
||||
|
||||
$('form[name="jobs_form"] input[type="text"], form[name="jobs_form"] jobs_form textarea').attr('readonly','readonly');
|
||||
$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;
|
||||
$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 };
|
||||
relatedSets[set] = {
|
||||
url: related[set],
|
||||
iterator: form.related[set].iterator
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
scope.stdout_rows = calcRows(scope.result_stdout);
|
||||
|
||||
scope.traceback_rows = calcRows(scope.result_traceback);
|
||||
$scope.stdout_rows = calcRows($scope.result_stdout);
|
||||
|
||||
$scope.traceback_rows = calcRows($scope.result_traceback);
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: data.inventory,
|
||||
list: InventoryList,
|
||||
@ -402,7 +414,7 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams,
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: data.credential,
|
||||
list: CredentialList,
|
||||
@ -410,7 +422,7 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams,
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: data.project,
|
||||
list: ProjectList,
|
||||
@ -418,47 +430,55 @@ function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams,
|
||||
});
|
||||
|
||||
// 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);
|
||||
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);
|
||||
})
|
||||
.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, form, { 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) {
|
||||
.error(function (data, status) {
|
||||
Wait('stop');
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Attempt to load job failed. GET returned status: ' + 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',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit',
|
||||
'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList', 'ProjectList', 'LookUpInit', 'PromptPasswords',
|
||||
'GetBasePath', 'md5Setup', 'FormatDate', 'JobStatusToolTip', 'Wait'
|
||||
];
|
||||
|
||||
@ -3,276 +3,292 @@
|
||||
*
|
||||
*
|
||||
* Organizations.js
|
||||
*
|
||||
*
|
||||
* Controller functions for Organization model.
|
||||
*
|
||||
*/
|
||||
|
||||
'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) {
|
||||
|
||||
ClearScope();
|
||||
|
||||
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;
|
||||
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 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.addOrganization = function () {
|
||||
$location.path($location.path() + '/add');
|
||||
};
|
||||
|
||||
$scope.editOrganization = function (id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
};
|
||||
|
||||
$scope.deleteOrganization = function (id, name) {
|
||||
|
||||
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 () {
|
||||
$scope.search(list.iterator);
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({
|
||||
hdr: 'Delete',
|
||||
body: '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'
|
||||
];
|
||||
|
||||
|
||||
function OrganizationsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath,
|
||||
ReturnToCaller, Wait) {
|
||||
|
||||
// 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);
|
||||
ClearScope();
|
||||
|
||||
// Inject dynamic view
|
||||
var generator = GenerateForm,
|
||||
form = OrganizationForm,
|
||||
base = $location.path().replace(/^\//, '').split('/')[0];
|
||||
|
||||
scope.showActivity = function() { Stream({ scope: scope }); }
|
||||
generator.inject(form, { mode: 'add', related: false, scope: $scope});
|
||||
generator.reset();
|
||||
|
||||
scope.addOrganization = function() {
|
||||
$location.path($location.path() + '/add');
|
||||
}
|
||||
LoadBreadCrumbs();
|
||||
|
||||
scope.editOrganization = function(id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
}
|
||||
|
||||
scope.deleteOrganization = function(id, name) {
|
||||
|
||||
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);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||
});
|
||||
};
|
||||
// Save
|
||||
$scope.formSave = function () {
|
||||
generator.clearApiErrors();
|
||||
Wait('start');
|
||||
var url = GetBasePath(base);
|
||||
url += (base !== 'organizations') ? $routeParams.project_id + '/organizations/' : '';
|
||||
Rest.setUrl(url);
|
||||
Rest.post({ name: $scope.name, description: $scope.description })
|
||||
.success(function (data) {
|
||||
Wait('stop');
|
||||
if (base === 'organizations') {
|
||||
$rootScope.flashMessage = "New organization successfully created!";
|
||||
$location.path('/organizations/' + data.id);
|
||||
} else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
|
||||
msg: 'Failed to add new organization. Post returned status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete ' + name + '?',
|
||||
action: action
|
||||
// Cancel
|
||||
$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'
|
||||
];
|
||||
|
||||
|
||||
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,
|
||||
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();
|
||||
|
||||
// After the Organization is loaded, retrieve each related set
|
||||
if ($scope.organizationLoadedRemove) {
|
||||
$scope.organizationLoadedRemove();
|
||||
}
|
||||
$scope.organizationLoadedRemove = $scope.$on('organizationLoaded', function () {
|
||||
for (var set in relatedSets) {
|
||||
$scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
Wait('stop');
|
||||
});
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Wait('start');
|
||||
Rest.setUrl(defaultUrl + id + '/');
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
var fld, related, set;
|
||||
LoadBreadCrumbs({ path: '/organizations/' + id, title: data.name });
|
||||
for (fld in form.fields) {
|
||||
if (data[fld]) {
|
||||
$scope[fld] = data[fld];
|
||||
master[fld] = data[fld];
|
||||
}
|
||||
}
|
||||
related = data.related;
|
||||
for (set in form.related) {
|
||||
if (related[set]) {
|
||||
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');
|
||||
})
|
||||
.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 () {
|
||||
var fld, params = {};
|
||||
generator.clearApiErrors();
|
||||
Wait('start');
|
||||
for (fld in form.fields) {
|
||||
params[fld] = $scope[fld];
|
||||
}
|
||||
Rest.setUrl(defaultUrl + id + '/');
|
||||
Rest.put(params)
|
||||
.success(function () {
|
||||
Wait('stop');
|
||||
master = params;
|
||||
$rootScope.flashMessage = "Your changes were successfully saved!";
|
||||
})
|
||||
.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
|
||||
});
|
||||
};
|
||||
|
||||
// Reset the form
|
||||
$scope.formReset = function () {
|
||||
$rootScope.flashMessage = null;
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
$scope[fld] = master[fld];
|
||||
}
|
||||
};
|
||||
|
||||
// Related set: Add button
|
||||
$scope.add = function (set) {
|
||||
$rootScope.flashMessage = null;
|
||||
$location.path('/' + base + '/' + $routeParams.organization_id + '/' + set);
|
||||
};
|
||||
|
||||
// Related set: Edit button
|
||||
$scope.edit = function (set, id) {
|
||||
$rootScope.flashMessage = null;
|
||||
$location.path('/' + set + '/' + id);
|
||||
};
|
||||
|
||||
// Related set: Delete button
|
||||
$scope['delete'] = function (set, itm_id, name, title) {
|
||||
$rootScope.flashMessage = null;
|
||||
|
||||
var action = function () {
|
||||
Wait('start');
|
||||
var url = defaultUrl + $routeParams.organization_id + '/' + set + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.post({ id: itm_id, disassociate: 1 })
|
||||
.success(function () {
|
||||
$('#prompt-modal').modal('hide');
|
||||
$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 + '?',
|
||||
action: action
|
||||
});
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
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,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, GetBasePath,
|
||||
ReturnToCaller, Wait)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
// 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');
|
||||
generator.reset();
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
// Save
|
||||
scope.formSave = function() {
|
||||
generator.clearApiErrors();
|
||||
Wait('start');
|
||||
var url = GetBasePath(base);
|
||||
url += (base != 'organizations') ? $routeParams['project_id'] + '/organizations/' : '';
|
||||
Rest.setUrl(url);
|
||||
Rest.post({ name: $scope.name,
|
||||
description: $scope.description })
|
||||
.success( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
if (base == 'organizations') {
|
||||
$rootScope.flashMessage = "New organization successfully created!";
|
||||
$location.path('/organizations/' + data.id);
|
||||
}
|
||||
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 });
|
||||
});
|
||||
};
|
||||
|
||||
// Cancel
|
||||
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'];
|
||||
|
||||
|
||||
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.
|
||||
|
||||
// Inject dynamic view
|
||||
var form = OrganizationForm;
|
||||
var generator = GenerateForm;
|
||||
var scope = GenerateForm.inject(form, {mode: 'edit', related: true});
|
||||
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();
|
||||
}
|
||||
scope.organizationLoadedRemove = scope.$on('organizationLoaded', function() {
|
||||
for (var set in relatedSets) {
|
||||
scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
Wait('stop');
|
||||
});
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Wait('start');
|
||||
Rest.setUrl(defaultUrl + id + '/');
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
LoadBreadCrumbs({ path: '/organizations/' + id, title: data.name });
|
||||
for (var fld in form.fields) {
|
||||
if (data[fld]) {
|
||||
scope[fld] = data[fld];
|
||||
master[fld] = data[fld];
|
||||
}
|
||||
}
|
||||
var related = data.related;
|
||||
for (var set in form.related) {
|
||||
if (related[set]) {
|
||||
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');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
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() {
|
||||
generator.clearApiErrors();
|
||||
Wait('start');
|
||||
var params = {};
|
||||
for (var fld in form.fields) {
|
||||
params[fld] = scope[fld];
|
||||
}
|
||||
Rest.setUrl(defaultUrl + id + '/');
|
||||
Rest.put(params)
|
||||
.success( function(data, status, headers, config) {
|
||||
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 });
|
||||
});
|
||||
};
|
||||
|
||||
scope.showActivity = function() { Stream({ scope: scope }); }
|
||||
|
||||
// Reset the form
|
||||
scope.formReset = function() {
|
||||
$rootScope.flashMessage = null;
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
scope[fld] = master[fld];
|
||||
}
|
||||
};
|
||||
|
||||
// Related set: Add button
|
||||
scope.add = function(set) {
|
||||
$rootScope.flashMessage = null;
|
||||
$location.path('/' + base + '/' + $routeParams.organization_id + '/' + set);
|
||||
};
|
||||
|
||||
// Related set: Edit button
|
||||
scope.edit = function(set, id, name) {
|
||||
$rootScope.flashMessage = null;
|
||||
$location.path('/' + set + '/' + id);
|
||||
};
|
||||
|
||||
// Related set: Delete button
|
||||
scope['delete'] = function(set, itm_id, name, title) {
|
||||
$rootScope.flashMessage = null;
|
||||
|
||||
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');
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(form.related[set].iterator);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
$('#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 + '?',
|
||||
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'
|
||||
];
|
||||
@ -3,310 +3,319 @@
|
||||
*
|
||||
*
|
||||
* Permissions.js
|
||||
*
|
||||
*
|
||||
* Controller functions for Permissions model.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
'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 = [];
|
||||
|
||||
CheckAccess({ scope: scope });
|
||||
|
||||
if (scope.removePostRefresh) {
|
||||
scope.removePostRefresh();
|
||||
|
||||
$scope.selected = [];
|
||||
|
||||
CheckAccess({
|
||||
scope: $scope
|
||||
});
|
||||
|
||||
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) {
|
||||
$location.path($location.path() + '/add');
|
||||
}
|
||||
}
|
||||
$scope.addPermission = function () {
|
||||
if ($scope.PermissionAddAllowed) {
|
||||
$location.path($location.path() + '/add');
|
||||
}
|
||||
};
|
||||
|
||||
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'); });
|
||||
$('#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);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
if (scope.PermissionAddAllowed) {
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete ' + name + '?',
|
||||
action: action
|
||||
});
|
||||
}
|
||||
}
|
||||
$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');
|
||||
});
|
||||
$('#prompt-modal').modal('hide');
|
||||
var url = GetBasePath('base') + 'permissions/' + id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.destroy()
|
||||
.success(function () {
|
||||
$scope.search(list.iterator);
|
||||
})
|
||||
.error(function (data, status) {
|
||||
Wait('stop');
|
||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
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',
|
||||
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller',
|
||||
'ClearScope', 'ProcessErrors', 'GetBasePath', 'CheckAccess', 'Wait'
|
||||
];
|
||||
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,
|
||||
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.
|
||||
function PermissionsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, PermissionsForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope,
|
||||
GetBasePath, ReturnToCaller, InventoryList, ProjectList, LookUpInit, CheckAccess,
|
||||
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 = {};
|
||||
|
||||
CheckAccess({ scope: scope })
|
||||
generator.reset();
|
||||
LoadBreadCrumbs();
|
||||
|
||||
scope['inventoryrequired'] = true;
|
||||
scope['projectrequired'] = false;
|
||||
scope.category = 'Inventory';
|
||||
master.category = 'Inventory';
|
||||
master.inventoryrequired = true;
|
||||
master.projectrequired = false;
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: null,
|
||||
list: InventoryList,
|
||||
field: 'inventory'
|
||||
});
|
||||
// Inject dynamic view
|
||||
var form = PermissionsForm,
|
||||
generator = GenerateForm,
|
||||
id = ($routeParams.user_id !== undefined) ? $routeParams.user_id : $routeParams.team_id,
|
||||
base = $location.path().replace(/^\//, '').split('/')[0],
|
||||
master = {};
|
||||
|
||||
generator.inject(form, { mode: 'add', related: false, scope: $scope });
|
||||
CheckAccess({ scope: $scope });
|
||||
generator.reset();
|
||||
LoadBreadCrumbs();
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: null,
|
||||
list: ProjectList,
|
||||
field: 'project'
|
||||
});
|
||||
$scope.inventoryrequired = true;
|
||||
$scope.projectrequired = false;
|
||||
$scope.category = 'Inventory';
|
||||
master.category = 'Inventory';
|
||||
master.inventoryrequired = true;
|
||||
master.projectrequired = false;
|
||||
|
||||
// Save
|
||||
scope.formSave = function() {
|
||||
generator.clearApiErrors();
|
||||
Wait('start');
|
||||
if (scope.PermissionAddAllowed) {
|
||||
var data = {};
|
||||
for (var fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
var url = (base == 'teams') ? GetBasePath('teams') + id + '/permissions/' : GetBasePath('users') + id + '/permissions/';
|
||||
Rest.setUrl(url);
|
||||
Rest.post(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
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');
|
||||
}
|
||||
};
|
||||
LookUpInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: null,
|
||||
list: InventoryList,
|
||||
field: 'inventory'
|
||||
});
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
$rootScope.flashMessage = null;
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
scope[fld] = master[fld];
|
||||
}
|
||||
scope.selectCategory();
|
||||
};
|
||||
|
||||
scope.selectCategory = function() { PermissionCategoryChange({ scope: scope, reset: true }); };
|
||||
|
||||
LookUpInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: null,
|
||||
list: ProjectList,
|
||||
field: 'project'
|
||||
});
|
||||
|
||||
scope.selectCategory();
|
||||
// Save
|
||||
$scope.formSave = function () {
|
||||
var fld, url, data = {};
|
||||
generator.clearApiErrors();
|
||||
Wait('start');
|
||||
if ($scope.PermissionAddAllowed) {
|
||||
data = {};
|
||||
for (fld in form.fields) {
|
||||
data[fld] = $scope[fld];
|
||||
}
|
||||
url = (base === 'teams') ? GetBasePath('teams') + id + '/permissions/' : GetBasePath('users') + id + '/permissions/';
|
||||
Rest.setUrl(url);
|
||||
Rest.post(data)
|
||||
.success(function () {
|
||||
Wait('stop');
|
||||
ReturnToCaller(1);
|
||||
})
|
||||
.error(function (data, status) {
|
||||
Wait('stop');
|
||||
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');
|
||||
}
|
||||
};
|
||||
|
||||
// Cancel
|
||||
$scope.formReset = function () {
|
||||
$rootScope.flashMessage = null;
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
$scope[fld] = master[fld];
|
||||
}
|
||||
$scope.selectCategory();
|
||||
};
|
||||
|
||||
$scope.selectCategory = function () {
|
||||
PermissionCategoryChange({ scope: $scope, reset: true });
|
||||
};
|
||||
|
||||
|
||||
$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) {
|
||||
|
||||
ClearScope();
|
||||
|
||||
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 + '/';
|
||||
generator.reset();
|
||||
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) {
|
||||
|
||||
LoadBreadCrumbs({ path: '/users/' + base_id + '/permissions/' + id, title: data.name });
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Wait('start');
|
||||
Rest.setUrl(defaultUrl);
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
var fld, sourceModel, sourceField;
|
||||
LoadBreadCrumbs({ path: '/users/' + base_id + '/permissions/' + id, title: data.name });
|
||||
for (fld in form.fields) {
|
||||
if (data[fld]) {
|
||||
if (form.fields[fld].sourceModel) {
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
for (var 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];
|
||||
master[sourceModel + '_' + sourceField] = data.summary_fields[sourceModel][sourceField];
|
||||
}
|
||||
scope[fld] = data[fld];
|
||||
master[fld] = scope[fld];
|
||||
}
|
||||
}
|
||||
$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
|
||||
|
||||
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
|
||||
LookUpInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: data.inventory,
|
||||
list: InventoryList,
|
||||
field: 'inventory'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: data.inventory,
|
||||
list: InventoryList,
|
||||
field: 'inventory'
|
||||
});
|
||||
LookUpInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: data.project,
|
||||
list: ProjectList,
|
||||
field: 'project'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: data.project,
|
||||
list: ProjectList,
|
||||
field: 'project'
|
||||
});
|
||||
|
||||
if (!scope.PermissionAddAllowed) {
|
||||
// If not a privileged user, disable access
|
||||
$('form[name="permission_form"]').find('select, input, button').each(function(index){
|
||||
if ($(this).is('input') || $(this).is('select')) {
|
||||
$(this).attr('readonly','readonly');
|
||||
}
|
||||
if ( $(this).is('input[type="checkbox"]') ||
|
||||
$(this).is('input[type="radio"]') ||
|
||||
$(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 });
|
||||
});
|
||||
if (!$scope.PermissionAddAllowed) {
|
||||
// If not a privileged user, disable access
|
||||
$('form[name="permission_form"]').find('select, input, button').each(function () {
|
||||
if ($(this).is('input') || $(this).is('select')) {
|
||||
$(this).attr('readonly', 'readonly');
|
||||
}
|
||||
if ($(this).is('input[type="checkbox"]') ||
|
||||
$(this).is('input[type="radio"]') ||
|
||||
$(this).is('button')) {
|
||||
$(this).attr('disabled', 'disabled');
|
||||
}
|
||||
});
|
||||
}
|
||||
Wait('stop');
|
||||
})
|
||||
.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() {
|
||||
generator.clearApiErrors();
|
||||
Wait('start');
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
Rest.setUrl(defaultUrl);
|
||||
Rest.put(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
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 });
|
||||
});
|
||||
};
|
||||
// Save changes to the parent
|
||||
$scope.formSave = function () {
|
||||
var fld, data = {};
|
||||
generator.clearApiErrors();
|
||||
Wait('start');
|
||||
for (fld in form.fields) {
|
||||
data[fld] = $scope[fld];
|
||||
}
|
||||
Rest.setUrl(defaultUrl);
|
||||
Rest.put(data)
|
||||
.success(function () {
|
||||
Wait('stop');
|
||||
ReturnToCaller(1);
|
||||
})
|
||||
.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() {
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
scope[fld] = master[fld];
|
||||
}
|
||||
scope.selectCategory(false);
|
||||
};
|
||||
// Cancel
|
||||
$scope.formReset = function () {
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
$scope[fld] = master[fld];
|
||||
}
|
||||
$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
@ -3,353 +3,378 @@
|
||||
*
|
||||
*
|
||||
* Teams.js
|
||||
*
|
||||
*
|
||||
* Controller functions for the Team model.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
'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 });
|
||||
|
||||
if (scope.removePostRefresh) {
|
||||
scope.removePostRefresh();
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
});
|
||||
ClearScope();
|
||||
|
||||
SearchInit({ scope: scope, set: 'teams', list: list, url: defaultUrl });
|
||||
PaginateInit({ scope: scope, list: list, url: defaultUrl });
|
||||
scope.search(list.iterator);
|
||||
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 () {
|
||||
// After a refresh, populate the organization name on each row
|
||||
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);
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
scope.showActivity = function() { Stream({ scope: scope }); }
|
||||
|
||||
scope.addTeam = function() {
|
||||
$location.path($location.path() + '/add');
|
||||
}
|
||||
$scope.showActivity = function () {
|
||||
Stream({ scope: $scope });
|
||||
};
|
||||
|
||||
scope.editTeam = function(id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
}
|
||||
|
||||
scope.deleteTeam = function(id, name) {
|
||||
|
||||
var action = function() {
|
||||
Wait('start');
|
||||
var url = defaultUrl + id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.destroy()
|
||||
.success( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(list.iterator);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
$('#prompt-modal').modal('hide');
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||
});
|
||||
};
|
||||
$scope.addTeam = function () {
|
||||
$location.path($location.path() + '/add');
|
||||
};
|
||||
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete ' + name + '?',
|
||||
action: action
|
||||
$scope.editTeam = function (id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
};
|
||||
|
||||
$scope.deleteTeam = function (id, name) {
|
||||
|
||||
var action = function () {
|
||||
Wait('start');
|
||||
var url = defaultUrl + id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.destroy()
|
||||
.success(function () {
|
||||
Wait('stop');
|
||||
$('#prompt-modal').modal('hide');
|
||||
$scope.search(list.iterator);
|
||||
})
|
||||
.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
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
scope.lookupOrganization = function(organization_id) {
|
||||
Rest.setUrl(GetBasePath('organizations') + organization_id + '/');
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
return data.name;
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
Prompt({
|
||||
hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete ' + name + '?',
|
||||
action: action
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
TeamsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'TeamList', 'GenerateList',
|
||||
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
|
||||
'SetTeamListeners', 'GetBasePath', 'SelectionInit', 'Wait', 'Stream' ];
|
||||
TeamsList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'TeamList', 'GenerateList',
|
||||
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
|
||||
'SetTeamListeners', 'GetBasePath', 'SelectionInit', 'Wait', 'Stream'
|
||||
];
|
||||
|
||||
|
||||
function TeamsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, GenerateForm,
|
||||
Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateList,
|
||||
OrganizationList, SearchInit, PaginateInit, GetBasePath, LookUpInit, Wait)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
function TeamsAdd($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm, GenerateForm,
|
||||
Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GenerateList,
|
||||
OrganizationList, SearchInit, PaginateInit, GetBasePath, LookUpInit, Wait) {
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//$scope.
|
||||
|
||||
// Inject dynamic view
|
||||
var defaultUrl = GetBasePath('teams');
|
||||
var form = TeamForm;
|
||||
var generator = GenerateForm;
|
||||
var scope = generator.inject(form, {mode: 'add', related: false});
|
||||
$rootScope.flashMessage = null;
|
||||
generator.reset();
|
||||
LoadBreadCrumbs();
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: null,
|
||||
list: OrganizationList,
|
||||
field: 'organization'
|
||||
});
|
||||
|
||||
// Save
|
||||
scope.formSave = function() {
|
||||
generator.clearApiErrors();
|
||||
Wait('start');
|
||||
Rest.setUrl(defaultUrl);
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
Rest.post(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
$rootScope.flashMessage = "New team successfully created!";
|
||||
$location.path('/teams/' + data.id);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to add new team. Post returned status: ' + status });
|
||||
});
|
||||
};
|
||||
// Inject dynamic view
|
||||
var defaultUrl = GetBasePath('teams'),
|
||||
form = TeamForm,
|
||||
generator = GenerateForm,
|
||||
scope = generator.inject(form, { mode: 'add', related: false });
|
||||
|
||||
$rootScope.flashMessage = null;
|
||||
generator.reset();
|
||||
LoadBreadCrumbs();
|
||||
|
||||
// Reset
|
||||
scope.formReset = function() {
|
||||
// Defaults
|
||||
generator.reset();
|
||||
};
|
||||
LookUpInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: null,
|
||||
list: OrganizationList,
|
||||
field: 'organization'
|
||||
});
|
||||
|
||||
// Save
|
||||
$scope.formSave = function () {
|
||||
var fld, data;
|
||||
generator.clearApiErrors();
|
||||
Wait('start');
|
||||
Rest.setUrl(defaultUrl);
|
||||
data = {};
|
||||
for (fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
Rest.post(data)
|
||||
.success(function (data) {
|
||||
Wait('stop');
|
||||
$rootScope.flashMessage = "New team successfully created!";
|
||||
$location.path('/teams/' + data.id);
|
||||
})
|
||||
.error(function (data, status) {
|
||||
Wait('stop');
|
||||
ProcessErrors($scope, data, status, form, { hdr: 'Error!', msg: 'Failed to add new team. Post returned status: ' +
|
||||
status });
|
||||
});
|
||||
};
|
||||
|
||||
// Reset
|
||||
$scope.formReset = function () {
|
||||
// Defaults
|
||||
generator.reset();
|
||||
};
|
||||
}
|
||||
|
||||
TeamsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'TeamForm', 'GenerateForm',
|
||||
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList',
|
||||
'OrganizationList', 'SearchInit', 'PaginateInit', 'GetBasePath', 'LookUpInit', 'Wait'];
|
||||
TeamsAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'TeamForm', 'GenerateForm',
|
||||
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList',
|
||||
'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) {
|
||||
|
||||
ClearScope();
|
||||
|
||||
var defaultUrl=GetBasePath('teams');
|
||||
var generator = GenerateForm;
|
||||
var form = TeamForm;
|
||||
var scope = generator.inject(form, {mode: 'edit', related: true});
|
||||
generator.reset();
|
||||
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
var master = {};
|
||||
var id = $routeParams.team_id;
|
||||
var relatedSets = {};
|
||||
var defaultUrl = GetBasePath('teams'),
|
||||
generator = GenerateForm,
|
||||
form = TeamForm,
|
||||
base = $location.path().replace(/^\//, '').split('/')[0],
|
||||
master = {},
|
||||
id = $routeParams.team_id,
|
||||
relatedSets = {};
|
||||
|
||||
scope.PermissionAddAllowed = false;
|
||||
|
||||
// Retrieve each related set and any lookups
|
||||
if (scope.teamLoadedRemove) {
|
||||
scope.teamLoadedRemove();
|
||||
}
|
||||
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;
|
||||
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 });
|
||||
});
|
||||
for (var set in relatedSets) {
|
||||
scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
});
|
||||
generator.inject(form, { mode: 'edit', related: true, scope: $scope });
|
||||
generator.reset();
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Wait('start');
|
||||
Rest.setUrl(defaultUrl + ':id/');
|
||||
Rest.get({ params: {id: id} })
|
||||
.success( function(data, status, headers, config) {
|
||||
LoadBreadCrumbs({ path: '/teams/' + id, title: data.name });
|
||||
for (var fld in form.fields) {
|
||||
if (data[fld]) {
|
||||
scope[fld] = data[fld];
|
||||
master[fld] = scope[fld];
|
||||
}
|
||||
}
|
||||
var related = data.related;
|
||||
for (var set in form.related) {
|
||||
if (related[set]) {
|
||||
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.PermissionAddAllowed = false;
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: data['organization'],
|
||||
list: OrganizationList,
|
||||
field: 'organization'
|
||||
});
|
||||
// Retrieve each related set and any lookups
|
||||
if ($scope.teamLoadedRemove) {
|
||||
$scope.teamLoadedRemove();
|
||||
}
|
||||
$scope.teamLoadedRemove = $scope.$on('teamLoaded', function () {
|
||||
CheckAccess({ scope: $scope });
|
||||
Rest.setUrl($scope.organization_url);
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
$scope.organization_name = data.name;
|
||||
master.organization_name = data.name;
|
||||
Wait('stop');
|
||||
})
|
||||
.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['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 });
|
||||
});
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Wait('start');
|
||||
Rest.setUrl(defaultUrl + ':id/');
|
||||
Rest.get({
|
||||
params: {
|
||||
id: id
|
||||
}
|
||||
})
|
||||
.success(function (data) {
|
||||
var fld, related, set;
|
||||
LoadBreadCrumbs({ path: '/teams/' + id, title: data.name });
|
||||
for (fld in form.fields) {
|
||||
if (data[fld]) {
|
||||
$scope[fld] = data[fld];
|
||||
master[fld] = $scope[fld];
|
||||
}
|
||||
}
|
||||
related = data.related;
|
||||
for (set in form.related) {
|
||||
if (related[set]) {
|
||||
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.showActivity = function() { Stream({ scope: scope }); }
|
||||
|
||||
// Save changes to the parent
|
||||
scope.formSave = function() {
|
||||
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.put(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
(base == 'teams') ? ReturnToCaller() : ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to update team: ' + $routeParams.team_id + '. PUT status: ' + status });
|
||||
});
|
||||
};
|
||||
LookUpInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: data.organization,
|
||||
list: OrganizationList,
|
||||
field: 'organization'
|
||||
});
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
$rootScope.flashMessage = null;
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
scope[fld] = master[fld];
|
||||
}
|
||||
};
|
||||
$scope.organization_url = data.related.organization;
|
||||
$scope.$emit('teamLoaded');
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors($scope, data, status, form, { hdr: 'Error!', msg: 'Failed to retrieve team: ' + $routeParams.team_id +
|
||||
'. GET status: ' + status });
|
||||
});
|
||||
|
||||
// Related set: Add button
|
||||
scope.add = function(set) {
|
||||
$rootScope.flashMessage = null;
|
||||
if (set == 'permissions') {
|
||||
if (scope.PermissionAddAllowed) {
|
||||
$location.path('/' + base + '/' + $routeParams.team_id + '/' + set + '/add');
|
||||
}
|
||||
else {
|
||||
Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$location.path('/' + base + '/' + $routeParams.team_id + '/' + set);
|
||||
}
|
||||
};
|
||||
$scope.showActivity = function () {
|
||||
Stream({ scope: $scope });
|
||||
};
|
||||
|
||||
// Related set: Edit button
|
||||
scope.edit = function(set, id, name) {
|
||||
$rootScope.flashMessage = null;
|
||||
if (set == 'permissions') {
|
||||
$location.path('/' + base + '/' + $routeParams.team_id + '/' + set + '/' + id);
|
||||
}
|
||||
else {
|
||||
$location.path('/' + set + '/' + id);
|
||||
}
|
||||
};
|
||||
// Save changes to the parent
|
||||
$scope.formSave = function () {
|
||||
var data = {}, fld;
|
||||
generator.clearApiErrors();
|
||||
Wait('start');
|
||||
$rootScope.flashMessage = null;
|
||||
Rest.setUrl(defaultUrl + $routeParams.team_id + '/');
|
||||
for (fld in form.fields) {
|
||||
data[fld] = $scope[fld];
|
||||
}
|
||||
Rest.put(data)
|
||||
.success(function () {
|
||||
Wait('stop');
|
||||
var base = $location.path().replace(/^\//, '').split('/')[0];
|
||||
if (base === 'teams') {
|
||||
ReturnToCaller();
|
||||
}
|
||||
ReturnToCaller(1);
|
||||
})
|
||||
.error(function (data, status) {
|
||||
Wait('stop');
|
||||
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
|
||||
msg: 'Failed to update team: ' + $routeParams.team_id + '. PUT status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
// Related set: Delete button
|
||||
scope['delete'] = function(set, itm_id, name, title) {
|
||||
$rootScope.flashMessage = null;
|
||||
|
||||
var action = function() {
|
||||
var url;
|
||||
if (set == 'permissions') {
|
||||
if (scope.PermissionAddAllowed) {
|
||||
url = GetBasePath('base') + 'permissions/' + itm_id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.destroy()
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(form.related[set].iterator);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||
// Cancel
|
||||
$scope.formReset = function () {
|
||||
$rootScope.flashMessage = null;
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
$scope[fld] = master[fld];
|
||||
}
|
||||
};
|
||||
|
||||
// Related set: Add button
|
||||
$scope.add = function (set) {
|
||||
$rootScope.flashMessage = null;
|
||||
if (set === 'permissions') {
|
||||
if ($scope.PermissionAddAllowed) {
|
||||
$location.path('/' + base + '/' + $routeParams.team_id + '/' + set + '/add');
|
||||
} else {
|
||||
Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
|
||||
}
|
||||
} else {
|
||||
$location.path('/' + base + '/' + $routeParams.team_id + '/' + set);
|
||||
}
|
||||
};
|
||||
|
||||
// Related set: Edit button
|
||||
$scope.edit = function (set, id) {
|
||||
$rootScope.flashMessage = null;
|
||||
if (set === 'permissions') {
|
||||
$location.path('/' + base + '/' + $routeParams.team_id + '/' + set + '/' + id);
|
||||
} else {
|
||||
$location.path('/' + set + '/' + id);
|
||||
}
|
||||
};
|
||||
|
||||
// Related set: Delete button
|
||||
$scope['delete'] = function (set, itm_id, name, title) {
|
||||
$rootScope.flashMessage = null;
|
||||
|
||||
var action = function () {
|
||||
var url;
|
||||
if (set === 'permissions') {
|
||||
if ($scope.PermissionAddAllowed) {
|
||||
url = GetBasePath('base') + 'permissions/' + itm_id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.destroy()
|
||||
.success(function () {
|
||||
$('#prompt-modal').modal('hide');
|
||||
$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. DELETE returned status: ' + status });
|
||||
});
|
||||
}
|
||||
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 + '/';
|
||||
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);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
$('#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 + '?',
|
||||
action: action
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
|
||||
}
|
||||
} else {
|
||||
url = defaultUrl + $routeParams.team_id + '/' + set + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.post({ id: itm_id, disassociate: 1 })
|
||||
.success(function () {
|
||||
$('#prompt-modal').modal('hide');
|
||||
$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 + '?',
|
||||
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'
|
||||
];
|
||||
@ -1,455 +1,468 @@
|
||||
/************************************
|
||||
/********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
*
|
||||
* Users.js
|
||||
*
|
||||
*
|
||||
* Controller functions for User model.
|
||||
*
|
||||
*/
|
||||
|
||||
'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/' :
|
||||
GetBasePath('teams') + $routeParams.team_id + '/users/';
|
||||
SelectionInit({ scope: scope, list: list, url: url, returnToCaller: 1 });
|
||||
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/';
|
||||
|
||||
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.addUser = function() {
|
||||
$location.path($location.path() + '/add');
|
||||
}
|
||||
|
||||
scope.editUser = function(id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
}
|
||||
|
||||
scope.deleteUser = function(id, name) {
|
||||
|
||||
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);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||
});
|
||||
};
|
||||
$scope.showActivity = function () {
|
||||
Stream({ scope: $scope });
|
||||
};
|
||||
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete ' + name + '?',
|
||||
action: action
|
||||
$scope.addUser = function () {
|
||||
$location.path($location.path() + '/add');
|
||||
};
|
||||
|
||||
$scope.editUser = function (id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
};
|
||||
|
||||
$scope.deleteUser = function (id, name) {
|
||||
|
||||
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 () {
|
||||
$scope.search(list.iterator);
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Prompt({
|
||||
hdr: 'Delete',
|
||||
body: '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});
|
||||
|
||||
scope.ldap_user = false;
|
||||
scope.not_ldap_user = !scope.ldap_user;
|
||||
scope.ldap_dn = null;
|
||||
// Inject dynamic view
|
||||
var defaultUrl = GetBasePath('organizations'),
|
||||
form = UserForm,
|
||||
generator = GenerateForm;
|
||||
|
||||
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();
|
||||
generator.reset();
|
||||
|
||||
LoadBreadCrumbs();
|
||||
LoadBreadCrumbs();
|
||||
|
||||
// Configure the lookup dialog. If we're adding a user through the Organizations tab,
|
||||
// default the Organization value.
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: ($routeParams.organization_id !== undefined) ? $routeParams.organization_id : null,
|
||||
list: OrganizationList,
|
||||
field: 'organization'
|
||||
});
|
||||
// Configure the lookup dialog. If we're adding a user through the Organizations tab,
|
||||
// default the Organization value.
|
||||
LookUpInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: ($routeParams.organization_id !== undefined) ? $routeParams.organization_id : null,
|
||||
list: OrganizationList,
|
||||
field: 'organization'
|
||||
});
|
||||
|
||||
if ($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;
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to lookup Organization: ' + data.id + '. GET returned status: ' + status });
|
||||
});
|
||||
}
|
||||
if ($routeParams.organization_id) {
|
||||
$scope.organization = $routeParams.organization_id;
|
||||
Rest.setUrl(GetBasePath('organizations') + $routeParams.organization_id + '/');
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
$scope.organization_name = data.name;
|
||||
})
|
||||
.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() {
|
||||
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) {
|
||||
if (form.fields[fld].realName) {
|
||||
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;
|
||||
Wait('start');
|
||||
Rest.post(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
if (base == 'users') {
|
||||
$rootScope.flashMessage = 'New user successfully created!';
|
||||
$location.path('/users/' + data.id);
|
||||
}
|
||||
else {
|
||||
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 });
|
||||
});
|
||||
}
|
||||
else {
|
||||
scope.organization_name_api_error = 'A value is required';
|
||||
}
|
||||
};
|
||||
// Save
|
||||
$scope.formSave = function () {
|
||||
generator.clearApiErrors();
|
||||
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.is_superuser = data.is_superuser || false;
|
||||
Wait('start');
|
||||
Rest.post(data)
|
||||
.success(function (data) {
|
||||
var base = $location.path().replace(/^\//, '').split('/')[0];
|
||||
if (base === 'users') {
|
||||
$rootScope.flashMessage = 'New user successfully created!';
|
||||
$location.path('/users/' + data.id);
|
||||
}
|
||||
ReturnToCaller(1);
|
||||
})
|
||||
.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';
|
||||
}
|
||||
};
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
// Defaults
|
||||
generator.reset();
|
||||
scope.ldap_user = false;
|
||||
};
|
||||
// Cancel
|
||||
$scope.formReset = function () {
|
||||
// Defaults
|
||||
generator.reset();
|
||||
$scope.ldap_user = false;
|
||||
};
|
||||
|
||||
// Password change
|
||||
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);
|
||||
}
|
||||
// Password change
|
||||
$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);
|
||||
};
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
ClearScope();
|
||||
|
||||
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 = {};
|
||||
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});
|
||||
generator.reset();
|
||||
|
||||
if (scope.removePostRefresh) {
|
||||
scope.removePostRefresh();
|
||||
if ($scope.removeFormReady) {
|
||||
$scope.removeFormReady();
|
||||
}
|
||||
$scope.removeFormReady = $scope.$on('formReady', function () {
|
||||
generator.inject(form, { mode: 'edit', related: true, scope: $scope });
|
||||
generator.reset();
|
||||
|
||||
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();
|
||||
}
|
||||
scope.removeUserLoaded = scope.$on('userLoaded', function() {
|
||||
for (var set in relatedSets) {
|
||||
scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
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) {
|
||||
LoadBreadCrumbs({ path: '/users/' + id, title: data.username });
|
||||
for (var fld in form.fields) {
|
||||
if (data[fld]) {
|
||||
if (fld == 'is_superuser') {
|
||||
scope[fld] = (data[fld] == 'true' || data[fld] == true) ? 'true' : 'false';
|
||||
}
|
||||
else {
|
||||
scope[fld] = data[fld];
|
||||
}
|
||||
master[fld] = scope[fld];
|
||||
}
|
||||
}
|
||||
var related = data.related;
|
||||
for (var set in form.related) {
|
||||
if (related[set]) {
|
||||
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;
|
||||
|
||||
// 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');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve user: ' + $routeParams.id + '. GET status: ' + status });
|
||||
});
|
||||
|
||||
// Save changes to the parent
|
||||
scope.formSave = function() {
|
||||
generator.clearApiErrors();
|
||||
$rootScope.flashMessage = null;
|
||||
Rest.setUrl(defaultUrl + id + '/');
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
if (form.fields[fld].realName) {
|
||||
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;
|
||||
|
||||
Wait('start');
|
||||
Rest.put(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
(base == 'users') ? ReturnToCaller() : 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 });
|
||||
});
|
||||
};
|
||||
|
||||
scope.showActivity = function() { Stream({ scope: scope }); }
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
$rootScope.flashMessage = null;
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
scope[fld] = master[fld];
|
||||
}
|
||||
scope['password_confirm'] = scope['password'];
|
||||
};
|
||||
|
||||
// Password change
|
||||
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);
|
||||
$rootScope.flashMessage = null;
|
||||
}
|
||||
|
||||
|
||||
// Related set: Add button
|
||||
scope.add = function(set) {
|
||||
$rootScope.flashMessage = null;
|
||||
if (set == 'permissions') {
|
||||
if (scope.PermissionAddAllowed) {
|
||||
$location.path('/' + base + '/' + $routeParams.user_id + '/' + set + '/add');
|
||||
}
|
||||
else {
|
||||
Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$location.path('/' + base + '/' + $routeParams.user_id + '/' + set);
|
||||
}
|
||||
};
|
||||
|
||||
// Related set: Edit button
|
||||
scope.edit = function(set, id, name) {
|
||||
$rootScope.flashMessage = null;
|
||||
if (set == 'permissions') {
|
||||
$location.path('/users/' + $routeParams.user_id + '/permissions/' + id);
|
||||
}
|
||||
else {
|
||||
$location.path('/' + set + '/' + id);
|
||||
}
|
||||
};
|
||||
|
||||
// Related set: Delete button
|
||||
scope['delete'] = function(set, itm_id, name, title) {
|
||||
$rootScope.flashMessage = null;
|
||||
|
||||
var action = function() {
|
||||
var url;
|
||||
if (set == 'permissions') {
|
||||
if (scope.PermissionAddAllowed) {
|
||||
url = GetBasePath('base') + 'permissions/' + itm_id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.destroy()
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(form.related[set].iterator);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||
});
|
||||
}
|
||||
else {
|
||||
Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
|
||||
}
|
||||
}
|
||||
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);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
$('#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 + '?',
|
||||
action: action
|
||||
});
|
||||
}
|
||||
|
||||
}); // $scope.$on
|
||||
|
||||
// Put form back to its original state
|
||||
ResetForm();
|
||||
|
||||
|
||||
if ($scope.removeModifyForm) {
|
||||
$scope.removeModifyForm();
|
||||
}
|
||||
$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];
|
||||
if (form.fields[fld]) {
|
||||
form.fields[fld]['readonly'] = true;
|
||||
form.fields[fld]['editRequired'] = false;
|
||||
if (form.fields[fld].awRequiredWhen) {
|
||||
delete form.fields[fld].awRequiredWhen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$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 });
|
||||
});
|
||||
});
|
||||
|
||||
Wait('start');
|
||||
Rest.setUrl(defaultUrl + id + '/');
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
if (data.ldap_dn !== null && data.ldap_dn !== undefined && data.ldap_dn !== '') {
|
||||
//this is an LDAP user
|
||||
$scope.$emit('modifyForm');
|
||||
}
|
||||
else {
|
||||
$scope.$emit('formReady');
|
||||
// After the Organization is loaded, retrieve each related set
|
||||
if ($scope.removeUserLoaded) {
|
||||
$scope.removeUserLoaded();
|
||||
}
|
||||
$scope.removeUserLoaded = $scope.$on('userLoaded', function () {
|
||||
for (var set in relatedSets) {
|
||||
$scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
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) {
|
||||
LoadBreadCrumbs({ path: '/users/' + id, title: data.username });
|
||||
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';
|
||||
} else {
|
||||
$scope[fld] = data[fld];
|
||||
}
|
||||
master[fld] = $scope[fld];
|
||||
}
|
||||
}
|
||||
related = data.related;
|
||||
for (set in form.related) {
|
||||
if (related[set]) {
|
||||
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;
|
||||
|
||||
// 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');
|
||||
})
|
||||
.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: ' +
|
||||
$routeParams.id + '. GET status: ' + status });
|
||||
});
|
||||
|
||||
// Save changes to the parent
|
||||
$scope.formSave = function () {
|
||||
var data = {}, fld;
|
||||
generator.clearApiErrors();
|
||||
$rootScope.flashMessage = null;
|
||||
Rest.setUrl(defaultUrl + id + '/');
|
||||
for (fld in form.fields) {
|
||||
if (form.fields[fld].realName) {
|
||||
data[form.fields[fld].realName] = $scope[fld];
|
||||
} else {
|
||||
data[fld] = $scope[fld];
|
||||
}
|
||||
}
|
||||
|
||||
data.is_superuser = data.is_superuser || false;
|
||||
|
||||
Wait('start');
|
||||
Rest.put(data)
|
||||
.success(function () {
|
||||
Wait('stop');
|
||||
var base = $location.path().replace(/^\//, '').split('/')[0];
|
||||
if (base === 'users') {
|
||||
ReturnToCaller();
|
||||
}
|
||||
ReturnToCaller(1);
|
||||
})
|
||||
.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 });
|
||||
};
|
||||
|
||||
// Cancel
|
||||
$scope.formReset = function () {
|
||||
$rootScope.flashMessage = null;
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
$scope[fld] = master[fld];
|
||||
}
|
||||
$scope.password_confirm = $scope.password;
|
||||
};
|
||||
|
||||
// Password change
|
||||
$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);
|
||||
$rootScope.flashMessage = null;
|
||||
};
|
||||
|
||||
|
||||
// Related set: Add button
|
||||
$scope.add = function (set) {
|
||||
$rootScope.flashMessage = null;
|
||||
if (set === 'permissions') {
|
||||
if ($scope.PermissionAddAllowed) {
|
||||
$location.path('/' + base + '/' + $routeParams.user_id + '/' + set + '/add');
|
||||
} else {
|
||||
Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
|
||||
}
|
||||
} else {
|
||||
$location.path('/' + base + '/' + $routeParams.user_id + '/' + set);
|
||||
}
|
||||
};
|
||||
|
||||
// Related set: Edit button
|
||||
$scope.edit = function (set, id) {
|
||||
$rootScope.flashMessage = null;
|
||||
if (set === 'permissions') {
|
||||
$location.path('/users/' + $routeParams.user_id + '/permissions/' + id);
|
||||
} else {
|
||||
$location.path('/' + set + '/' + id);
|
||||
}
|
||||
};
|
||||
|
||||
// Related set: Delete button
|
||||
$scope['delete'] = function (set, itm_id, name, title) {
|
||||
$rootScope.flashMessage = null;
|
||||
|
||||
var action = function () {
|
||||
var url;
|
||||
if (set === 'permissions') {
|
||||
if ($scope.PermissionAddAllowed) {
|
||||
url = GetBasePath('base') + 'permissions/' + itm_id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.destroy()
|
||||
.success(function () {
|
||||
$('#prompt-modal').modal('hide');
|
||||
$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. DELETE returned status: ' + status });
|
||||
});
|
||||
} else {
|
||||
Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
|
||||
}
|
||||
} else {
|
||||
url = defaultUrl + $routeParams.user_id + '/' + set + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.post({
|
||||
id: itm_id,
|
||||
disassociate: 1
|
||||
})
|
||||
.success(function () {
|
||||
$('#prompt-modal').modal('hide');
|
||||
$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 + '?',
|
||||
action: action
|
||||
});
|
||||
};
|
||||
}); // $scope.$on
|
||||
|
||||
// Put form back to its original state
|
||||
ResetForm();
|
||||
|
||||
|
||||
if ($scope.removeModifyForm) {
|
||||
$scope.removeModifyForm();
|
||||
}
|
||||
$scope.removeModifyForm = $scope.$on('modifyForm', function () {
|
||||
// Modify form based on LDAP settings
|
||||
Rest.setUrl(GetBasePath('config'));
|
||||
Rest.get()
|
||||
.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;
|
||||
if (form.fields[fld].awRequiredWhen) {
|
||||
delete form.fields[fld].awRequiredWhen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$scope.$emit('formReady');
|
||||
})
|
||||
.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) {
|
||||
if (data.ldap_dn !== null && data.ldap_dn !== undefined && data.ldap_dn !== '') {
|
||||
//this is an LDAP user
|
||||
$scope.$emit('modifyForm');
|
||||
} else {
|
||||
$scope.$emit('formReady');
|
||||
}
|
||||
})
|
||||
.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'
|
||||
];
|
||||
@ -6,11 +6,10 @@
|
||||
*
|
||||
*/
|
||||
angular.module('ActivityDetailDefinition', [])
|
||||
.value(
|
||||
'ActivityDetailForm', {
|
||||
|
||||
.value('ActivityDetailForm', {
|
||||
|
||||
name: 'activity',
|
||||
editTitle: 'Activity Detail',
|
||||
editTitle: 'Activity Detail',
|
||||
well: false,
|
||||
'class': 'horizontal-narrow',
|
||||
formFieldSize: 'col-lg-10',
|
||||
@ -21,18 +20,18 @@ angular.module('ActivityDetailDefinition', [])
|
||||
label: "Initiated by",
|
||||
type: 'text',
|
||||
readonly: true
|
||||
},
|
||||
},
|
||||
operation: {
|
||||
label: 'Action',
|
||||
type: 'text',
|
||||
readonly: true
|
||||
},
|
||||
},
|
||||
changes: {
|
||||
label: 'Changes',
|
||||
type: 'textarea',
|
||||
ngHide: "!changes || changes =='' || changes == 'null'",
|
||||
readonly: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}); //Form
|
||||
|
||||
@ -6,23 +6,22 @@
|
||||
*
|
||||
*/
|
||||
angular.module('CredentialFormDefinition', [])
|
||||
.value(
|
||||
'CredentialForm', {
|
||||
|
||||
addTitle: 'Create Credential', //Legend in add mode
|
||||
editTitle: '{{ name }}', //Legend in edit mode
|
||||
.value('CredentialForm', {
|
||||
|
||||
addTitle: 'Create Credential', //Legend in add mode
|
||||
editTitle: '{{ name }}', //Legend in edit mode
|
||||
name: 'credential',
|
||||
well: true,
|
||||
forceListeners: true,
|
||||
|
||||
|
||||
actions: {
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'edit'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
label: 'Name',
|
||||
@ -30,27 +29,31 @@ angular.module('CredentialFormDefinition', [])
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
autocomplete: false
|
||||
},
|
||||
description: {
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
},
|
||||
owner: {
|
||||
label: "Does this credential belong to a team or user?",
|
||||
type: 'radio_group',
|
||||
ngChange: "ownerChange()",
|
||||
options: [
|
||||
{ label: 'User', value: 'user', selected: true },
|
||||
{ label: 'Team', value: 'team' }
|
||||
],
|
||||
awPopOver: "<p>A credential must be associated with either a user or a team. Choosing a user allows only the selected user access " +
|
||||
options: [{
|
||||
label: 'User',
|
||||
value: 'user',
|
||||
selected: true
|
||||
}, {
|
||||
label: 'Team',
|
||||
value: 'team'
|
||||
}],
|
||||
awPopOver: "<p>A credential must be associated with either a user or a team. Choosing a user allows only the selected user access " +
|
||||
"to the credential. Choosing a team shares the credential with all team members.</p>",
|
||||
dataTitle: 'Owner',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
user: {
|
||||
label: 'User that owns this credential',
|
||||
type: 'lookup',
|
||||
@ -58,8 +61,11 @@ 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',
|
||||
type: 'lookup',
|
||||
@ -67,69 +73,84 @@ 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',
|
||||
excludeModal: true,
|
||||
type: 'select',
|
||||
ngOptions: 'kind.label for kind in credential_kind_options',
|
||||
ngChange: 'kindChange()',
|
||||
addRequired: true,
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
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' +
|
||||
'<dt>Machine</dt>\n' +
|
||||
'<dd>Authentication for remote machine access. This can include SSH keys, usernames, passwords, ' +
|
||||
'and sudo information. Machine credentials are used when submitting jobs to run playbooks against ' +
|
||||
'remote hosts.</dd>' +
|
||||
'<dt>Rackspace</dt>\n' +
|
||||
'<dd>Access information for Rackspace Cloud used for inventory management or deployment.</dd>\n' +
|
||||
'<dt>SCM</dt>\n' +
|
||||
'<dd>Used to check out and synchronize playbook repositories with a remote source control ' +
|
||||
'management system such as Git, Subversion (svn), or Mercurial (hg). These credentials are ' +
|
||||
'used on the Projects tab.</dd>\n' +
|
||||
'</dl>\n'
|
||||
}]
|
||||
},
|
||||
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' +
|
||||
'<dt>Machine</dt>\n' +
|
||||
'<dd>Authentication for remote machine access. This can include SSH keys, usernames, passwords, ' +
|
||||
'and sudo information. Machine credentials are used when submitting jobs to run playbooks against ' +
|
||||
'remote hosts.</dd>' +
|
||||
'<dt>Rackspace</dt>\n' +
|
||||
'<dd>Access information for Rackspace Cloud used for inventory management or deployment.</dd>\n' +
|
||||
'<dt>SCM</dt>\n' +
|
||||
'<dd>Used to check out and synchronize playbook repositories with a remote source control ' +
|
||||
'management system such as Git, Subversion (svn), or Mercurial (hg). These credentials are ' +
|
||||
'used on the Projects tab.</dd>\n' +
|
||||
'</dl>\n'
|
||||
}]
|
||||
},
|
||||
access_key: {
|
||||
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'
|
||||
},
|
||||
},
|
||||
secret_key: {
|
||||
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,
|
||||
apiField: 'passwowrd'
|
||||
},
|
||||
},
|
||||
"username": {
|
||||
labelBind: 'usernameLabel',
|
||||
type: 'text',
|
||||
ngShow: "kind.value && kind.value !== 'aws'",
|
||||
awRequiredWhen: {variable: 'rackspace_required', init: false },
|
||||
autocomplete: 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,
|
||||
apiField: 'passwowrd'
|
||||
},
|
||||
},
|
||||
"password": {
|
||||
label: 'Password',
|
||||
type: 'password',
|
||||
@ -141,7 +162,7 @@ angular.module('CredentialFormDefinition', [])
|
||||
clear: false,
|
||||
associated: 'password_confirm',
|
||||
autocomplete: false
|
||||
},
|
||||
},
|
||||
"password_confirm": {
|
||||
label: 'Confirm Password',
|
||||
type: 'password',
|
||||
@ -151,7 +172,7 @@ angular.module('CredentialFormDefinition', [])
|
||||
awPassMatch: true,
|
||||
associated: 'password',
|
||||
autocomplete: false
|
||||
},
|
||||
},
|
||||
"ssh_password": {
|
||||
label: 'SSH Password',
|
||||
type: 'password',
|
||||
@ -163,7 +184,7 @@ angular.module('CredentialFormDefinition', [])
|
||||
clear: true,
|
||||
associated: 'ssh_password_confirm',
|
||||
autocomplete: false
|
||||
},
|
||||
},
|
||||
"ssh_password_confirm": {
|
||||
label: 'Confirm SSH Password',
|
||||
type: 'password',
|
||||
@ -173,7 +194,7 @@ angular.module('CredentialFormDefinition', [])
|
||||
awPassMatch: true,
|
||||
associated: 'ssh_password',
|
||||
autocomplete: false
|
||||
},
|
||||
},
|
||||
"ssh_key_data": {
|
||||
labelBind: 'sshKeyDataLabel',
|
||||
type: 'textarea',
|
||||
@ -182,7 +203,7 @@ angular.module('CredentialFormDefinition', [])
|
||||
editRequired: false,
|
||||
'class': 'ssh-key-field',
|
||||
rows: 10
|
||||
},
|
||||
},
|
||||
"ssh_key_unlock": {
|
||||
label: 'Key Password',
|
||||
type: 'password',
|
||||
@ -192,9 +213,9 @@ angular.module('CredentialFormDefinition', [])
|
||||
ngChange: "clearPWConfirm('ssh_key_unlock_confirm')",
|
||||
associated: 'ssh_key_unlock_confirm',
|
||||
ask: true,
|
||||
askShow: "kind.value == 'ssh'", //Only allow ask for machine credentials
|
||||
askShow: "kind.value == 'ssh'", //Only allow ask for machine credentials
|
||||
clear: true
|
||||
},
|
||||
},
|
||||
"ssh_key_unlock_confirm": {
|
||||
label: 'Confirm Key Password',
|
||||
type: 'password',
|
||||
@ -203,7 +224,7 @@ angular.module('CredentialFormDefinition', [])
|
||||
editRequired: false,
|
||||
awPassMatch: true,
|
||||
associated: 'ssh_key_unlock'
|
||||
},
|
||||
},
|
||||
"sudo_username": {
|
||||
label: 'Sudo Username',
|
||||
type: 'text',
|
||||
@ -211,7 +232,7 @@ angular.module('CredentialFormDefinition', [])
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
autocomplete: false
|
||||
},
|
||||
},
|
||||
"sudo_password": {
|
||||
label: 'Sudo Password',
|
||||
type: 'password',
|
||||
@ -223,7 +244,7 @@ angular.module('CredentialFormDefinition', [])
|
||||
clear: true,
|
||||
associated: 'sudo_password_confirm',
|
||||
autocomplete: false
|
||||
},
|
||||
},
|
||||
"sudo_password_confirm": {
|
||||
label: 'Confirm Sudo Password',
|
||||
type: 'password',
|
||||
@ -233,24 +254,21 @@ angular.module('CredentialFormDefinition', [])
|
||||
awPassMatch: true,
|
||||
associated: 'sudo_password',
|
||||
autocomplete: false
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
label: 'Save',
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
}
|
||||
|
||||
}); //InventoryForm
|
||||
},
|
||||
|
||||
buttons: {
|
||||
save: {
|
||||
label: 'Save',
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
related: {}
|
||||
|
||||
});
|
||||
@ -4,12 +4,11 @@
|
||||
* Groups.js
|
||||
* Form definition for Group model
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('GroupFormDefinition', [])
|
||||
.value(
|
||||
'GroupForm', {
|
||||
|
||||
.value('GroupForm', {
|
||||
|
||||
addTitle: 'Create Group',
|
||||
editTitle: 'Edit Group',
|
||||
showTitle: true,
|
||||
@ -18,12 +17,15 @@ angular.module('GroupFormDefinition', [])
|
||||
well: true,
|
||||
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: {
|
||||
label: 'Name',
|
||||
@ -31,19 +33,19 @@ angular.module('GroupFormDefinition', [])
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
tab: 'properties'
|
||||
},
|
||||
description: {
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
tab: 'properties'
|
||||
},
|
||||
},
|
||||
variables: {
|
||||
label: 'Variables',
|
||||
type: 'textarea',
|
||||
addRequired: false,
|
||||
editRequird: false,
|
||||
editRequird: false,
|
||||
rows: 6,
|
||||
'default': '---',
|
||||
dataTitle: 'Group Variables',
|
||||
@ -59,24 +61,27 @@ angular.module('GroupFormDefinition', [])
|
||||
'<p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">docs.ansible.com</a></p>',
|
||||
dataContainer: 'body',
|
||||
tab: 'properties'
|
||||
},
|
||||
},
|
||||
source: {
|
||||
label: 'Source',
|
||||
type: 'select',
|
||||
ngOptions: 'source.label for source in source_type_options',
|
||||
ngChange: 'sourceChange()',
|
||||
addRequired: false,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
//'default': { label: 'Manual', value: '' },
|
||||
tab: 'source'
|
||||
},
|
||||
},
|
||||
source_path: {
|
||||
label: 'Script Path',
|
||||
ngShow: "source && source.value == 'file'",
|
||||
type: 'text',
|
||||
awRequiredWhen: {variable: "sourcePathRequired", init: "false" },
|
||||
tab: 'source'
|
||||
awRequiredWhen: {
|
||||
variable: "sourcePathRequired",
|
||||
init: "false"
|
||||
},
|
||||
tab: 'source'
|
||||
},
|
||||
credential: {
|
||||
label: 'Cloud Credential',
|
||||
type: 'lookup',
|
||||
@ -84,10 +89,10 @@ angular.module('GroupFormDefinition', [])
|
||||
sourceModel: 'credential',
|
||||
sourceField: 'name',
|
||||
ngClick: 'lookUpCredential()',
|
||||
addRequired: false,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
tab: 'source'
|
||||
},
|
||||
},
|
||||
source_regions: {
|
||||
label: 'Regions',
|
||||
type: 'text',
|
||||
@ -102,13 +107,13 @@ angular.module('GroupFormDefinition', [])
|
||||
"</p>",
|
||||
dataContainer: 'body',
|
||||
tab: 'source'
|
||||
},
|
||||
},
|
||||
source_vars: {
|
||||
label: 'Source Variables',
|
||||
ngShow: "source && (source.value == 'file' || source.value == 'ec2')",
|
||||
type: 'textarea',
|
||||
addRequired: false,
|
||||
editRequird: false,
|
||||
editRequird: false,
|
||||
rows: 6,
|
||||
'default': '---',
|
||||
parseTypeName: 'envParseType',
|
||||
@ -126,80 +131,73 @@ angular.module('GroupFormDefinition', [])
|
||||
'<p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">docs.ansible.com</a></p>',
|
||||
dataContainer: 'body',
|
||||
tab: 'source'
|
||||
},
|
||||
},
|
||||
checkbox_group: {
|
||||
label: 'Update Options',
|
||||
type: 'checkbox_group',
|
||||
ngShow: "source && (source.value !== '' && source.value !== null)",
|
||||
tab: 'source',
|
||||
|
||||
fields: [
|
||||
{
|
||||
name: 'overwrite',
|
||||
label: 'Overwrite',
|
||||
type: 'checkbox',
|
||||
ngShow: "source.value !== '' && source.value !== null",
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPopOver: '<p>When checked all child groups and hosts not found on the remote source will be deleted from ' +
|
||||
'the local inventory.</p><p>Unchecked any local child hosts and groups not found on the external source will ' +
|
||||
'remain untouched by the inventory update process.</p>',
|
||||
dataTitle: 'Overwrite',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right',
|
||||
labelClass: 'checkbox-options'
|
||||
},
|
||||
{
|
||||
name: 'overwrite_vars',
|
||||
label: 'Overwrite Variables',
|
||||
type: 'checkbox',
|
||||
ngShow: "source.value !== '' && source.value !== null",
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPopOver: '<p>If checked, all variables for child groups and hosts will be removed and replaced by those ' +
|
||||
'found on the external source.</p><p>When not checked a merge will be performed, combining local variables with ' +
|
||||
'those found on the external source.</p>',
|
||||
dataTitle: 'Overwrite Variables',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right',
|
||||
labelClass: 'checkbox-options'
|
||||
},
|
||||
{
|
||||
name: 'update_on_launch',
|
||||
label: 'Update on Launch',
|
||||
type: 'checkbox',
|
||||
ngShow: "source.value !== '' && source.value !== null",
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPopOver: '<p>Each time a job runs using this inventory, refresh the inventory from the selected source before ' +
|
||||
'executing job tasks.</p>',
|
||||
dataTitle: 'Update on Launch',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right',
|
||||
labelClass: 'checkbox-options'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
fields: [{
|
||||
name: 'overwrite',
|
||||
label: 'Overwrite',
|
||||
type: 'checkbox',
|
||||
ngShow: "source.value !== '' && source.value !== null",
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPopOver: '<p>When checked all child groups and hosts not found on the remote source will be deleted from ' +
|
||||
'the local inventory.</p><p>Unchecked any local child hosts and groups not found on the external source will ' +
|
||||
'remain untouched by the inventory update process.</p>',
|
||||
dataTitle: 'Overwrite',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right',
|
||||
labelClass: 'checkbox-options'
|
||||
}, {
|
||||
name: 'overwrite_vars',
|
||||
label: 'Overwrite Variables',
|
||||
type: 'checkbox',
|
||||
ngShow: "source.value !== '' && source.value !== null",
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPopOver: '<p>If checked, all variables for child groups and hosts will be removed and replaced by those ' +
|
||||
'found on the external source.</p><p>When not checked a merge will be performed, combining local variables with ' +
|
||||
'those found on the external source.</p>',
|
||||
dataTitle: 'Overwrite Variables',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right',
|
||||
labelClass: 'checkbox-options'
|
||||
}, {
|
||||
name: 'update_on_launch',
|
||||
label: 'Update on Launch',
|
||||
type: 'checkbox',
|
||||
ngShow: "source.value !== '' && source.value !== null",
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPopOver: '<p>Each time a job runs using this inventory, refresh the inventory from the selected source before ' +
|
||||
'executing job tasks.</p>',
|
||||
dataTitle: 'Update on Launch',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right',
|
||||
labelClass: 'checkbox-options'
|
||||
}]
|
||||
}
|
||||
},
|
||||
|
||||
buttons: {
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
|
||||
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
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
save: {
|
||||
ngClick: 'formSave()',
|
||||
ngDisabled: true
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
related: { }
|
||||
|
||||
});
|
||||
@ -7,14 +7,13 @@
|
||||
*
|
||||
*/
|
||||
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',
|
||||
formFieldSize: 'col-lg-9',
|
||||
|
||||
fields: {
|
||||
groups: {
|
||||
@ -26,30 +25,28 @@ angular.module('HostGroupsFormDefinition', [])
|
||||
editRequired: true,
|
||||
awPopOver: "<p>Provide a host name, ip address, or ip address:port. Examples include:</p>" +
|
||||
"<blockquote>myserver.domain.com<br/>" +
|
||||
"127.0.0.1<br />" +
|
||||
"127.0.0.1<br />" +
|
||||
"10.1.0.140:25<br />" +
|
||||
"server.example.com:25" +
|
||||
"</blockquote>",
|
||||
"</blockquote>",
|
||||
dataTitle: 'Host Name',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: '#form-modal .modal-content'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
save: {
|
||||
ngClick: 'formSave()',
|
||||
ngDisabled: true
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true
|
||||
}
|
||||
},
|
||||
|
||||
related: { }
|
||||
|
||||
}); //UserForm
|
||||
|
||||
|
||||
@ -4,18 +4,17 @@
|
||||
* Hosts.js
|
||||
* Form definition for Host model
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('HostFormDefinition', [])
|
||||
.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
|
||||
.value('HostForm', {
|
||||
|
||||
addTitle: 'Create Host',
|
||||
editTitle: '{{ name }}',
|
||||
name: 'host',
|
||||
well: false,
|
||||
formLabelSize: 'col-lg-3',
|
||||
formFieldSize: 'col-lg-9',
|
||||
formFieldSize: 'col-lg-9',
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
@ -24,21 +23,21 @@ angular.module('HostFormDefinition', [])
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
awPopOver: "<p>Provide a host name, ip address, or ip address:port. Examples include:</p>" +
|
||||
"<blockquote>myserver.domain.com<br/>" +
|
||||
"127.0.0.1<br />" +
|
||||
"10.1.0.140:25<br />" +
|
||||
"server.example.com:25" +
|
||||
"</blockquote>",
|
||||
"<blockquote>myserver.domain.com<br/>" +
|
||||
"127.0.0.1<br />" +
|
||||
"10.1.0.140:25<br />" +
|
||||
"server.example.com:25" +
|
||||
"</blockquote>",
|
||||
dataTitle: 'Host Name',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: '#form-modal .modal-content'
|
||||
},
|
||||
description: {
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
},
|
||||
enabled: {
|
||||
label: 'Enabled?',
|
||||
type: 'checkbox',
|
||||
@ -51,12 +50,12 @@ angular.module('HostFormDefinition', [])
|
||||
dataPlacement: 'right',
|
||||
dataContainer: '#form-modal .modal-content',
|
||||
ngDisabled: 'has_inventory_sources == true'
|
||||
},
|
||||
},
|
||||
variables: {
|
||||
label: 'Variables',
|
||||
type: 'textarea',
|
||||
addRequired: false,
|
||||
editRequird: false,
|
||||
editRequird: false,
|
||||
rows: 6,
|
||||
"class": "modal-input-xlarge",
|
||||
"default": "---",
|
||||
@ -70,28 +69,25 @@ angular.module('HostFormDefinition', [])
|
||||
dataTitle: 'Host Variables',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: '#form-modal .modal-content'
|
||||
},
|
||||
},
|
||||
inventory: {
|
||||
type: 'hidden',
|
||||
includeOnEdit: true,
|
||||
includeOnEdit: true,
|
||||
includeOnAdd: true
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
save: {
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
related: {}
|
||||
|
||||
});
|
||||
|
||||
@ -4,12 +4,11 @@
|
||||
* Inventories.js
|
||||
* Form definition for User model
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('InventoryFormDefinition', [])
|
||||
.value(
|
||||
'InventoryForm', {
|
||||
|
||||
.value('InventoryForm', {
|
||||
|
||||
addTitle: 'Create Inventory',
|
||||
editTitle: '{{ inventory_name | capitalize }}',
|
||||
name: 'inventory',
|
||||
@ -24,8 +23,8 @@ angular.module('InventoryFormDefinition', [])
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
iconSize: 'large'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
inventory_name: {
|
||||
@ -35,29 +34,32 @@ angular.module('InventoryFormDefinition', [])
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
capitalize: false
|
||||
},
|
||||
inventory_description: {
|
||||
},
|
||||
inventory_description: {
|
||||
realName: 'description',
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
},
|
||||
organization: {
|
||||
label: 'Organization',
|
||||
type: 'lookup',
|
||||
sourceModel: 'organization',
|
||||
sourceField: 'name',
|
||||
ngClick: 'lookUpOrganization()',
|
||||
awRequiredWhen: {variable: "organizationrequired", init: "true" }
|
||||
},
|
||||
awRequiredWhen: {
|
||||
variable: "organizationrequired",
|
||||
init: "true"
|
||||
}
|
||||
},
|
||||
inventory_variables: {
|
||||
realName: 'variables',
|
||||
label: 'Variables',
|
||||
type: 'textarea',
|
||||
'class': 'span12',
|
||||
addRequired: false,
|
||||
editRequird: false,
|
||||
editRequird: false,
|
||||
parseTypeName: 'inventoryParseType',
|
||||
rows: 6,
|
||||
"default": "---",
|
||||
@ -71,23 +73,22 @@ angular.module('InventoryFormDefinition', [])
|
||||
dataTitle: 'Inventory Variables',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
buttons: {
|
||||
save: {
|
||||
ngClick: 'formSave()',
|
||||
ngDisabled: true
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true
|
||||
}
|
||||
},
|
||||
|
||||
related: {
|
||||
|
||||
}
|
||||
|
||||
}); //InventoryForm
|
||||
}
|
||||
|
||||
});
|
||||
@ -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
|
||||
@ -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
|
||||
@ -1,57 +0,0 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* InventoryStatus.js
|
||||
* Form definition for Inventory Status -JSON view
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('InventoryStatusDefinition', [])
|
||||
.value(
|
||||
'InventoryStatusForm', {
|
||||
|
||||
name: 'inventory_update',
|
||||
editTitle: 'Inventory Status',
|
||||
well: false,
|
||||
'class': 'horizontal-narrow',
|
||||
|
||||
fields: {
|
||||
license_error: {
|
||||
type: 'alertblock',
|
||||
'class': 'alert-info',
|
||||
alertTxt: 'The invenvtory update process exceeded the available number of licensed hosts. ' +
|
||||
'<strong><a ng-click=\"viewLicense()\" href=\"\">View your license</a></strong> ' +
|
||||
'for more information.',
|
||||
ngShow: 'license_error',
|
||||
closeable: true
|
||||
},
|
||||
created: {
|
||||
label: 'Created',
|
||||
type: 'text',
|
||||
readonly: true
|
||||
},
|
||||
status: {
|
||||
label: 'Status',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
'class': 'nowrap mono-space resizable',
|
||||
rows: '{{ status_rows }}'
|
||||
},
|
||||
result_stdout: {
|
||||
label: 'Std Out',
|
||||
type: 'textarea',
|
||||
ngShow: 'result_stdout',
|
||||
'class': 'nowrap mono-space resizable',
|
||||
readonly: true,
|
||||
rows: '{{ stdout_rows }}'
|
||||
},
|
||||
result_traceback: {
|
||||
label: 'Traceback',
|
||||
type: 'textarea',
|
||||
ngShow: 'result_traceback',
|
||||
'class': 'nowrap mono-space resizable',
|
||||
readonly: true,
|
||||
rows: '{{ traceback_rows }}'
|
||||
}
|
||||
}
|
||||
}); //Form
|
||||
@ -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',
|
||||
@ -22,7 +21,7 @@ angular.module('JobEventDataDefinition', [])
|
||||
readonly: true,
|
||||
rows: 18,
|
||||
'class': 'modal-input-xxlarge'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}); //Form
|
||||
|
||||
144
awx/ui/static/js/forms/JobEvents.js
Normal file
144
awx/ui/static/js/forms/JobEvents.js
Normal 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 !== ''"
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -7,8 +7,7 @@
|
||||
*
|
||||
*/
|
||||
angular.module('JobSummaryDefinition', [])
|
||||
.value(
|
||||
'JobSummary', {
|
||||
.value('JobSummary', {
|
||||
|
||||
editTitle: '{{ id }} - {{ name }}',
|
||||
name: 'jobs',
|
||||
@ -21,12 +20,12 @@ angular.module('JobSummaryDefinition', [])
|
||||
control: '<div class=\"job-detail-status\"><span style="padding-right: 15px; font-weight: bold;">Status</span> ' +
|
||||
'<i class=\"fa icon-job-{{ status }}\"></i> {{ status }}</div>',
|
||||
readonly: true
|
||||
},
|
||||
},
|
||||
created: {
|
||||
label: 'Created On',
|
||||
type: 'text',
|
||||
readonly: true
|
||||
},
|
||||
},
|
||||
result_stdout: {
|
||||
label: 'Standard Out',
|
||||
type: 'textarea',
|
||||
@ -35,7 +34,7 @@ angular.module('JobSummaryDefinition', [])
|
||||
rows: '{{ stdout_rows }}',
|
||||
'class': 'nowrap mono-space resizable',
|
||||
ngShow: 'result_stdout != ""'
|
||||
},
|
||||
},
|
||||
result_traceback: {
|
||||
label: 'Traceback',
|
||||
type: 'textarea',
|
||||
@ -44,7 +43,6 @@ angular.module('JobSummaryDefinition', [])
|
||||
rows: '{{ traceback_rows }}',
|
||||
'class': 'nowrap mono-space resizable',
|
||||
ngShow: 'result_traceback != ""'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
@ -7,11 +7,10 @@
|
||||
*
|
||||
*/
|
||||
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,
|
||||
@ -25,8 +24,8 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
iconSize: 'large'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
@ -35,20 +34,20 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
column: 1
|
||||
},
|
||||
description: {
|
||||
},
|
||||
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": 0,
|
||||
addRequired: true,
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
column: 1,
|
||||
awPopOver: "<p>When this template is submitted as a job, setting the type to <em>run</em> will execute the playbook, running tasks " +
|
||||
@ -57,7 +56,7 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
dataTitle: 'Job Type',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
inventory: {
|
||||
label: 'Inventory',
|
||||
type: 'lookup',
|
||||
@ -70,7 +69,7 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
dataTitle: 'Inventory',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
project: {
|
||||
label: 'Project',
|
||||
type: 'lookup',
|
||||
@ -83,7 +82,7 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
dataTitle: 'Project',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
playbook: {
|
||||
label: 'Playbook',
|
||||
type:'select',
|
||||
@ -95,29 +94,29 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
dataTitle: 'Playbook',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
credential: {
|
||||
label: 'Machine Credential',
|
||||
type: 'lookup',
|
||||
sourceModel: 'credential',
|
||||
sourceField: 'name',
|
||||
ngClick: 'lookUpCredential()',
|
||||
addRequired: false,
|
||||
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 " +
|
||||
awPopOver: "<p>Select the credential you want the job to use when accessing the remote hosts. Choose the credential containing " +
|
||||
" the username and SSH key or password that Ansbile will need to log into the remote hosts.</p>",
|
||||
dataTitle: 'Credential',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
cloud_credential: {
|
||||
label: 'Cloud Credential',
|
||||
type: 'lookup',
|
||||
sourceModel: 'cloud_credential',
|
||||
sourceField: 'name',
|
||||
ngClick: 'lookUpCloudcredential()',
|
||||
addRequired: false,
|
||||
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 " +
|
||||
@ -125,16 +124,16 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
dataTitle: 'Cloud Credential',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
forks: {
|
||||
label: 'Forks',
|
||||
id: 'forks-number',
|
||||
type: 'number',
|
||||
type: 'number',
|
||||
integer: true,
|
||||
min: 0,
|
||||
spinner: true,
|
||||
spinner: true,
|
||||
"default": '0',
|
||||
addRequired: false,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
'class': "input-small",
|
||||
column: 1,
|
||||
@ -144,11 +143,11 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
dataTitle: 'Forks',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
limit: {
|
||||
label: 'Limit',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
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. " +
|
||||
@ -157,26 +156,26 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
dataTitle: 'Limit',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
verbosity: {
|
||||
label: 'Verbosity',
|
||||
type: 'select',
|
||||
ngOptions: 'v.label for v in verbosity_options',
|
||||
"default": 0,
|
||||
addRequired: true,
|
||||
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,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
"default": "---",
|
||||
column: 2,
|
||||
@ -189,13 +188,13 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
dataTitle: 'Extra Variables',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
job_tags: {
|
||||
label: 'Job Tags',
|
||||
type: 'textarea',
|
||||
rows: 1,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
type: 'textarea',
|
||||
rows: 1,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
'class': 'span12',
|
||||
column: 2,
|
||||
awPopOver: "<p>Provide a comma separated list of tags.</p>\n" +
|
||||
@ -203,26 +202,25 @@ 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 "configuration", "packages" and "install".</p>" +
|
||||
"<p>If you just want to run the "configuration" and "packages" 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"
|
||||
},
|
||||
},
|
||||
allow_callbacks: {
|
||||
label: 'Allow Callbacks',
|
||||
type: 'checkbox',
|
||||
addRequired: false,
|
||||
addRequired: false,
|
||||
editRequird: false,
|
||||
trueValue: 'true',
|
||||
falseValue: 'false',
|
||||
ngChange: "toggleCallback('host_config_key')",
|
||||
column: 2,
|
||||
awPopOver: "<p>Create a callback URL a host can use to contact Tower and request a configuration update " +
|
||||
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\" " +
|
||||
"<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>" +
|
||||
@ -230,11 +228,11 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
dataPlacement: 'right',
|
||||
dataTitle: 'Callback URL',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
callback_url: {
|
||||
label: 'Callback URL',
|
||||
label: 'Callback URL',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
readonly: true,
|
||||
column: 2,
|
||||
@ -242,7 +240,7 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
'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\" " +
|
||||
"<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>" +
|
||||
@ -250,7 +248,7 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
dataPlacement: 'right',
|
||||
dataTitle: 'Callback URL',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
host_config_key: {
|
||||
label: 'Host Config Key',
|
||||
type: 'text',
|
||||
@ -259,25 +257,25 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
column: 2,
|
||||
awPopOver: "<p>When contacting the Tower server 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\" " +
|
||||
"<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: {
|
||||
save: {
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
related: {
|
||||
|
||||
jobs: {
|
||||
type: 'collection',
|
||||
@ -295,54 +293,55 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
awToolTip: "Reset the search filter",
|
||||
ngClick: "resetSearch('job')",
|
||||
iconSize: 'large'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
id: {
|
||||
label: 'Job ID',
|
||||
key: true,
|
||||
desc: true,
|
||||
searchType: 'int'
|
||||
},
|
||||
searchType: 'int'
|
||||
},
|
||||
created: {
|
||||
label: 'Date',
|
||||
link: false,
|
||||
searchable: false
|
||||
},
|
||||
},
|
||||
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" },
|
||||
{ name: "pending", value: "pending" },
|
||||
{ name: "running", value: "running" },
|
||||
{ name: "running", value: "running" },
|
||||
{ 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'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
label: 'View',
|
||||
ngClick: "edit('jobs', \{\{ job.id \}\}, '\{\{ job.name \}\}')",
|
||||
ngClick: "edit('jobs', job.id, job.name)",
|
||||
icon: 'icon-zoom-in'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}); //InventoryForm
|
||||
|
||||
|
||||
@ -7,9 +7,8 @@
|
||||
* @dict
|
||||
*/
|
||||
angular.module('JobFormDefinition', [])
|
||||
.value(
|
||||
'JobForm', {
|
||||
|
||||
.value('JobForm', {
|
||||
|
||||
addTitle: 'Create Job',
|
||||
editTitle: '{{ id }} - {{ name }}',
|
||||
name: 'jobs',
|
||||
@ -26,19 +25,19 @@ angular.module('JobFormDefinition', [])
|
||||
icon: 'icon-zoom-in',
|
||||
active: true,
|
||||
ngShow: "job_id !== null"
|
||||
},
|
||||
},
|
||||
events: {
|
||||
href: "/#/jobs/{{ job_id }}/job_events",
|
||||
label: 'Events',
|
||||
icon: 'icon-list-ul'
|
||||
},
|
||||
hosts: {
|
||||
},
|
||||
hosts: {
|
||||
href: "/#/jobs/{{ job_id }}/job_host_summaries",
|
||||
label: 'Host Summary',
|
||||
icon: 'icon-laptop'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
label: 'Job Template',
|
||||
@ -47,20 +46,20 @@ angular.module('JobFormDefinition', [])
|
||||
editRequired: false,
|
||||
readonly: true,
|
||||
column: 1
|
||||
},
|
||||
description: {
|
||||
},
|
||||
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,
|
||||
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 " +
|
||||
@ -69,7 +68,7 @@ angular.module('JobFormDefinition', [])
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body',
|
||||
column: 1
|
||||
},
|
||||
},
|
||||
inventory: {
|
||||
label: 'Inventory',
|
||||
type: 'lookup',
|
||||
@ -83,7 +82,7 @@ angular.module('JobFormDefinition', [])
|
||||
dataTitle: 'Inventory',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
project: {
|
||||
label: 'Project',
|
||||
type: 'lookup',
|
||||
@ -97,42 +96,42 @@ angular.module('JobFormDefinition', [])
|
||||
dataTitle: 'Project',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
playbook: {
|
||||
label: 'Playbook',
|
||||
type:'select',
|
||||
type: 'select',
|
||||
ngOptions: 'book for book in playbook_options',
|
||||
id: 'playbook-select',
|
||||
addRequired: true,
|
||||
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,
|
||||
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>",
|
||||
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,
|
||||
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 " +
|
||||
@ -140,17 +139,17 @@ angular.module('JobFormDefinition', [])
|
||||
dataTitle: 'Cloud Credential',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
forks: {
|
||||
label: 'Forks',
|
||||
id: 'forks-number',
|
||||
type: 'number',
|
||||
type: 'number',
|
||||
integer: true,
|
||||
min: 0,
|
||||
spinner: true,
|
||||
spinner: true,
|
||||
"class": 'input-small',
|
||||
"default": '0',
|
||||
addRequired: false,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
column: 1,
|
||||
disabled: true,
|
||||
@ -158,43 +157,43 @@ angular.module('JobFormDefinition', [])
|
||||
dataContainer: 'body',
|
||||
dataTitle: 'Forks',
|
||||
dataPlacement: 'right'
|
||||
},
|
||||
},
|
||||
limit: {
|
||||
label: 'Limit',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
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 ; : or ,</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 " +
|
||||
"<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,
|
||||
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,
|
||||
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 " +
|
||||
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" +
|
||||
@ -203,13 +202,13 @@ angular.module('JobFormDefinition', [])
|
||||
dataTitle: 'Extra Variables',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right'
|
||||
},
|
||||
},
|
||||
job_tags: {
|
||||
label: 'Job Tags',
|
||||
type: 'textarea',
|
||||
rows: 1,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
type: 'textarea',
|
||||
rows: 1,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
'class': 'span12',
|
||||
column: 2,
|
||||
awPopOver: "<p>Provide a comma separated list of tags.</p>\n" +
|
||||
@ -217,27 +216,27 @@ angular.module('JobFormDefinition', [])
|
||||
"<p>For example, you might have a task consisiting of a long list of actions. Tag values can be assigned to each action. " +
|
||||
"Suppose the actions have been assigned tag values of "configuration", "packages" and "install".</p>" +
|
||||
"<p>If you just want to run the "configuration" and "packages" actions, you would enter the following here " +
|
||||
"in the Job Tags field:<\p>\n" +
|
||||
"in the Job Tags field:</p>\n" +
|
||||
"<blockquote>configuration,packages</blockquote>\n",
|
||||
dataTitle: "Job Tags",
|
||||
dataContainer: 'body',
|
||||
dataPlacement: "right"
|
||||
},
|
||||
},
|
||||
allow_callbacks: {
|
||||
label: 'Allow Callbacks',
|
||||
type: 'checkbox',
|
||||
addRequired: false,
|
||||
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 " +
|
||||
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\" " +
|
||||
"<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>" +
|
||||
@ -245,11 +244,11 @@ angular.module('JobFormDefinition', [])
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body',
|
||||
dataTitle: 'Callback URL'
|
||||
},
|
||||
},
|
||||
callback_url: {
|
||||
label: 'Callback URL',
|
||||
label: 'Callback URL',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
readonly: true,
|
||||
column: 2,
|
||||
@ -257,7 +256,7 @@ angular.module('JobFormDefinition', [])
|
||||
'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\" " +
|
||||
"<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>" +
|
||||
@ -265,7 +264,7 @@ angular.module('JobFormDefinition', [])
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body',
|
||||
dataTitle: 'Callback URL'
|
||||
},
|
||||
},
|
||||
host_config_key: {
|
||||
label: 'Host Config Key',
|
||||
type: 'text',
|
||||
@ -274,64 +273,65 @@ angular.module('JobFormDefinition', [])
|
||||
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\" " +
|
||||
"<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',
|
||||
buttons: {
|
||||
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: 'formSave()',
|
||||
ngDisabled: true
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
label: 'Reset',
|
||||
icon: 'icon-undo',
|
||||
'class': 'btn btn-default',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
ngDisabled: true
|
||||
}
|
||||
},
|
||||
|
||||
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: {
|
||||
label: 'Created On',
|
||||
type: 'text',
|
||||
readonly: true
|
||||
},
|
||||
},
|
||||
result_stdout: {
|
||||
label: 'Standard Out',
|
||||
label: 'Standard Out',
|
||||
type: 'textarea',
|
||||
readonly: true,
|
||||
xtraWide: true,
|
||||
rows: "\{\{ stdout_rows \}\}",
|
||||
rows: "{{ stdout_rows }}",
|
||||
"class": 'nowrap mono-space',
|
||||
ngShow: "result_stdout != ''"
|
||||
},
|
||||
},
|
||||
result_traceback: {
|
||||
label: 'Traceback',
|
||||
type: 'textarea',
|
||||
xtraWide: true,
|
||||
readonly: true,
|
||||
rows: "\{\{ traceback_rows \}\}",
|
||||
rows: "{{ traceback_rows }}",
|
||||
"class": 'nowrap mono-space',
|
||||
ngShow: "result_traceback != ''"
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
statusActions: {
|
||||
refresh: {
|
||||
refresh: {
|
||||
dataPlacement: 'top',
|
||||
icon: "icon-refresh",
|
||||
iconSize: 'large',
|
||||
@ -340,8 +340,7 @@ angular.module('JobFormDefinition', [])
|
||||
'class': 'btn-xs btn-primary',
|
||||
awToolTip: "Refresh the page",
|
||||
ngClick: "refresh()"
|
||||
}
|
||||
}
|
||||
|
||||
}); //Form
|
||||
}
|
||||
|
||||
});
|
||||
84
awx/ui/static/js/forms/LicenseForm.js
Normal file
84
awx/ui/static/js/forms/LicenseForm.js
Normal file
@ -0,0 +1,84 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* LicenseForm.js
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('LicenseFormDefinition', [])
|
||||
.value('LicenseForm', {
|
||||
|
||||
name: 'license',
|
||||
well: false,
|
||||
forceListeners: true,
|
||||
|
||||
fields: {
|
||||
license_status: {
|
||||
type: 'custom',
|
||||
control: "<div class=\"license-status\" ng-class=\"status_color\"><i class=\"fa fa-circle\"></i> " +
|
||||
"{{ license_status }}</span></div>",
|
||||
readonly: true,
|
||||
section: 'License'
|
||||
},
|
||||
license_key: {
|
||||
label: 'Key',
|
||||
type: 'textarea',
|
||||
'class': 'modal-input-xlarge',
|
||||
readonly: true,
|
||||
section: 'License'
|
||||
},
|
||||
license_date: {
|
||||
label: 'Expires On',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
section: 'License'
|
||||
},
|
||||
time_remaining: {
|
||||
label: 'Time Left',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
section: 'License'
|
||||
},
|
||||
available_instances: {
|
||||
label: 'Available',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
section: 'Managed Hosts'
|
||||
},
|
||||
current_instances: {
|
||||
label: 'Used',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
section: 'Managed Hosts'
|
||||
},
|
||||
free_instances: {
|
||||
label: 'Remaining',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
section: 'Managed Hosts',
|
||||
controlNGClass: 'free_instances_class',
|
||||
labelNGClass: 'free_instances_class'
|
||||
},
|
||||
company_name: {
|
||||
label: 'Company',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
section: 'Contact Info'
|
||||
},
|
||||
contact_name: {
|
||||
label: 'Contact',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
section: 'Contact Info'
|
||||
},
|
||||
contact_email: {
|
||||
label: 'Contact Email',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
section: 'Contact Info'
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -4,16 +4,19 @@
|
||||
* Organization.js
|
||||
* Form definition for Organization model
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('OrganizationFormDefinition', [])
|
||||
.value(
|
||||
'OrganizationForm', {
|
||||
|
||||
addTitle: 'Create Organization', //Title in add mode
|
||||
editTitle: '{{ name }}', //Title in edit mode
|
||||
name: 'organization', //entity or model name in singular form
|
||||
well: true, //Wrap the form with TB well/
|
||||
.value('OrganizationForm', {
|
||||
|
||||
addTitle: 'Create Organization', //Title in add mode
|
||||
editTitle: '{{ name }}', //Title in edit mode
|
||||
name: 'organization', //entity or model name in singular form
|
||||
well: true,
|
||||
collapse: true,
|
||||
collapseTitle: "Properties",
|
||||
collapseMode: 'edit',
|
||||
collapseOpen: true,
|
||||
|
||||
actions: {
|
||||
stream: {
|
||||
@ -24,8 +27,8 @@ angular.module('OrganizationFormDefinition', [])
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
iconSize: 'large'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
@ -34,120 +37,118 @@ angular.module('OrganizationFormDefinition', [])
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
capitalize: false
|
||||
},
|
||||
description: {
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
related: {
|
||||
|
||||
users: {
|
||||
users: {
|
||||
type: 'collection',
|
||||
title: 'Users',
|
||||
iterator: 'user',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
ngClick: "add('users')",
|
||||
label: 'Add',
|
||||
icon: 'icon-plus',
|
||||
awToolTip: 'Add a new user'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
username: {
|
||||
key: true,
|
||||
label: 'Username'
|
||||
},
|
||||
},
|
||||
first_name: {
|
||||
label: 'First Name'
|
||||
},
|
||||
},
|
||||
last_name: {
|
||||
label: 'Last Name'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
label: 'Edit',
|
||||
ngClick: "edit('users', \{\{ user.id \}\}, '\{\{ user.username \}\}')",
|
||||
icon: 'icon-edit',
|
||||
'class': 'btn-default',
|
||||
awToolTip: 'Edit user'
|
||||
},
|
||||
"delete": {
|
||||
label: 'Delete',
|
||||
ngClick: "delete('users', \{\{ user.id \}\}, '\{\{ user.username \}\}', 'users')",
|
||||
icon: 'icon-trash',
|
||||
"class": 'btn-danger',
|
||||
awToolTip: 'Remove user'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
admins: { // Assumes a plural name (e.g. things)
|
||||
fieldActions: {
|
||||
edit: {
|
||||
label: 'Edit',
|
||||
ngClick: "edit('users', user.id, user.username)",
|
||||
icon: 'icon-edit',
|
||||
'class': 'btn-default',
|
||||
awToolTip: 'Edit user'
|
||||
},
|
||||
"delete": {
|
||||
label: 'Delete',
|
||||
ngClick: "delete('users', user.id, user.username, 'users')",
|
||||
icon: 'icon-trash',
|
||||
"class": 'btn-danger',
|
||||
awToolTip: 'Remove user'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
admins: { // Assumes a plural name (e.g. things)
|
||||
type: 'collection',
|
||||
title: 'Administrators',
|
||||
iterator: 'admin', // Singular form of name (e.g. thing)
|
||||
open: false, // Open accordion on load?
|
||||
iterator: 'admin', // Singular form of name (e.g. thing)
|
||||
open: false, // Open accordion on load?
|
||||
base: '/users',
|
||||
actions: { // Actions displayed top right of list
|
||||
actions: { // Actions displayed top right of list
|
||||
add: {
|
||||
ngClick: "add('admins')",
|
||||
icon: 'icon-plus',
|
||||
label: 'Add',
|
||||
awToolTip: 'Add new administrator'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
fields: {
|
||||
username: {
|
||||
key: true,
|
||||
label: 'Username'
|
||||
},
|
||||
},
|
||||
first_name: {
|
||||
label: 'First Name'
|
||||
},
|
||||
},
|
||||
last_name: {
|
||||
label: 'Last Name'
|
||||
}
|
||||
},
|
||||
fieldActions: { // Actions available on each row
|
||||
}
|
||||
},
|
||||
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'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}); //OrganizationForm
|
||||
}
|
||||
|
||||
|
||||
}); //OrganizationForm
|
||||
|
||||
@ -5,60 +5,63 @@
|
||||
*
|
||||
* Form definition for Projects model
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('PermissionFormDefinition', [])
|
||||
.value(
|
||||
'PermissionsForm', {
|
||||
|
||||
addTitle: 'Add Permission', //Title in add mode
|
||||
editTitle: '{{ name }}', //Title in edit mode
|
||||
name: 'permission', //entity or model name in singular form
|
||||
well: true, //Wrap the form with TB well
|
||||
forceListeners: true,
|
||||
.value('PermissionsForm', {
|
||||
|
||||
addTitle: 'Add Permission', //Title in add mode
|
||||
editTitle: '{{ name }}', //Title in edit mode
|
||||
name: 'permission', //entity or model name in singular form
|
||||
well: true, //Wrap the form with TB well
|
||||
forceListeners: true,
|
||||
|
||||
stream: {
|
||||
'class': "btn-primary btn-xs activity-btn",
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
dataPlacement: "top",
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
iconSize: 'large'
|
||||
},
|
||||
|
||||
'class': "btn-primary btn-xs activity-btn",
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
dataPlacement: "top",
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
iconSize: 'large'
|
||||
},
|
||||
|
||||
fields: {
|
||||
category: {
|
||||
label: 'Permission Type',
|
||||
labelClass: 'prepend-asterisk',
|
||||
type: 'radio_group',
|
||||
options: [
|
||||
{ label: 'Inventory', value: 'Inventory', selected: true },
|
||||
{ label: 'Deployment', value: 'Deploy'}
|
||||
],
|
||||
options: [{
|
||||
label: 'Inventory',
|
||||
value: 'Inventory',
|
||||
selected: true
|
||||
}, {
|
||||
label: 'Deployment',
|
||||
value: 'Deploy'
|
||||
}],
|
||||
ngChange: 'selectCategory()'
|
||||
},
|
||||
},
|
||||
name: {
|
||||
label: 'Name',
|
||||
type: 'text',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
capitalize: false
|
||||
},
|
||||
description: {
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
},
|
||||
user: {
|
||||
label: 'User',
|
||||
label: 'User',
|
||||
type: 'hidden'
|
||||
},
|
||||
},
|
||||
team: {
|
||||
label: 'Team',
|
||||
type: 'hidden'
|
||||
},
|
||||
},
|
||||
project: {
|
||||
label: 'Project',
|
||||
type: 'lookup',
|
||||
@ -66,44 +69,65 @@ angular.module('PermissionFormDefinition', [])
|
||||
sourceField: 'name',
|
||||
ngShow: "category == 'Deploy'",
|
||||
ngClick: 'lookUpProject()',
|
||||
awRequiredWhen: { variable: "projectrequired", init: "false" }
|
||||
},
|
||||
awRequiredWhen: {
|
||||
variable: "projectrequired",
|
||||
init: "false"
|
||||
}
|
||||
},
|
||||
inventory: {
|
||||
label: 'Inventory',
|
||||
type: 'lookup',
|
||||
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' }]
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
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: {
|
||||
save: {
|
||||
ngClick: 'formSave()',
|
||||
ngDisabled: true
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true
|
||||
}
|
||||
},
|
||||
|
||||
related: { }
|
||||
|
||||
}); // Form
|
||||
@ -7,17 +7,16 @@
|
||||
*
|
||||
*/
|
||||
angular.module('ProjectStatusDefinition', [])
|
||||
.value(
|
||||
'ProjectStatusForm', {
|
||||
.value('ProjectStatusForm', {
|
||||
|
||||
name: 'project_update',
|
||||
editTitle: 'SCM Status',
|
||||
editTitle: 'SCM Status',
|
||||
well: false,
|
||||
'class': 'horizontal-narrow',
|
||||
|
||||
fields: {
|
||||
created: {
|
||||
label: 'Created',
|
||||
label: 'Created',
|
||||
type: 'text',
|
||||
readonly: true
|
||||
},
|
||||
@ -27,7 +26,7 @@ angular.module('ProjectStatusDefinition', [])
|
||||
readonly: true
|
||||
},
|
||||
result_stdout: {
|
||||
label: 'Std Out',
|
||||
label: 'Std Out',
|
||||
type: 'textarea',
|
||||
ngShow: "result_stdout",
|
||||
'class': 'mono-space',
|
||||
@ -35,7 +34,7 @@ angular.module('ProjectStatusDefinition', [])
|
||||
rows: 15
|
||||
},
|
||||
result_traceback: {
|
||||
label: 'Traceback',
|
||||
label: 'Traceback',
|
||||
type: 'textarea',
|
||||
ngShow: "result_traceback",
|
||||
'class': 'mono-space',
|
||||
|
||||
@ -5,17 +5,20 @@
|
||||
*
|
||||
* Form definition for Projects model
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('ProjectFormDefinition', [])
|
||||
.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
|
||||
.value('ProjectsForm', {
|
||||
|
||||
addTitle: 'Create Project',
|
||||
editTitle: '{{ name }}',
|
||||
name: 'project',
|
||||
forceListeners: true,
|
||||
well: true,
|
||||
collapse: true,
|
||||
collapseTitle: "Properties",
|
||||
collapseMode: 'edit',
|
||||
collapseOpen: true,
|
||||
|
||||
actions: {
|
||||
stream: {
|
||||
@ -26,8 +29,8 @@ angular.module('ProjectFormDefinition', [])
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
iconSize: 'large'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
@ -36,13 +39,13 @@ angular.module('ProjectFormDefinition', [])
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
capitalize: false
|
||||
},
|
||||
description: {
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
},
|
||||
organization: {
|
||||
label: 'Organization',
|
||||
type: 'lookup',
|
||||
@ -52,35 +55,38 @@ 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 ' +
|
||||
'access to modify the project.',
|
||||
'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 ' +
|
||||
'access to modify the project.',
|
||||
dataTitle: 'Organization',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right'
|
||||
},
|
||||
},
|
||||
scm_type: {
|
||||
label: 'SCM Type',
|
||||
type: 'select',
|
||||
ngOptions: 'type.label for type in scm_type_options',
|
||||
ngChange: 'scmChange()',
|
||||
addRequired: true,
|
||||
addRequired: true,
|
||||
editRequired: true
|
||||
},
|
||||
},
|
||||
missing_path_alert: {
|
||||
type: 'alertblock',
|
||||
"class": 'alert-info',
|
||||
type: 'alertblock',
|
||||
"class": 'alert-info',
|
||||
ngShow: "showMissingPlaybooksAlert && scm_type.value == ''",
|
||||
alertTxt: '<p class=\"text-justify\"><strong>WARNING:</strong> There are no unassigned playbook directories in the base ' +
|
||||
'project path {{ base_dir }}. Either the projects directory is empty, or all of the contents are already assigned to ' +
|
||||
'other projects. New projects can be checked out from source control by ' +
|
||||
'other projects. New projects can be checked out from source control by ' +
|
||||
'changing the SCM type option rather than specifying checkout paths manually. To continue with manual setup, log into ' +
|
||||
'the Tower host and ensure content is present in a subdirectory under {{ base_dir }}. Run "chown -R awx" on the content ' +
|
||||
'directory to ensure Tower can read the playbooks.</p>',
|
||||
closeable: false
|
||||
},
|
||||
},
|
||||
base_dir: {
|
||||
label: 'Project Base Path',
|
||||
type: 'textarea',
|
||||
@ -88,61 +94,69 @@ angular.module('ProjectFormDefinition', [])
|
||||
showonly: true,
|
||||
ngShow: "scm_type.value == ''",
|
||||
awPopOver: '<p>Base path used for locating playbooks. Directories found inside this path will be listed in the playbook directory drop-down. ' +
|
||||
'Together the base path and selected playbook directory provide the full path used to locate playbooks.</p>' +
|
||||
'<p>Use PROJECTS_ROOT in your environment settings file to determine the base path value.</p>',
|
||||
'Together the base path and selected playbook directory provide the full path used to locate playbooks.</p>' +
|
||||
'<p>Use PROJECTS_ROOT in your environment settings file to determine the base path value.</p>',
|
||||
dataTitle: 'Project Base Path',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right'
|
||||
},
|
||||
},
|
||||
local_path: {
|
||||
label: 'Playbook Directory',
|
||||
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>' +
|
||||
'<p>Use PROJECTS_ROOT in your environment settings file to determine the base path value.</p>',
|
||||
'Together the base path and the playbook directory provide the full path used to locate playbooks.</p>' +
|
||||
'<p>Use PROJECTS_ROOT in your environment settings file to determine the base path value.</p>',
|
||||
dataTitle: 'Project Path',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right'
|
||||
},
|
||||
},
|
||||
scm_url: {
|
||||
label: 'SCM URL',
|
||||
type: 'text',
|
||||
ngShow: "scm_type && scm_type.value !== ''",
|
||||
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',
|
||||
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',
|
||||
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'" }
|
||||
]
|
||||
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',
|
||||
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',
|
||||
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'"
|
||||
}]
|
||||
},
|
||||
scm_branch: {
|
||||
labelBind: "scmBranchLabel",
|
||||
type: 'text',
|
||||
ngShow: "scm_type && scm_type.value !== ''",
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
},
|
||||
credential: {
|
||||
label: 'SCM Credential',
|
||||
type: 'lookup',
|
||||
@ -150,111 +164,105 @@ angular.module('ProjectFormDefinition', [])
|
||||
sourceModel: 'credential',
|
||||
sourceField: 'name',
|
||||
ngClick: 'lookUpCredential()',
|
||||
addRequired: false,
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
},
|
||||
checkbox_group: {
|
||||
label: 'SCM Update Options',
|
||||
type: 'checkbox_group',
|
||||
ngShow: "scm_type && scm_type.value !== ''",
|
||||
fields: [
|
||||
{
|
||||
name: 'scm_clean',
|
||||
label: 'Clean',
|
||||
type: 'checkbox',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPopOver: '<p>Remove any local modifications prior to performing an update.</p>',
|
||||
dataTitle: 'SCM Clean',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right',
|
||||
labelClass: 'checkbox-options'
|
||||
},
|
||||
{
|
||||
name: 'scm_delete_on_update',
|
||||
label: 'Delete on Update',
|
||||
type: 'checkbox',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPopOver: '<p>Delete the local repository in its entirety prior to performing an update.</p><p>Depending on the size of the ' +
|
||||
'repository this may significantly increase the amount of time required to complete an update.</p>',
|
||||
dataTitle: 'SCM Delete',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right',
|
||||
labelClass: 'checkbox-options'
|
||||
},
|
||||
{
|
||||
name: 'scm_update_on_launch',
|
||||
label: 'Update on Launch',
|
||||
type: 'checkbox',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPopOver: '<p>Each time a job runs using this project, perform an update to the local repository prior to starting the job.</p>',
|
||||
dataTitle: 'SCM Update',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right',
|
||||
labelClass: 'checkbox-options'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
fields: [{
|
||||
name: 'scm_clean',
|
||||
label: 'Clean',
|
||||
type: 'checkbox',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPopOver: '<p>Remove any local modifications prior to performing an update.</p>',
|
||||
dataTitle: 'SCM Clean',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right',
|
||||
labelClass: 'checkbox-options'
|
||||
}, {
|
||||
name: 'scm_delete_on_update',
|
||||
label: 'Delete on Update',
|
||||
type: 'checkbox',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPopOver: '<p>Delete the local repository in its entirety prior to performing an update.</p><p>Depending on the size of the ' +
|
||||
'repository this may significantly increase the amount of time required to complete an update.</p>',
|
||||
dataTitle: 'SCM Delete',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right',
|
||||
labelClass: 'checkbox-options'
|
||||
}, {
|
||||
name: 'scm_update_on_launch',
|
||||
label: 'Update on Launch',
|
||||
type: 'checkbox',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPopOver: '<p>Each time a job runs using this project, perform an update to the local repository prior to starting the job.</p>',
|
||||
dataTitle: 'SCM Update',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right',
|
||||
labelClass: 'checkbox-options'
|
||||
}]
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
buttons: {
|
||||
save: {
|
||||
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',
|
||||
iterator: 'organization',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
actions: {
|
||||
add: {
|
||||
ngClick: "add('organizations')",
|
||||
icon: 'icon-plus',
|
||||
label: 'Add',
|
||||
awToolTip: 'Add an organization'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
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'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}); // Form
|
||||
|
||||
|
||||
}); // Form
|
||||
@ -2,20 +2,19 @@
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Teams.js
|
||||
*
|
||||
* Form definition for Team model
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('TeamFormDefinition', [])
|
||||
.value(
|
||||
'TeamForm', {
|
||||
|
||||
addTitle: 'Create Team', //Legend in add mode
|
||||
editTitle: '{{ name }}', //Legend in edit mode
|
||||
.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,
|
||||
|
||||
@ -28,8 +27,8 @@ angular.module('TeamFormDefinition', [])
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
iconSize: 'large'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
@ -38,228 +37,230 @@ angular.module('TeamFormDefinition', [])
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
capitalize: false
|
||||
},
|
||||
description: {
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
},
|
||||
organization: {
|
||||
label: 'Organization',
|
||||
type: 'lookup',
|
||||
sourceModel: 'organization',
|
||||
sourceField: 'name',
|
||||
ngClick: 'lookUpOrganization()',
|
||||
awRequiredWhen: {variable: "teamrequired", init: "true" }
|
||||
awRequiredWhen: {
|
||||
variable: "teamrequired",
|
||||
init: "true"
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
buttons: {
|
||||
save: {
|
||||
ngClick: 'formSave()',
|
||||
ngDisabled: true
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
ngDisabled: true
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
credentials: {
|
||||
related: {
|
||||
|
||||
credentials: {
|
||||
type: 'collection',
|
||||
title: 'Credentials',
|
||||
iterator: 'credential',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
actions: {
|
||||
add: {
|
||||
ngClick: "add('credentials')",
|
||||
icon: 'icon-plus',
|
||||
label: 'Add',
|
||||
add: 'Add a new credential'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
label: 'Edit',
|
||||
ngClick: "edit('credentials', \{\{ credential.id \}\}, '\{\{ credential.name \}\}')",
|
||||
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'
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
permissions: {
|
||||
type: 'collection',
|
||||
title: 'Permissions',
|
||||
iterator: 'permission',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
ngClick: "add('permissions')",
|
||||
icon: 'icon-plus',
|
||||
label: 'Add',
|
||||
awToolTip: 'Add a permission for this user',
|
||||
ngShow: 'PermissionAddAllowed'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
key: true,
|
||||
label: 'Name',
|
||||
ngClick: "edit('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}')"
|
||||
},
|
||||
ngClick: "edit('permissions', permission.id, permission.name)"
|
||||
},
|
||||
inventory: {
|
||||
label: 'Inventory',
|
||||
sourceModel: 'inventory',
|
||||
sourceField: 'name',
|
||||
ngBind: 'permission.summary_fields.inventory.name'
|
||||
},
|
||||
},
|
||||
project: {
|
||||
label: 'Project',
|
||||
sourceModel: 'project',
|
||||
sourceField: 'name',
|
||||
ngBind: 'permission.summary_fields.project.name'
|
||||
},
|
||||
permission_type: {
|
||||
label: 'Permission'
|
||||
}
|
||||
},
|
||||
|
||||
permission_type: {
|
||||
label: 'Permission'
|
||||
}
|
||||
},
|
||||
|
||||
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'
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
"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',
|
||||
ngShow: 'PermissionAddAllowed'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
|
||||
projects: {
|
||||
projects: {
|
||||
type: 'collection',
|
||||
title: 'Projects',
|
||||
iterator: 'project',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
actions: {
|
||||
add: {
|
||||
ngClick: "add('projects')",
|
||||
icon: 'icon-plus',
|
||||
label: 'Add'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
label: 'Edit',
|
||||
ngClick: "edit('projects', \{\{ project.id \}\}, '\{\{ project.name \}\}')",
|
||||
icon: 'icon-edit',
|
||||
awToolTip: 'Modify the project',
|
||||
'class': 'btn btn-default'
|
||||
},
|
||||
"delete": {
|
||||
label: 'Delete',
|
||||
ngClick: "delete('projects', \{\{ project.id \}\}, '\{\{ project.name \}\}', 'projects')",
|
||||
icon: 'icon-trash',
|
||||
"class": 'btn-danger',
|
||||
awToolTip: 'Remove the project'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
users: {
|
||||
fieldActions: {
|
||||
edit: {
|
||||
label: 'Edit',
|
||||
ngClick: "edit('projects', project.id, project.name)",
|
||||
icon: 'icon-edit',
|
||||
awToolTip: 'Modify the project',
|
||||
'class': 'btn btn-default'
|
||||
},
|
||||
"delete": {
|
||||
label: 'Delete',
|
||||
ngClick: "delete('projects', project.id, project.name, 'projects')",
|
||||
icon: 'icon-trash',
|
||||
"class": 'btn-danger',
|
||||
awToolTip: 'Remove the project'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
users: {
|
||||
type: 'collection',
|
||||
title: 'Users',
|
||||
iterator: 'user',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
actions: {
|
||||
add: {
|
||||
ngClick: "add('users')",
|
||||
icon: 'icon-plus',
|
||||
label: 'Add',
|
||||
awToolTip: 'Add a user'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
username: {
|
||||
key: true,
|
||||
label: 'Username'
|
||||
},
|
||||
},
|
||||
first_name: {
|
||||
label: 'First Name'
|
||||
},
|
||||
},
|
||||
last_name: {
|
||||
label: 'Last Name'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
label: 'Edit',
|
||||
ngClick: "edit('users', \{\{ user.id \}\}, '\{\{ user.username \}\}')",
|
||||
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'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}); //InventoryForm
|
||||
|
||||
}
|
||||
|
||||
}); //InventoryForm
|
||||
@ -4,17 +4,20 @@
|
||||
* Users.js
|
||||
* Form definition for User model
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('UserFormDefinition', [])
|
||||
.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
|
||||
.value('UserForm', {
|
||||
|
||||
addTitle: 'Create User',
|
||||
editTitle: '{{ username }}',
|
||||
name: 'user',
|
||||
well: true,
|
||||
forceListeners: true,
|
||||
collapse: true,
|
||||
collapseTitle: "Properties",
|
||||
collapseMode: 'edit',
|
||||
collapseOpen: true,
|
||||
|
||||
actions: {
|
||||
stream: {
|
||||
@ -25,31 +28,31 @@ angular.module('UserFormDefinition', [])
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
iconSize: 'large'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
first_name: {
|
||||
first_name: {
|
||||
label: 'First Name',
|
||||
type: 'text',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
capitalize: true
|
||||
},
|
||||
last_name: {
|
||||
},
|
||||
last_name: {
|
||||
label: 'Last Name',
|
||||
type: 'text',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
capitalize: true
|
||||
},
|
||||
},
|
||||
email: {
|
||||
label: 'Email',
|
||||
type: 'email',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
autocomplete: false
|
||||
},
|
||||
},
|
||||
organization: {
|
||||
label: 'Organization',
|
||||
type: 'lookup',
|
||||
@ -57,14 +60,20 @@ 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 },
|
||||
autocomplete: false
|
||||
awRequiredWhen: {
|
||||
variable: "not_ldap_user",
|
||||
init: true
|
||||
},
|
||||
autocomplete: false
|
||||
},
|
||||
password: {
|
||||
label: 'Password',
|
||||
type: 'password',
|
||||
@ -74,7 +83,7 @@ angular.module('UserFormDefinition', [])
|
||||
ngChange: "clearPWConfirm('password_confirm')",
|
||||
autocomplete: false,
|
||||
chkPass: true
|
||||
},
|
||||
},
|
||||
password_confirm: {
|
||||
label: 'Confirm Password',
|
||||
type: 'password',
|
||||
@ -84,7 +93,7 @@ angular.module('UserFormDefinition', [])
|
||||
awPassMatch: true,
|
||||
associated: 'password',
|
||||
autocomplete: false
|
||||
},
|
||||
},
|
||||
is_superuser: {
|
||||
label: 'Superuser (User has full system administration privileges.)',
|
||||
type: 'checkbox',
|
||||
@ -92,171 +101,169 @@ angular.module('UserFormDefinition', [])
|
||||
falseValue: 'false',
|
||||
"default": 'false',
|
||||
ngShow: "current_user['is_superuser'] == true"
|
||||
},
|
||||
ldap_user: {
|
||||
label: 'Created by LDAP',
|
||||
},
|
||||
ldap_user: {
|
||||
label: 'Created by LDAP',
|
||||
type: 'checkbox',
|
||||
readonly: true
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
buttons: {
|
||||
save: {
|
||||
ngClick: 'formSave()',
|
||||
ngDisabled: true
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
ngDisabled: true
|
||||
}
|
||||
},
|
||||
|
||||
related: {
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
credentials: {
|
||||
type: 'collection',
|
||||
title: 'Credentials',
|
||||
iterator: 'credential',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
actions: {
|
||||
add: {
|
||||
ngClick: "add('credentials')",
|
||||
icon: 'icon-plus',
|
||||
label: 'Add',
|
||||
awToolTip: 'Add a credential for this user'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
label: 'Edit',
|
||||
ngClick: "edit('credentials', \{\{ credential.id \}\}, '\{\{ credential.name \}\}')",
|
||||
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'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
permissions: {
|
||||
type: 'collection',
|
||||
title: 'Permissions',
|
||||
iterator: 'permission',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
ngClick: "add('permissions')",
|
||||
icon: 'icon-plus',
|
||||
label: 'Add',
|
||||
awToolTip: 'Add a permission for this user',
|
||||
ngShow: 'PermissionAddAllowed'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
key: true,
|
||||
label: 'Name',
|
||||
ngClick: "edit('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}')"
|
||||
},
|
||||
ngClick: "edit('permissions', permission.id, permission.name)"
|
||||
},
|
||||
inventory: {
|
||||
label: 'Inventory',
|
||||
sourceModel: 'inventory',
|
||||
sourceField: 'name',
|
||||
ngBind: 'permission.summary_fields.inventory.name'
|
||||
},
|
||||
},
|
||||
project: {
|
||||
label: 'Project',
|
||||
sourceModel: 'project',
|
||||
sourceField: 'name',
|
||||
ngBind: 'permission.summary_fields.project.name'
|
||||
},
|
||||
},
|
||||
permission_type: {
|
||||
label: 'Permission'
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
label: 'Edit',
|
||||
ngClick: "edit('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}')",
|
||||
ngClick: "edit('permissions', permission.id, permission.name)",
|
||||
icon: 'icon-edit',
|
||||
awToolTip: 'Edit the permission',
|
||||
'class': 'btn btn-default'
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
"delete": {
|
||||
label: 'Delete',
|
||||
ngClick: "delete('permissions', \{\{ permission.id \}\}, '\{\{ permission.name \}\}', 'permissions')",
|
||||
ngClick: "delete('permissions', permission.id, permission.name, 'permissions')",
|
||||
icon: 'icon-trash',
|
||||
"class": 'btn-danger',
|
||||
awToolTip: 'Delete the permission',
|
||||
ngShow: 'PermissionAddAllowed'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
admin_of_organizations: { // Assumes a plural name (e.g. things)
|
||||
},
|
||||
|
||||
admin_of_organizations: { // Assumes a plural name (e.g. things)
|
||||
type: 'collection',
|
||||
title: 'Admin of Organizations',
|
||||
iterator: 'adminof', // Singular form of name (e.g. thing)
|
||||
open: false, // Open accordion on load?
|
||||
iterator: 'adminof', // Singular form of name (e.g. thing)
|
||||
open: false, // Open accordion on load?
|
||||
base: '/organizations',
|
||||
|
||||
actions: {
|
||||
},
|
||||
|
||||
actions: {},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
organizations: {
|
||||
organizations: {
|
||||
type: 'collection',
|
||||
title: 'Organizations',
|
||||
iterator: 'organization',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
},
|
||||
|
||||
actions: {},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
teams: {
|
||||
type: 'collection',
|
||||
@ -264,19 +271,18 @@ angular.module('UserFormDefinition', [])
|
||||
iterator: 'team',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
},
|
||||
actions: {},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
projects: {
|
||||
type: 'collection',
|
||||
@ -284,21 +290,19 @@ angular.module('UserFormDefinition', [])
|
||||
iterator: 'project',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
},
|
||||
actions: {},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}); //UserForm
|
||||
}
|
||||
|
||||
}); //UserForm
|
||||
@ -1,65 +1,86 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* InventoryGroups.js
|
||||
* InventoryGroups.js
|
||||
*
|
||||
* Help object for inventory groups/hosts page.
|
||||
*
|
||||
* @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>'
|
||||
},
|
||||
{
|
||||
'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."
|
||||
},
|
||||
{
|
||||
"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 },
|
||||
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>"
|
||||
},
|
||||
{
|
||||
"will be added to the selected group.</div>"
|
||||
}, {
|
||||
intro: 'Copy or move groups:',
|
||||
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>"
|
||||
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 },
|
||||
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>"
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
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>"
|
||||
}]
|
||||
}
|
||||
});
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -4,102 +4,103 @@
|
||||
* helpers/Access.js
|
||||
*
|
||||
* Routines for checking user access and license state
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('AccessHelper', ['RestServices', 'Utilities', 'ngCookies'])
|
||||
.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;
|
||||
'use strict';
|
||||
|
||||
if (me.is_superuser) {
|
||||
scope.PermissionAddAllowed = true;
|
||||
}
|
||||
else {
|
||||
if (me.related.admin_of_organizations) {
|
||||
Rest.setUrl(me.related.admin_of_organizations);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
if (data.results.length > 0) {
|
||||
scope.PermissionAddAllowed = true;
|
||||
}
|
||||
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 });
|
||||
});
|
||||
}
|
||||
}
|
||||
//if (!access) {
|
||||
// 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() {
|
||||
// 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 ' +
|
||||
'<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>';
|
||||
angular.module('AccessHelper', ['RestServices', 'Utilities', 'ngCookies'])
|
||||
.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,
|
||||
scope = params.scope;
|
||||
|
||||
if (license && !Authorization.licenseTested()) {
|
||||
// This is our first time evaluating the license
|
||||
license['tested'] = true;
|
||||
$cookieStore.remove('license');
|
||||
$cookieStore.put('license', license);
|
||||
$rootScope.license_tested = true;
|
||||
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) {
|
||||
// demo
|
||||
status = 'alert-info';
|
||||
hdr = 'Tower Demo';
|
||||
msg = '<p>Thank you for trying Ansible Tower. You can use this edition to manage up to 10 hosts free.</p>' +
|
||||
purchase_msg;
|
||||
Alert(hdr, msg, status);
|
||||
}
|
||||
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) {
|
||||
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) {
|
||||
status = 'alert-info';
|
||||
hdr = 'License Warning';
|
||||
msg = '<p>Your Ansible Tower license has reached capacity for the number of managed ' +
|
||||
'hosts allowed. You will not be able to add any additional hosts.</p>' + purchase_msg;
|
||||
Alert(hdr, msg, status, null, true);
|
||||
}
|
||||
if (me.is_superuser) {
|
||||
scope.PermissionAddAllowed = true;
|
||||
} else {
|
||||
if (me.related.admin_of_organizations) {
|
||||
Rest.setUrl(me.related.admin_of_organizations);
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
if (data.results.length > 0) {
|
||||
scope.PermissionAddAllowed = true;
|
||||
} else {
|
||||
scope.PermissionAddAllowed = false;
|
||||
}
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors(scope, data, status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Call to ' + me.related.admin_of_organizations +
|
||||
' failed. DELETE returned status: ' + status
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
//if (!access) {
|
||||
// Alert('Access Denied', 'You do not have access to this function. Please contact your system administrator.');
|
||||
//}
|
||||
//return access;
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
.factory('CheckLicense', ['$rootScope', '$cookieStore', 'Alert', '$location', 'Authorization',
|
||||
function ($rootScope, $cookieStore, Alert, $location, Authorization) {
|
||||
return function () {
|
||||
// Check license status and alert the user, if needed
|
||||
var status = 'success',
|
||||
hdr, msg,
|
||||
license = $cookieStore.get('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);
|
||||
$rootScope.license_tested = true;
|
||||
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) {
|
||||
// demo
|
||||
status = 'alert-info';
|
||||
hdr = 'Tower Demo';
|
||||
msg = '<p>Thank you for trying Ansible Tower. You can use this edition to manage up to 10 hosts free.</p>' +
|
||||
purchase_msg;
|
||||
Alert(hdr, msg, status);
|
||||
}
|
||||
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) {
|
||||
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) {
|
||||
status = 'alert-info';
|
||||
hdr = 'License Warning';
|
||||
msg = '<p>Your Ansible Tower license has reached capacity for the number of managed ' +
|
||||
'hosts allowed. You will not be able to add any additional hosts.</p>' + purchase_msg;
|
||||
Alert(hdr, msg, status, null, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}]);
|
||||
]);
|
||||
@ -3,78 +3,62 @@
|
||||
*
|
||||
* ChildrenHelper
|
||||
*
|
||||
* Used in job_events to expand/collapse children by setting the
|
||||
* Used in job_events to expand/collapse children by setting the
|
||||
* 'show' attribute of each job_event in the set of job_events.
|
||||
* See the filter in job_events.js list.
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('ChildrenHelper', ['RestServices', 'Utilities'])
|
||||
.factory('ToggleChildren', ['Alert', 'Rest', 'GetBasePath','ProcessErrors','FormatDate',
|
||||
function(Alert, Rest, GetBasePath, ProcessErrors, FormatDate) {
|
||||
return function(params) {
|
||||
|
||||
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]
|
||||
|
||||
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);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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']) {
|
||||
collapse(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'use strict';
|
||||
|
||||
// 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) {
|
||||
clicked = i;
|
||||
found = true;
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Expand or collapse children based on clicked element's icon
|
||||
if (/plus-square-o/.test(set[clicked]['ngicon'])) {
|
||||
// Expand: lookup and display children
|
||||
expand(clicked);
|
||||
}
|
||||
else if (/minus-square-o/.test(set[clicked]['ngicon'])) {
|
||||
collapse(clicked);
|
||||
}
|
||||
|
||||
function collapse(node) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scan the array list and find the clicked element
|
||||
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)) {
|
||||
// Expand: lookup and display children
|
||||
expand(clicked);
|
||||
} else if (/minus-square-o/.test(set[clicked].ngicon)) {
|
||||
collapse(clicked);
|
||||
}
|
||||
};
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
]);
|
||||
@ -7,176 +7,185 @@
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('CredentialsHelper', ['Utilities'])
|
||||
|
||||
.factory('KindChange', [ 'Empty', function(Empty) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var form = params.form;
|
||||
var reset = params.reset;
|
||||
'use strict';
|
||||
|
||||
// Put things in a default state
|
||||
scope['usernameLabel'] = 'Username';
|
||||
scope['aws_required'] = false;
|
||||
scope['rackspace_required'] = false;
|
||||
scope['sshKeyDataLabel'] = 'SSH Private Key';
|
||||
|
||||
if (!Empty(scope['kind'])) {
|
||||
// Apply kind specific settings
|
||||
switch(scope['kind'].value) {
|
||||
angular.module('CredentialsHelper', ['Utilities'])
|
||||
|
||||
.factory('KindChange', ['Empty',
|
||||
function (Empty) {
|
||||
return function (params) {
|
||||
|
||||
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';
|
||||
|
||||
if (!Empty(scope.kind)) {
|
||||
// Apply kind specific settings
|
||||
switch (scope.kind.value) {
|
||||
case 'aws':
|
||||
scope['aws_required'] = true;
|
||||
break;
|
||||
case 'rax':
|
||||
scope['rackspace_required'] = true;
|
||||
scope.aws_required = true;
|
||||
break;
|
||||
case 'rax':
|
||||
scope.rackspace_required = true;
|
||||
break;
|
||||
case 'ssh':
|
||||
scope['usernameLabel'] = 'SSH Username';
|
||||
break;
|
||||
case 'scm':
|
||||
scope['sshKeyDataLabel'] = 'SCM Private Key';
|
||||
scope.usernameLabel = 'SSH Username';
|
||||
break;
|
||||
case 'scm':
|
||||
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;
|
||||
}
|
||||
|
||||
// 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');
|
||||
if (!Empty(scope.kind) && scope.kind.value !== '') {
|
||||
if ( $('#' + id + '-icon').hasClass('icon-minus') ) {
|
||||
scope.accordionToggle('#' + id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( $('#' + id + '-icon').hasClass('icon-plus') ) {
|
||||
scope.accordionToggle('#' + id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}])
|
||||
|
||||
|
||||
.factory('OwnerChange', [ function() {
|
||||
return function(params) {
|
||||
var scope = params.scope;
|
||||
var owner = scope['owner'];
|
||||
if (owner == 'team') {
|
||||
scope['team_required'] = true;
|
||||
scope['user_required'] = false;
|
||||
scope['user'] = null;
|
||||
scope['user_username'] = null;
|
||||
}
|
||||
else {
|
||||
scope['team_required'] = false;
|
||||
scope['user_required'] = true;
|
||||
scope['team'] = null;
|
||||
scope['team_name'] = null;
|
||||
}
|
||||
|
||||
}
|
||||
}])
|
||||
|
||||
|
||||
.factory('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 = {}
|
||||
|
||||
for (var fld in form.fields) {
|
||||
if (fld !== 'access_key' && fld !== 'secret_key' && fld !== 'ssh_username' &&
|
||||
fld !== 'ssh_password') {
|
||||
if (scope[fld] === null) {
|
||||
data[fld] = "";
|
||||
}
|
||||
else {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Empty(scope.team)) {
|
||||
data.team = scope.team;
|
||||
data.user = "";
|
||||
}
|
||||
else {
|
||||
data.user = scope.user;
|
||||
data.team = "";
|
||||
}
|
||||
|
||||
data['kind'] = scope['kind'].value;
|
||||
// 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;
|
||||
}
|
||||
|
||||
switch (data['kind']) {
|
||||
case 'ssh':
|
||||
data['password'] = scope['ssh_password'];
|
||||
break;
|
||||
// Collapse or open help widget based on whether scm value is selected
|
||||
collapse = $('#credential_kind').parent().find('.panel-collapse').first();
|
||||
id = collapse.attr('id');
|
||||
if (!Empty(scope.kind) && scope.kind.value !== '') {
|
||||
if ($('#' + id + '-icon').hasClass('icon-minus')) {
|
||||
scope.accordionToggle('#' + id);
|
||||
}
|
||||
} else {
|
||||
if ($('#' + id + '-icon').hasClass('icon-plus')) {
|
||||
scope.accordionToggle('#' + id);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
.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;
|
||||
}
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
.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 (fld in form.fields) {
|
||||
if (fld !== 'access_key' && fld !== 'secret_key' && fld !== 'ssh_username' &&
|
||||
fld !== 'ssh_password') {
|
||||
if (scope[fld] === null) {
|
||||
data[fld] = "";
|
||||
} else {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Empty(scope.team)) {
|
||||
data.team = scope.team;
|
||||
data.user = "";
|
||||
} else {
|
||||
data.user = scope.user;
|
||||
data.team = "";
|
||||
}
|
||||
|
||||
data.kind = scope.kind.value;
|
||||
|
||||
switch (data.kind) {
|
||||
case 'ssh':
|
||||
data.password = scope.ssh_password;
|
||||
break;
|
||||
case 'aws':
|
||||
data['username'] = scope['access_key'];
|
||||
data['password'] = scope['secret_key'];
|
||||
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 {
|
||||
Wait('start');
|
||||
if (mode == 'add') {
|
||||
var 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) {
|
||||
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 });
|
||||
});
|
||||
}
|
||||
else {
|
||||
var url = GetBasePath('credentials') + scope.id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.put(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
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 update Credential. PUT status: ' + status });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}]);
|
||||
|
||||
if (Empty(data.team) && Empty(data.user)) {
|
||||
Alert('Missing User or Team', 'You must provide either a User or a Team. If this credential will only be accessed by a specific ' +
|
||||
'user, select a User. To allow a team of users to access this credential, select a Team.', 'alert-danger');
|
||||
} else {
|
||||
Wait('start');
|
||||
if (mode === 'add') {
|
||||
url = (!Empty(data.team)) ? GetBasePath('teams') + data.team + '/credentials/' :
|
||||
GetBasePath('users') + data.user + '/credentials/';
|
||||
Rest.setUrl(url);
|
||||
Rest.post(data)
|
||||
.success(function () {
|
||||
Wait('stop');
|
||||
var base = $location.path().replace(/^\//, '').split('/')[0];
|
||||
if (base === 'credentials') {
|
||||
ReturnToCaller();
|
||||
}
|
||||
ReturnToCaller(1);
|
||||
})
|
||||
.error(function (data, status) {
|
||||
Wait('stop');
|
||||
ProcessErrors(scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to create new Credential. POST status: ' + status
|
||||
});
|
||||
});
|
||||
} else {
|
||||
url = GetBasePath('credentials') + scope.id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.put(data)
|
||||
.success(function () {
|
||||
Wait('stop');
|
||||
var base = $location.path().replace(/^\//, '').split('/')[0];
|
||||
if (base === 'credentials') {
|
||||
ReturnToCaller();
|
||||
}
|
||||
ReturnToCaller(1);
|
||||
})
|
||||
.error(function (data, status) {
|
||||
Wait('stop');
|
||||
ProcessErrors(scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to update Credential. PUT status: ' + status
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
]);
|
||||
@ -6,194 +6,57 @@
|
||||
* 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 + '/';
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Rest.setUrl(defaultUrl);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
|
||||
// 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) {
|
||||
case 'start':
|
||||
case 'end':
|
||||
case 'delta':
|
||||
case 'msg':
|
||||
case 'stdout':
|
||||
case 'stderr':
|
||||
case 'msg':
|
||||
case 'results':
|
||||
case 'module_name':
|
||||
case 'module_args':
|
||||
case 'rc':
|
||||
delete form.fields[fld];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($.isEmptyObject(data['event_data']) || !data['event_data']['res'] || typeof data['event_data']['res'] != 'string') {
|
||||
delete form.fields['traceback'];
|
||||
}
|
||||
|
||||
// Remove remaining form fields that do not have a corresponding data value
|
||||
for (var fld in form.fields) {
|
||||
switch (fld) {
|
||||
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) {
|
||||
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 (fld in form.fields) {
|
||||
switch (fld) {
|
||||
case 'start':
|
||||
case 'end':
|
||||
case 'delta':
|
||||
case 'msg':
|
||||
case 'stdout':
|
||||
case 'stderr':
|
||||
case 'msg':
|
||||
case 'results':
|
||||
case 'module_name':
|
||||
case 'module_args':
|
||||
case 'rc':
|
||||
delete form.fields[fld];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($.isEmptyObject(data.event_data) || !data.event_data.res || typeof data.event_data.res !== 'string') {
|
||||
delete form.fields.traceback;
|
||||
}
|
||||
|
||||
// Remove remaining form fields that do not have a corresponding data value
|
||||
for (fld in form.fields) {
|
||||
switch (fld) {
|
||||
case 'start':
|
||||
case 'end':
|
||||
case 'delta':
|
||||
@ -202,114 +65,118 @@ 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])) {
|
||||
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;
|
||||
rows = (rows > 10) ? 10 : rows;
|
||||
rows = (rows < 3) ? 3 : rows;
|
||||
form.fields[fld].rows = rows;
|
||||
}
|
||||
if (data.event_data && data.event_data.res && Empty(data.event_data.res[fld])) {
|
||||
delete form.fields[fld];
|
||||
} else {
|
||||
if (form.fields[fld].type === 'textarea') {
|
||||
n = data.event_data.res[fld].match(/\n/g);
|
||||
rows = (n) ? n.length : 1;
|
||||
rows = (rows > 10) ? 10 : rows;
|
||||
rows = (rows < 3) ? 3 : rows;
|
||||
form.fields[fld].rows = rows;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'results':
|
||||
if ( data['event_data'] && data['event_data']['res'] && data['event_data']['res'][fld] == undefined) {
|
||||
// not defined
|
||||
delete form.fields[fld];
|
||||
}
|
||||
else if (!Array.isArray(data['event_data']['res'][fld]) || data['event_data']['res'][fld].length == 0) {
|
||||
// defined, but empty
|
||||
delete form.fields[fld];
|
||||
}
|
||||
else {
|
||||
// defined and not empty, so attempt to size the textarea field
|
||||
var txt = '';
|
||||
for (var i=0; i < data['event_data']['res'][fld].length; i++) {
|
||||
txt += data['event_data']['res'][fld][i];
|
||||
}
|
||||
if (txt == '') {
|
||||
// there's an array, but the actual text is empty
|
||||
delete form.fields[fld];
|
||||
}
|
||||
else {
|
||||
var n = txt.match(/\n/g);
|
||||
var rows = (n) ? n.length : 1;
|
||||
rows = (rows > 10) ? 10 : rows;
|
||||
rows = (rows < 3) ? 3 : rows;
|
||||
form.fields[fld].rows = rows;
|
||||
}
|
||||
if (data.event_data && data.event_data.res && data.event_data.res[fld] === undefined) {
|
||||
// not defined
|
||||
delete form.fields[fld];
|
||||
} else if (!Array.isArray(data.event_data.res[fld]) || data.event_data.res[fld].length === 0) {
|
||||
// defined, but empty
|
||||
delete form.fields[fld];
|
||||
} else {
|
||||
// defined and not empty, so attempt to size the textarea field
|
||||
txt = '';
|
||||
for (i = 0; i < data.event_data.res[fld].length; i++) {
|
||||
txt += data.event_data.res[fld][i];
|
||||
}
|
||||
if (txt === '') {
|
||||
// there's an array, but the actual text is empty
|
||||
delete form.fields[fld];
|
||||
} else {
|
||||
n = txt.match(/\n/g);
|
||||
rows = (n) ? n.length : 1;
|
||||
rows = (rows > 10) ? 10 : rows;
|
||||
rows = (rows < 3) ? 3 : rows;
|
||||
form.fields[fld].rows = rows;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'module_name':
|
||||
case 'module_args':
|
||||
if (data['event_data'] && data['event_data']['res']) {
|
||||
if (data['event_data']['res']['invocation'] === undefined ||
|
||||
data['event_data']['res']['invocation'][fld] === undefined) {
|
||||
if (data.event_data && data.event_data.res) {
|
||||
if (data.event_data.res.invocation === undefined ||
|
||||
data.event_data.res.invocation[fld] === undefined) {
|
||||
delete form.fields[fld];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// load the form
|
||||
scope = generator.inject(form, { mode: 'edit', modal: true, related: false});
|
||||
generator.reset();
|
||||
scope.formModalAction = function() {
|
||||
$('#form-modal').modal("hide");
|
||||
}
|
||||
scope.formModalActionLabel = 'OK';
|
||||
scope.formModalCancelShow = false;
|
||||
scope.formModalInfo = 'View JSON';
|
||||
$('#form-modal .btn-success').removeClass('btn-success').addClass('btn-none');
|
||||
$('#form-modal').addClass('skinny-modal');
|
||||
scope.formModalHeader = data['event_display'].replace(/^\u00a0*/g,'');
|
||||
|
||||
// Respond to View JSON button
|
||||
scope.formModalInfoAction = function() {
|
||||
var generator = GenerateForm;
|
||||
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' });
|
||||
generator.reset();
|
||||
scope.formModal2Header = data['event_display'].replace(/^\u00a0*/g,'');
|
||||
scope.event_data = JSON.stringify(data['event_data'], null, '\t');
|
||||
scope.formModal2ActionLabel = 'OK';
|
||||
scope.formModal2CancelShow = false;
|
||||
scope.formModal2Info = false;
|
||||
scope.formModalInfo = 'View JSON';
|
||||
scope.formModal2Action = function() {
|
||||
$('#form-modal2').modal("hide");
|
||||
}
|
||||
$('#form-modal2 .btn-success').removeClass('btn-success').addClass('btn-none');
|
||||
}
|
||||
|
||||
if (typeof data['event_data']['res'] == 'string') {
|
||||
scope['traceback'] = data['event_data']['res'];
|
||||
}
|
||||
|
||||
for (var fld in form.fields) {
|
||||
switch(fld) {
|
||||
// load the form
|
||||
scope = generator.inject(form, {
|
||||
mode: 'edit',
|
||||
modal: true,
|
||||
related: false
|
||||
});
|
||||
generator.reset();
|
||||
scope.formModalAction = function () {
|
||||
$('#form-modal').modal("hide");
|
||||
};
|
||||
scope.formModalActionLabel = 'OK';
|
||||
scope.formModalCancelShow = false;
|
||||
scope.formModalInfo = 'View JSON';
|
||||
$('#form-modal .btn-success').removeClass('btn-success').addClass('btn-none');
|
||||
$('#form-modal').addClass('skinny-modal');
|
||||
scope.formModalHeader = data.event_display.replace(/^\u00a0*/g, '');
|
||||
|
||||
// Respond to View JSON button
|
||||
scope.formModalInfoAction = function () {
|
||||
var generator = GenerateForm,
|
||||
scope = generator.inject(JobEventDataForm, {
|
||||
mode: 'edit',
|
||||
modal: true,
|
||||
related: false,
|
||||
modal_selector: '#form-modal2',
|
||||
modal_body_id: 'form-modal2-body',
|
||||
modal_title_id: 'formModal2Header'
|
||||
});
|
||||
generator.reset();
|
||||
scope.formModal2Header = data.event_display.replace(/^\u00a0*/g, '');
|
||||
scope.event_data = JSON.stringify(data.event_data, null, '\t');
|
||||
scope.formModal2ActionLabel = 'OK';
|
||||
scope.formModal2CancelShow = false;
|
||||
scope.formModal2Info = false;
|
||||
scope.formModalInfo = 'View JSON';
|
||||
scope.formModal2Action = function () {
|
||||
$('#form-modal2').modal("hide");
|
||||
};
|
||||
$('#form-modal2 .btn-success').removeClass('btn-success').addClass('btn-none');
|
||||
};
|
||||
|
||||
if (typeof data.event_data.res === 'string') {
|
||||
scope.traceback = data.event_data.res;
|
||||
}
|
||||
|
||||
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,50 +186,50 @@ 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 (txt !== '') {
|
||||
scope[fld] = txt;
|
||||
}
|
||||
case 'results':
|
||||
if (Array.isArray(data.event_data.res[fld]) && data.event_data.res[fld].length > 0) {
|
||||
txt = '';
|
||||
for (i = 0; i < data.event_data.res[fld].length; i++) {
|
||||
txt += data.event_data.res[fld][i];
|
||||
}
|
||||
if (txt !== '') {
|
||||
scope[fld] = txt;
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 'msg':
|
||||
case 'stdout':
|
||||
case 'stderr':
|
||||
case 'delta':
|
||||
case 'rc':
|
||||
if (data['event_data'] && data['event_data']['res'] && data['event_data']['res'][fld] !== undefined) {
|
||||
scope[fld] = data['event_data']['res'][fld];
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scope.$$phase) {
|
||||
scope.$digest();
|
||||
}
|
||||
}
|
||||
|
||||
if (!scope.$$phase) {
|
||||
scope.$digest();
|
||||
}
|
||||
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
$('#form-modal').modal("hide");
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve event: ' + event_id + '. GET status: ' + status });
|
||||
.error(function (data, status) {
|
||||
$('#form-modal').modal("hide");
|
||||
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
|
||||
msg: 'Failed to retrieve event: ' + event_id + '. GET status: ' + status });
|
||||
});
|
||||
|
||||
}
|
||||
}]);
|
||||
};
|
||||
}
|
||||
]);
|
||||
File diff suppressed because it is too large
Load Diff
@ -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',
|
||||
|
||||
@ -2,479 +2,463 @@
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* JobSubmission.js
|
||||
*
|
||||
*
|
||||
*/
|
||||
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) {
|
||||
|
||||
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;
|
||||
'use strict';
|
||||
|
||||
function navigate(canceled) {
|
||||
//Decide where to send the user once the modal dialog closes
|
||||
if (!canceled) {
|
||||
if (base == 'jobs') {
|
||||
scope.refreshJob();
|
||||
}
|
||||
else {
|
||||
$location.path('/jobs');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$location.path('/' + base);
|
||||
}
|
||||
}
|
||||
angular.module('JobSubmissionHelper', ['RestServices', 'Utilities', 'CredentialFormDefinition', 'CredentialsListDefinition',
|
||||
'LookUpHelper', 'ProjectFormDefinition', 'JobSubmissionHelper'
|
||||
])
|
||||
|
||||
function cancel() {
|
||||
// Delete a job
|
||||
var url = GetBasePath('jobs') + scope.job_id +'/'
|
||||
Rest.setUrl(url);
|
||||
Rest.destroy()
|
||||
.success ( function(data, status, headers, config) {
|
||||
if (form.name == 'credential') {
|
||||
navigate(true);
|
||||
.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) {
|
||||
|
||||
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') {
|
||||
scope.refreshJob();
|
||||
} else {
|
||||
$location.path('/jobs');
|
||||
}
|
||||
} else {
|
||||
$location.path('/' + base);
|
||||
}
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
// Delete a job
|
||||
var url = GetBasePath('jobs') + scope.job_id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.destroy()
|
||||
.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() {
|
||||
// User clicked cancel button
|
||||
$('#password-modal').modal('hide');
|
||||
if (form.name == 'credential') {
|
||||
cancel();
|
||||
}
|
||||
else {
|
||||
scope.$emit('UpdateSubmitted','canceled');
|
||||
}
|
||||
}
|
||||
|
||||
scope.startJob = function() {
|
||||
$('#password-modal').modal('hide');
|
||||
Wait('start');
|
||||
var pswd = {};
|
||||
var value_supplied = false;
|
||||
$('.password-field').each(function(index) {
|
||||
pswd[$(this).attr('name')] = $(this).val();
|
||||
if ($(this).val() != '' && $(this).val() !== null) {
|
||||
value_supplied = true;
|
||||
scope.cancelJob = function () {
|
||||
// User clicked cancel button
|
||||
$('#password-modal').modal('hide');
|
||||
if (form.name === 'credential') {
|
||||
cancel();
|
||||
} else {
|
||||
scope.$emit('UpdateSubmitted', 'canceled');
|
||||
}
|
||||
});
|
||||
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') {
|
||||
navigate(false);
|
||||
}
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'POST to ' + start_url + ' failed with status: ' + status });
|
||||
});
|
||||
}
|
||||
else {
|
||||
Wait('stop');
|
||||
Alert('No Passwords', 'Required password(s) not provided. The request was not submitted.', 'alert-info');
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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++) {
|
||||
// Add the password field
|
||||
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 {
|
||||
current_form = form;
|
||||
}
|
||||
field = current_form.fields[passwords[i]];
|
||||
fld = passwords[i];
|
||||
scope[fld] = '';
|
||||
html += "<div class=\"form-group\">\n";
|
||||
html += "<label class=\"control-label col-lg-3 normal-weight\" for=\"" + fld + "\">* ";
|
||||
html += (field.labelBind) ? scope[field.labelBind] : field.label;
|
||||
html += "</label>\n";
|
||||
html += "<div class=\"col-lg-9\">\n";
|
||||
html += "<input type=\"password\" ";
|
||||
html += "ng-model=\"" + fld + '" ';
|
||||
html += 'name="' + fld + '" ';
|
||||
html += "class=\"password-field form-control\" ";
|
||||
html += "required ";
|
||||
html += "/>";
|
||||
html += "<br />\n";
|
||||
// Add error messages
|
||||
html += "<span class=\"error\" ng-show=\"password_form." + fld + ".$dirty && " +
|
||||
"password_form." + fld + ".$error.required\">A value is required!</span>\n";
|
||||
html += "<span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
|
||||
// Add the related confirm field
|
||||
fld = field.associated;
|
||||
field = current_form.fields[field.associated];
|
||||
scope[fld] = '';
|
||||
html += "<div class=\"form-group\">\n";
|
||||
html += "<label class=\"control-label col-lg-3 normal-weight\" for=\"" + fld + "\">* ";
|
||||
html += (field.labelBind) ? scope[field.labelBind] : field.label;
|
||||
html += "</label>\n";
|
||||
html += "<div class=\"col-lg-9\">\n";
|
||||
html += "<input type=\"password\" ";
|
||||
html += "ng-model=\"" + fld + '" ';
|
||||
html += 'name="' + fld + '" ';
|
||||
html += "class=\"form-control\" ";
|
||||
html += "required ";
|
||||
html += (field.awPassMatch) ? "awpassmatch=\"" + field.associated + "\" " : "";
|
||||
html += "/>";
|
||||
html += "<br />\n";
|
||||
// Add error messages
|
||||
html += "<span class=\"error\" ng-show=\"password_form." + fld + ".$dirty && " +
|
||||
"password_form." + fld + ".$error.required\">A value is required!</span>\n";
|
||||
if (field.awPassMatch) {
|
||||
html += "<span class=\"error\" ng-show=\"password_form." + fld +
|
||||
".$error.awpassmatch\">Must match Password value</span>\n";
|
||||
}
|
||||
html += "<span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
}
|
||||
html += "</form>\n";
|
||||
var 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-body').find('input[type="password"]:first').focus();
|
||||
});
|
||||
}
|
||||
else {
|
||||
scope.startJob();
|
||||
}
|
||||
}
|
||||
}])
|
||||
|
||||
.factory('SubmitJob',['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'CredentialList',
|
||||
'LookUpInit', 'CredentialForm', 'ProcessErrors', 'JobTemplateForm', 'Wait',
|
||||
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 + '/';
|
||||
};
|
||||
|
||||
function postJob(data) {
|
||||
// Create the job record
|
||||
if (scope.credentialWatchRemove) {
|
||||
scope.credentialWatchRemove();
|
||||
scope.startJob = function () {
|
||||
var pswd = {}, value_supplied = false;
|
||||
$('#password-modal').modal('hide');
|
||||
Wait('start');
|
||||
$('.password-field').each(function () {
|
||||
pswd[$(this).attr('name')] = $(this).val();
|
||||
if ($(this).val() !== '' && $(this).val() !== null) {
|
||||
value_supplied = true;
|
||||
}
|
||||
});
|
||||
if (Empty(passwords) || passwords.length === 0 || value_supplied) {
|
||||
Rest.setUrl(start_url);
|
||||
Rest.post(pswd)
|
||||
.success(function () {
|
||||
scope.$emit('UpdateSubmitted', 'started');
|
||||
if (form.name === 'credential') {
|
||||
navigate(false);
|
||||
}
|
||||
})
|
||||
.error(function (data, status) {
|
||||
Wait('stop');
|
||||
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'POST to ' + start_url + ' failed with status: ' + status });
|
||||
});
|
||||
} else {
|
||||
Wait('stop');
|
||||
Alert('No Passwords', 'Required password(s) not provided. The request was not submitted.', 'alert-info');
|
||||
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.
|
||||
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 : "";
|
||||
for (i = 0; i < passwords.length; i++) {
|
||||
// Add the password field
|
||||
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 {
|
||||
// No match found. Abandon ship!
|
||||
Alert('Form Not Found', 'Could not locate form for: ' + passwords[i], 'alert-danger');
|
||||
$location('/#/jobs');
|
||||
}
|
||||
} else {
|
||||
current_form = form;
|
||||
}
|
||||
field = current_form.fields[passwords[i]];
|
||||
fld = passwords[i];
|
||||
scope[fld] = '';
|
||||
html += "<div class=\"form-group\">\n";
|
||||
html += "<label class=\"control-label col-lg-3 normal-weight\" for=\"" + fld + "\">* ";
|
||||
html += (field.labelBind) ? scope[field.labelBind] : field.label;
|
||||
html += "</label>\n";
|
||||
html += "<div class=\"col-lg-9\">\n";
|
||||
html += "<input type=\"password\" ";
|
||||
html += "ng-model=\"" + fld + '" ';
|
||||
html += 'name="' + fld + '" ';
|
||||
html += "class=\"password-field form-control\" ";
|
||||
html += "required ";
|
||||
html += "/>";
|
||||
html += "<br />\n";
|
||||
// Add error messages
|
||||
html += "<span class=\"error\" ng-show=\"password_form." + fld + ".$dirty && " +
|
||||
"password_form." + fld + ".$error.required\">A value is required!</span>\n";
|
||||
html += "<span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
|
||||
// Add the related confirm field
|
||||
fld = field.associated;
|
||||
field = current_form.fields[field.associated];
|
||||
scope[fld] = '';
|
||||
html += "<div class=\"form-group\">\n";
|
||||
html += "<label class=\"control-label col-lg-3 normal-weight\" for=\"" + fld + "\">* ";
|
||||
html += (field.labelBind) ? scope[field.labelBind] : field.label;
|
||||
html += "</label>\n";
|
||||
html += "<div class=\"col-lg-9\">\n";
|
||||
html += "<input type=\"password\" ";
|
||||
html += "ng-model=\"" + fld + '" ';
|
||||
html += 'name="' + fld + '" ';
|
||||
html += "class=\"form-control\" ";
|
||||
html += "required ";
|
||||
html += (field.awPassMatch) ? "awpassmatch=\"" + field.associated + "\" " : "";
|
||||
html += "/>";
|
||||
html += "<br />\n";
|
||||
// Add error messages
|
||||
html += "<span class=\"error\" ng-show=\"password_form." + fld + ".$dirty && " +
|
||||
"password_form." + fld + ".$error.required\">A value is required!</span>\n";
|
||||
if (field.awPassMatch) {
|
||||
html += "<span class=\"error\" ng-show=\"password_form." + fld +
|
||||
".$error.awpassmatch\">Must match Password value</span>\n";
|
||||
}
|
||||
html += "<span class=\"error api-error\" ng-bind=\"" + fld + "_api_error\"></span>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
}
|
||||
html += "</form>\n";
|
||||
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-body').find('input[type="password"]:first').focus();
|
||||
});
|
||||
} else {
|
||||
scope.startJob();
|
||||
}
|
||||
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;
|
||||
Wait('start');
|
||||
Rest.setUrl(url);
|
||||
Rest.post({
|
||||
name: name + ' ' + dt, // job name required and unique
|
||||
description: data.description,
|
||||
job_template: data.id,
|
||||
inventory: data.inventory,
|
||||
project: data.project,
|
||||
playbook: data.playbook,
|
||||
credential: data.credential,
|
||||
forks: data.forks,
|
||||
limit: data.limit,
|
||||
verbosity: data.verbosity,
|
||||
extra_vars: data.extra_vars
|
||||
})
|
||||
.success( function(data, status, headers, config) {
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
.factory('SubmitJob', ['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'CredentialList',
|
||||
'LookUpInit', 'CredentialForm', 'ProcessErrors', 'JobTemplateForm', 'Wait',
|
||||
function (PromptPasswords, $compile, Rest, $location, GetBasePath, CredentialList, LookUpInit, CredentialForm,
|
||||
ProcessErrors, JobTemplateForm, Wait) {
|
||||
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();
|
||||
}
|
||||
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({
|
||||
name: name + ' ' + dt, // job name required and unique
|
||||
description: data.description,
|
||||
job_template: data.id,
|
||||
inventory: data.inventory,
|
||||
project: data.project,
|
||||
playbook: data.playbook,
|
||||
credential: data.credential,
|
||||
forks: data.forks,
|
||||
limit: data.limit,
|
||||
verbosity: data.verbosity,
|
||||
extra_vars: data.extra_vars
|
||||
}).success(function (data) {
|
||||
scope.job_id = data.id;
|
||||
if (data.passwords_needed_to_start.length > 0) {
|
||||
// Passwords needed. Prompt for passwords, then start job.
|
||||
PromptPasswords({
|
||||
scope: scope,
|
||||
passwords: data.passwords_needed_to_start,
|
||||
start_url: data.related.start,
|
||||
form: CredentialForm
|
||||
});
|
||||
// Passwords needed. Prompt for passwords, then start job.
|
||||
PromptPasswords({
|
||||
scope: scope,
|
||||
passwords: data.passwords_needed_to_start,
|
||||
start_url: data.related.start,
|
||||
form: CredentialForm
|
||||
});
|
||||
} else {
|
||||
// No passwords needed, start the job!
|
||||
Rest.setUrl(data.related.start);
|
||||
Rest.post()
|
||||
.success(function () {
|
||||
Wait('stop');
|
||||
var base = $location.path().replace(/^\//, '').split('/')[0];
|
||||
if (base === 'jobs') {
|
||||
scope.refresh();
|
||||
} else {
|
||||
$location.path('/jobs');
|
||||
}
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'Failed to start job. POST returned status: ' + status });
|
||||
});
|
||||
}
|
||||
else {
|
||||
// No passwords needed, start the job!
|
||||
Rest.setUrl(data.related.start);
|
||||
Rest.post()
|
||||
.success( function(data, status, headers, config) {
|
||||
Wait('stop');
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
if (base == 'jobs') {
|
||||
scope.refresh();
|
||||
}
|
||||
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, headers, config) {
|
||||
}).error(function (data, status) {
|
||||
Wait('stop');
|
||||
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) {
|
||||
// Create a job record
|
||||
scope.credential = '';
|
||||
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) {
|
||||
if (newVal !== oldVal) {
|
||||
// After user selects a credential from the modal,
|
||||
// submit the job
|
||||
if (scope.credential != '' && scope.credential !== null && scope.credential !== undefined) {
|
||||
data.credential = scope.credential;
|
||||
postJob(data);
|
||||
}
|
||||
}
|
||||
});
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: JobTemplateForm,
|
||||
current_item: null,
|
||||
list: CredentialList,
|
||||
field: 'credential',
|
||||
hdr: 'Credential Required'
|
||||
});
|
||||
scope.lookUpCredential();
|
||||
}
|
||||
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 });
|
||||
});
|
||||
};
|
||||
}])
|
||||
|
||||
// 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/';
|
||||
|
||||
if (scope.removeUpdateSubmitted) {
|
||||
scope.removeUpdateSubmitted();
|
||||
}
|
||||
scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function(e, action) {
|
||||
// Refresh the project list after update request submitted
|
||||
Wait('stop');
|
||||
Alert('Update Started', 'The request to start the SCM update process was submitted. ' +
|
||||
'To monitor the update status, refresh the page by clicking the <em>Refresh</em> button.', 'alert-info');
|
||||
scope.refresh();
|
||||
});
|
||||
|
||||
if (scope.removeSCMSubmit) {
|
||||
scope.removeSCMSubmit();
|
||||
}
|
||||
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,
|
||||
passwords: passwords_needed_to_update,
|
||||
start_url: url,
|
||||
form: ProjectsForm,
|
||||
extra_html: extra_html
|
||||
});
|
||||
});
|
||||
|
||||
// Check to see if we have permission to perform the update and if any passwords are needed
|
||||
Wait('start');
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
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) {
|
||||
// Create a job record
|
||||
scope.credential = '';
|
||||
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) {
|
||||
if (newVal !== oldVal) {
|
||||
// After user selects a credential from the modal,
|
||||
// submit the job
|
||||
if (scope.credential !== '' && scope.credential !== null && scope.credential !== undefined) {
|
||||
data.credential = scope.credential;
|
||||
postJob(data);
|
||||
}
|
||||
}
|
||||
});
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: JobTemplateForm,
|
||||
current_item: null,
|
||||
list: CredentialList,
|
||||
field: 'credential',
|
||||
hdr: 'Credential Required'
|
||||
});
|
||||
scope.lookUpCredential();
|
||||
} else {
|
||||
// We have what we need, submit the job
|
||||
postJob(data);
|
||||
}
|
||||
})
|
||||
.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',
|
||||
'ProjectsForm', 'Wait',
|
||||
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 () {
|
||||
// Refresh the project list after update request submitted
|
||||
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 += "<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";
|
||||
extra_html += "<input type=\"text\" readonly";
|
||||
extra_html += ' name=\"scm_url\" ';
|
||||
extra_html += "class=\"form-control\" ";
|
||||
extra_html += "value=\"" + scope.projects[i].scm_url + "\" ";
|
||||
extra_html += "/>";
|
||||
extra_html += "</div>\n";
|
||||
extra_html += "</div>\n";
|
||||
if (scope.projects[i].scm_username) {
|
||||
extra_html += "<div class=\"form-group\">\n";
|
||||
extra_html += "<label class=\"control-label col-lg-3 normal-weight\" for=\"scm_username\">SCM Username</label>\n";
|
||||
extra_html += "<div class=\"col-lg-9\">\n";
|
||||
extra_html += "<input type=\"text\" readonly";
|
||||
extra_html += ' name=\"scm_username\" ';
|
||||
extra_html += "class=\"form-control\" ";
|
||||
extra_html += "value=\"" + scope.projects[i].scm_username + "\" ";
|
||||
extra_html += "/>";
|
||||
extra_html += "</div>\n";
|
||||
extra_html += "</div>\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
extra_html += "</p>";
|
||||
scope.$emit('SCMSubmit', data.passwords_needed_to_update, extra_html);
|
||||
}
|
||||
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 });
|
||||
Alert('Update Started', 'The request to start the SCM update process was submitted. ' +
|
||||
'To monitor the update status, refresh the page by clicking the <em>Refresh</em> button.', 'alert-info');
|
||||
scope.refresh();
|
||||
});
|
||||
};
|
||||
}])
|
||||
|
||||
if (scope.removeSCMSubmit) {
|
||||
scope.removeSCMSubmit();
|
||||
}
|
||||
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,
|
||||
passwords: passwords_needed_to_update,
|
||||
start_url: url,
|
||||
form: ProjectsForm,
|
||||
extra_html: extra_html
|
||||
});
|
||||
});
|
||||
|
||||
// Check to see if we have permission to perform the update and if any passwords are needed
|
||||
Wait('start');
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
var i, extra_html;
|
||||
Wait('stop');
|
||||
if (data.can_update) {
|
||||
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";
|
||||
extra_html += "<input type=\"text\" readonly";
|
||||
extra_html += ' name=\"scm_url\" ';
|
||||
extra_html += "class=\"form-control\" ";
|
||||
extra_html += "value=\"" + scope.projects[i].scm_url + "\" ";
|
||||
extra_html += "/>";
|
||||
extra_html += "</div>\n";
|
||||
extra_html += "</div>\n";
|
||||
if (scope.projects[i].scm_username) {
|
||||
extra_html += "<div class=\"form-group\">\n";
|
||||
extra_html += "<label class=\"control-label col-lg-3 normal-weight\" for=\"scm_username\">SCM Username</label>\n";
|
||||
extra_html += "<div class=\"col-lg-9\">\n";
|
||||
extra_html += "<input type=\"text\" readonly";
|
||||
extra_html += ' name=\"scm_username\" ';
|
||||
extra_html += "class=\"form-control\" ";
|
||||
extra_html += "value=\"" + scope.projects[i].scm_username + "\" ";
|
||||
extra_html += "/>";
|
||||
extra_html += "</div>\n";
|
||||
extra_html += "</div>\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
extra_html += "</p>";
|
||||
scope.$emit('SCMSubmit', data.passwords_needed_to_update, extra_html);
|
||||
} else {
|
||||
Alert('Permission Denied', 'You do not have access to update this project. Please contact your system administrator.',
|
||||
'alert-danger');
|
||||
}
|
||||
})
|
||||
.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',
|
||||
'GroupForm', 'BuildTree', 'Wait',
|
||||
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;
|
||||
// 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) {
|
||||
|
||||
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) {
|
||||
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');
|
||||
if (scope.removeHostReloadComplete) {
|
||||
scope.removeHostReloadComplete();
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.removeUpdateSubmitted) {
|
||||
scope.removeUpdateSubmitted();
|
||||
}
|
||||
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) {
|
||||
scope.refresh();
|
||||
}
|
||||
scope.$emit('HostReloadComplete');
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.removeInventorySubmit) {
|
||||
scope.removeInventorySubmit();
|
||||
}
|
||||
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,
|
||||
passwords: passwords_needed_to_update,
|
||||
start_url: url,
|
||||
form: GroupForm,
|
||||
extra_html: extra_html
|
||||
});
|
||||
});
|
||||
|
||||
// Check to see if we have permission to perform the update and if any passwords are needed
|
||||
Wait('start');
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
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 {
|
||||
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) {
|
||||
scope.removeHostReloadComplete = scope.$on('HostReloadComplete', function () {
|
||||
Wait('stop');
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Failed to get inventory_source details. ' + url + 'GET status: ' + status });
|
||||
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');
|
||||
if (scope.removeHostReloadComplete) {
|
||||
scope.removeHostReloadComplete();
|
||||
}
|
||||
});
|
||||
};
|
||||
}]);
|
||||
|
||||
if (scope.removeUpdateSubmitted) {
|
||||
scope.removeUpdateSubmitted();
|
||||
}
|
||||
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) {
|
||||
scope.refresh();
|
||||
}
|
||||
scope.$emit('HostReloadComplete');
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.removeInventorySubmit) {
|
||||
scope.removeInventorySubmit();
|
||||
}
|
||||
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,
|
||||
passwords: passwords_needed_to_update,
|
||||
start_url: url,
|
||||
form: GroupForm,
|
||||
extra_html: extra_html
|
||||
});
|
||||
});
|
||||
|
||||
// Check to see if we have permission to perform the update and if any passwords are needed
|
||||
Wait('start');
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.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 {
|
||||
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) {
|
||||
Wait('stop');
|
||||
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'Failed to get inventory_source details. ' + url + 'GET status: ' + status });
|
||||
});
|
||||
};
|
||||
}
|
||||
]);
|
||||
@ -4,15 +4,18 @@
|
||||
* JobsHelper
|
||||
*
|
||||
* Routines shared by job related controllers
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinition', 'InventoryHelper'])
|
||||
|
||||
.factory('JobStatusToolTip', [ function() {
|
||||
return function(status) {
|
||||
var toolTip;
|
||||
switch (status) {
|
||||
.factory('JobStatusToolTip', [
|
||||
function () {
|
||||
return function (status) {
|
||||
var toolTip;
|
||||
switch (status) {
|
||||
case 'successful':
|
||||
case 'success':
|
||||
toolTip = 'There were no failed tasks.';
|
||||
@ -35,118 +38,124 @@ angular.module('JobsHelper', ['Utilities', 'FormGenerator', 'JobSummaryDefinitio
|
||||
case 'running':
|
||||
toolTip = 'Playbook tasks executing.';
|
||||
break;
|
||||
}
|
||||
return toolTip;
|
||||
}
|
||||
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) {
|
||||
// Display status info in a modal dialog- called from inventory edit page
|
||||
|
||||
var job_id = params.job_id;
|
||||
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 generator = GenerateForm;
|
||||
var form = JobSummary;
|
||||
|
||||
// Using jquery dialog for its expandable property
|
||||
|
||||
var html = '<div id=\"status-modal-dialog\" title=\"Job ' + job_id + '\">' +
|
||||
'<div id=\"form-container\" style=\"width: 100%;\"></div></div>\n';
|
||||
|
||||
$('#inventory-modal-container').empty().append(html);
|
||||
var 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;
|
||||
if (ww > 1199) {
|
||||
// desktop
|
||||
x = 675;
|
||||
y = (750 > wh) ? wh - 20 : 750;
|
||||
maxrows = 20;
|
||||
}
|
||||
else if (ww <= 1199 && ww >= 768) {
|
||||
x = 550;
|
||||
y = (620 > wh) ? wh - 15 : 620;
|
||||
maxrows = 15;
|
||||
}
|
||||
else {
|
||||
x = (ww - 20);
|
||||
y = (500 > wh) ? wh : 500;
|
||||
maxrows = 10;
|
||||
}
|
||||
|
||||
// Create the modal
|
||||
$('#status-modal-dialog').dialog({
|
||||
buttons: { 'OK': function() { $( this ).dialog( 'close' ); } },
|
||||
modal: true,
|
||||
width: x,
|
||||
height: y,
|
||||
autoOpen: false,
|
||||
create: function () {
|
||||
// fix the close button
|
||||
$('.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' });
|
||||
},
|
||||
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 );
|
||||
},
|
||||
close: function() {
|
||||
// Destroy on close
|
||||
$('.tooltip').each( function() {
|
||||
// Remove any lingering tooltip <div> elements
|
||||
$(this).remove();
|
||||
});
|
||||
$('.popover').each(function() {
|
||||
// remove lingering popover <div> elements
|
||||
$(this).remove();
|
||||
});
|
||||
$('#status-modal-dialog').dialog('destroy');
|
||||
$('#inventory-modal-container').empty();
|
||||
WatchInventoryWindowResize();
|
||||
},
|
||||
open: function() {
|
||||
Wait('stop');
|
||||
}
|
||||
});
|
||||
|
||||
function calcRows (content) {
|
||||
var n = content.match(/\n/g);
|
||||
var rows = (n) ? n.length : 1;
|
||||
return (rows > maxrows) ? 20 : rows;
|
||||
var job_id = params.job_id,
|
||||
generator = GenerateForm,
|
||||
form = JobSummary,
|
||||
scope, ww, wh, x, y, maxrows, url, html;
|
||||
|
||||
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);
|
||||
|
||||
scope = generator.inject(form, { mode: 'edit', id: 'form-container', breadCrumbs: false, related: false });
|
||||
|
||||
// Set modal dimensions based on viewport width
|
||||
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) {
|
||||
x = 550;
|
||||
y = (620 > wh) ? wh - 15 : 620;
|
||||
maxrows = 15;
|
||||
} else {
|
||||
x = (ww - 20);
|
||||
y = (500 > wh) ? wh : 500;
|
||||
maxrows = 10;
|
||||
}
|
||||
|
||||
Wait('start');
|
||||
var url = GetBasePath('jobs') + job_id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success( function(data) {
|
||||
scope.id = data.id;
|
||||
scope.name = data.name;
|
||||
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);
|
||||
var cDate = new Date(data.created);
|
||||
scope.created = FormatDate(cDate);
|
||||
$('#status-modal-dialog').dialog('open');
|
||||
// Create the modal
|
||||
$('#status-modal-dialog').dialog({
|
||||
buttons: {
|
||||
'OK': function () {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
},
|
||||
modal: true,
|
||||
width: x,
|
||||
height: y,
|
||||
autoOpen: false,
|
||||
create: function () {
|
||||
// fix the close button
|
||||
$('.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'
|
||||
});
|
||||
},
|
||||
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"]'),
|
||||
content = dialog.find('#status-modal-dialog');
|
||||
content.width(dialog.width() - 28);
|
||||
},
|
||||
close: function () {
|
||||
// Destroy on close
|
||||
$('.tooltip').each(function () {
|
||||
// Remove any lingering tooltip <div> elements
|
||||
$(this).remove();
|
||||
});
|
||||
$('.popover').each(function () {
|
||||
// remove lingering popover <div> elements
|
||||
$(this).remove();
|
||||
});
|
||||
$('#status-modal-dialog').dialog('destroy');
|
||||
$('#inventory-modal-container').empty();
|
||||
WatchInventoryWindowResize();
|
||||
},
|
||||
open: function () {
|
||||
Wait('stop');
|
||||
}
|
||||
});
|
||||
|
||||
function calcRows(content) {
|
||||
var n = content.match(/\n/g),
|
||||
rows = (n) ? n.length : 1;
|
||||
return (rows > maxrows) ? 20 : rows;
|
||||
}
|
||||
|
||||
Wait('start');
|
||||
url = GetBasePath('jobs') + job_id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
var cDate;
|
||||
scope.id = data.id;
|
||||
scope.name = data.name;
|
||||
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);
|
||||
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 });
|
||||
});
|
||||
};
|
||||
|
||||
}]);
|
||||
|
||||
}
|
||||
]);
|
||||
@ -21,13 +21,13 @@ 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) {
|
||||
// pass in a url value to override the default
|
||||
defaultUrl = params.url;
|
||||
@ -46,7 +46,7 @@ angular.module('LookUpHelper', ['RestServices', 'Utilities', 'SearchHelper', 'Pa
|
||||
$('input[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').attr('data-source', field);
|
||||
|
||||
scope['lookUp' + name] = function () {
|
||||
|
||||
|
||||
var master = {}, listGenerator, listScope;
|
||||
|
||||
// Generating the search list potentially kills the values held in scope for the field.
|
||||
@ -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 < scope[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,15 @@ 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] !== '' &&
|
||||
@ -165,4 +169,4 @@ angular.module('LookUpHelper', ['RestServices', 'Utilities', 'SearchHelper', 'Pa
|
||||
};
|
||||
};
|
||||
}
|
||||
]);
|
||||
]);
|
||||
|
||||
@ -5,165 +5,155 @@
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('PaginationHelpers', ['Utilities', 'RefreshHelper', 'RefreshRelatedHelper'])
|
||||
'use strict';
|
||||
|
||||
.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;
|
||||
angular.module('PaginationHelpers', ['Utilities', 'RefreshHelper', 'RefreshRelatedHelper'])
|
||||
|
||||
scope[iterator + '_page'] = 1;
|
||||
scope[iterator + '_num_pages'] = Math.ceil((count / scope[iterator + '_page_size']));
|
||||
scope[iterator + '_num_pages'] = (scope[iterator + '_num_pages'] <= 0) ? 1 : scope[iterator + '_num_pages'];
|
||||
scope[iterator + '_total_rows'] = count;
|
||||
.factory('PageRangeSetup', ['Empty',
|
||||
function (Empty) {
|
||||
return function (params) {
|
||||
|
||||
var scope = params.scope,
|
||||
count = params.count,
|
||||
next = params.next,
|
||||
previous = params.previous,
|
||||
iterator = params.iterator,
|
||||
i, first, last;
|
||||
|
||||
// Which page are we on?
|
||||
if ( Empty(next) && previous ) {
|
||||
// no next page, but there is a previous page
|
||||
scope[iterator + '_page'] = parseInt(previous.match(/page=\d+/)[0].replace(/page=/,'')) + 1;
|
||||
}
|
||||
else if ( next && Empty(previous) ) {
|
||||
// next page available, but no previous page
|
||||
scope[iterator + '_page'] = 1;
|
||||
}
|
||||
else if ( next && previous ) {
|
||||
// we're in between next and previous
|
||||
scope[iterator + '_page'] = parseInt(previous.match(/page=\d+/)[0].replace(/page=/,'')) + 1;
|
||||
}
|
||||
scope[iterator + '_num_pages'] = Math.ceil((count / scope[iterator + '_page_size']));
|
||||
scope[iterator + '_num_pages'] = (scope[iterator + '_num_pages'] <= 0) ? 1 : scope[iterator + '_num_pages'];
|
||||
scope[iterator + '_total_rows'] = count;
|
||||
|
||||
// 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;
|
||||
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']) ?
|
||||
scope[iterator + '_page'] + 4 : scope[iterator + '_num_pages'];
|
||||
}
|
||||
for (var i=first; i <= last; i++) {
|
||||
scope[iterator + '_page_range'].push(i);
|
||||
}
|
||||
|
||||
}
|
||||
}])
|
||||
|
||||
.factory('RelatedPaginateInit', [ 'RefreshRelated', '$cookieStore', 'Wait',
|
||||
function(RefreshRelated, $cookieStore, Wait) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var relatedSets = params.relatedSets;
|
||||
var pageSize = (params.pageSize) ? params.pageSize : 10;
|
||||
|
||||
for (var key in relatedSets){
|
||||
cookieSize = $cookieStore.get(relatedSets[key].iterator + '_page_size');
|
||||
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_size'] = pageSize;
|
||||
}
|
||||
}
|
||||
|
||||
scope.getPage = function(page, set, iterator) {
|
||||
var new_url = scope[iterator + '_url'].replace(/.page\=\d+/,'');
|
||||
var connect = (/\/$/.test(new_url)) ? '?' : '&';
|
||||
new_url += connect + 'page=' + page;
|
||||
new_url += (scope[iterator + 'SearchParams']) ? '&' + scope[iterator + 'SearchParams'] +
|
||||
'&page_size=' + scope[iterator + '_page_size' ] : 'page_size=' + scope[iterator + 'PageSize' ];
|
||||
Wait('start');
|
||||
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: new_url });
|
||||
// Which page are we on?
|
||||
if (Empty(next) && previous) {
|
||||
// no next page, but there is a previous page
|
||||
scope[iterator + '_page'] = parseInt(previous.match(/page=\d+/)[0].replace(/page=/, '')) + 1;
|
||||
} else if (next && Empty(previous)) {
|
||||
// next page available, but no previous page
|
||||
scope[iterator + '_page'] = 1;
|
||||
} else if (next && previous) {
|
||||
// we're in between next and previous
|
||||
scope[iterator + '_page'] = parseInt(previous.match(/page=\d+/)[0].replace(/page=/, '')) + 1;
|
||||
}
|
||||
|
||||
scope.pageIsActive = function(page, iterator) {
|
||||
return (page == scope[iterator + '_page']) ? 'active' : '';
|
||||
// Calc the range of up to 10 pages to show
|
||||
scope[iterator + '_page_range'] = [];
|
||||
first = (scope[iterator + '_page'] > 5) ? scope[iterator + '_page'] - 5 : 1;
|
||||
if (scope[iterator + '_page'] < 6) {
|
||||
last = (10 <= scope[iterator + '_num_pages']) ? 10 : scope[iterator + '_num_pages'];
|
||||
} else {
|
||||
last = (scope[iterator + '_page'] + 4 < scope[iterator + '_num_pages']) ?
|
||||
scope[iterator + '_page'] + 4 : scope[iterator + '_num_pages'];
|
||||
}
|
||||
for (i = first; i <= last; i++) {
|
||||
scope[iterator + '_page_range'].push(i);
|
||||
}
|
||||
|
||||
scope.changePageSize = function(set, iterator) {
|
||||
// Called when a new page size is selected
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
.factory('RelatedPaginateInit', ['RefreshRelated', '$cookieStore', 'Wait',
|
||||
function (RefreshRelated, $cookieStore, Wait) {
|
||||
return function (params) {
|
||||
|
||||
var scope = params.scope,
|
||||
relatedSets = params.relatedSets,
|
||||
pageSize = (params.pageSize) ? params.pageSize : 10,
|
||||
key;
|
||||
|
||||
for (key in relatedSets) {
|
||||
scope[relatedSets[key].iterator + '_url'] = relatedSets[key].url;
|
||||
scope[relatedSets[key].iterator + '_page'] = 0;
|
||||
scope[relatedSets[key].iterator + '_page_size'] = pageSize;
|
||||
}
|
||||
|
||||
scope.getPage = function (page, set, iterator) {
|
||||
var new_url = scope[iterator + '_url'].replace(/.page\=\d+/, ''),
|
||||
connect = (/\/$/.test(new_url)) ? '?' : '&';
|
||||
new_url += connect + 'page=' + page;
|
||||
new_url += (scope[iterator + 'SearchParams']) ? '&' + scope[iterator + 'SearchParams'] +
|
||||
'&page_size=' + scope[iterator + '_page_size'] : 'page_size=' + scope[iterator + 'PageSize'];
|
||||
Wait('start');
|
||||
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: new_url });
|
||||
};
|
||||
|
||||
scope.pageIsActive = function (page, iterator) {
|
||||
return (page === scope[iterator + '_page']) ? 'active' : '';
|
||||
};
|
||||
|
||||
scope.changePageSize = function (set, iterator) {
|
||||
// Called when a new page size is selected
|
||||
|
||||
scope[iterator + '_page'] = 1;
|
||||
var url = scope[iterator + '_url'];
|
||||
|
||||
// Using the session cookie, keep track of user rows per page selection
|
||||
$cookieStore.put(iterator + '_page_size', scope[iterator + '_page_size']);
|
||||
|
||||
url = url.replace(/\/\?.*$/, '/');
|
||||
url += (scope[iterator + 'SearchParams']) ? '?' + scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + '_page_size'] :
|
||||
'?page_size=' + scope[iterator + '_page_size'];
|
||||
|
||||
RefreshRelated({
|
||||
scope: scope,
|
||||
set: set,
|
||||
iterator: iterator,
|
||||
url: url
|
||||
});
|
||||
};
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
.factory('PaginateInit', ['Refresh', '$cookieStore', 'Wait',
|
||||
function (Refresh, $cookieStore, Wait) {
|
||||
return function (params) {
|
||||
|
||||
var scope = params.scope,
|
||||
list = params.list,
|
||||
iterator = (params.iterator) ? params.iterator : list.iterator,
|
||||
mode = (params.mode) ? params.mode : null;
|
||||
|
||||
scope[iterator + '_page'] = (params.page) ? params.page : 1;
|
||||
scope[iterator + '_url'] = params.url;
|
||||
scope[iterator + '_mode'] = mode;
|
||||
|
||||
if (params.pageSize) {
|
||||
scope[iterator + '_page_size'] = params.pageSize;
|
||||
} else if (mode === 'lookup') {
|
||||
scope[iterator + '_page_size'] = 5;
|
||||
} else {
|
||||
scope[iterator + '_page_size'] = 20;
|
||||
}
|
||||
|
||||
scope[iterator + '_page'] = 1;
|
||||
var url = scope[iterator + '_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'];
|
||||
Wait('start');
|
||||
Refresh({ scope: scope, set: set, iterator: iterator, url: new_url });
|
||||
};
|
||||
|
||||
// Using the session cookie, keep track of user rows per page selection
|
||||
$cookieStore.put(iterator + '_page_size', scope[iterator + '_page_size']);
|
||||
|
||||
url = url.replace(/\/\?.*$/,'/');
|
||||
url += (scope[iterator + 'SearchParams']) ? '?' + scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + '_page_size' ] :
|
||||
'?page_size=' + scope[iterator + '_page_size' ];
|
||||
|
||||
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: url });
|
||||
}
|
||||
scope.pageIsActive = function (page, iterator) {
|
||||
return (page === scope[iterator + '_page']) ? 'active' : '';
|
||||
};
|
||||
|
||||
}
|
||||
}])
|
||||
|
||||
|
||||
.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');
|
||||
|
||||
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') {
|
||||
scope[iterator + '_page_size'] = 5;
|
||||
}
|
||||
else {
|
||||
scope[iterator + '_page_size'] = 20;
|
||||
}
|
||||
}
|
||||
|
||||
scope.getPage = function(page, set, iterator) {
|
||||
var new_url = scope[iterator + '_url'].replace(/.page\=\d+/,'');
|
||||
var connect = (/\/$/.test(new_url)) ? '?' : '&';
|
||||
new_url += connect + 'page=' + page;
|
||||
new_url += (scope[iterator + 'SearchParams']) ? '&' + scope[iterator + 'SearchParams'] +
|
||||
'&page_size=' + scope[iterator + '_page_size' ] : 'page_size=' + scope[iterator + 'PageSize' ];
|
||||
Wait('start');
|
||||
Refresh({ scope: scope, set: set, iterator: iterator, url: new_url });
|
||||
}
|
||||
|
||||
scope.pageIsActive = function(page, iterator) {
|
||||
return (page == scope[iterator + '_page']) ? 'active' : '';
|
||||
}
|
||||
|
||||
scope.changePageSize = function(set, iterator) {
|
||||
// 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' ];
|
||||
Wait('start');
|
||||
Refresh({ scope: scope, set: set, iterator: iterator, url: new_url });
|
||||
}
|
||||
|
||||
}
|
||||
}]);
|
||||
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
|
||||
scope[iterator + '_page'] = 0;
|
||||
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 });
|
||||
};
|
||||
};
|
||||
}
|
||||
]);
|
||||
|
||||
@ -3,61 +3,61 @@
|
||||
*
|
||||
* ParseHelper
|
||||
*
|
||||
* Routines for parsing variable data and toggling
|
||||
* Routines for parsing variable data and toggling
|
||||
* between JSON and YAML.
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('ParseHelper', [])
|
||||
.factory('ParseTypeChange', [function() {
|
||||
return function(scope, varName, parseTypeName) {
|
||||
'use strict';
|
||||
|
||||
// Toggle displayed variable string between JSON and YAML
|
||||
angular.module('ParseHelper', [])
|
||||
.factory('ParseTypeChange', [
|
||||
function () {
|
||||
return function (scope, varName, parseTypeName) {
|
||||
|
||||
var fld = (varName) ? varName : 'variables';
|
||||
var pfld = (parseTypeName) ? parseTypeName : 'parseType';
|
||||
|
||||
scope.blockParseTypeWatch = false;
|
||||
scope.blockVariableDataWatch = false;
|
||||
// Toggle displayed variable string between JSON and YAML
|
||||
|
||||
if (scope['remove' + fld + 'Watch']) {
|
||||
scope['remove' + fld + 'Watch']();
|
||||
var fld = (varName) ? varName : 'variables',
|
||||
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) {
|
||||
var json_obj;
|
||||
if (newVal !== oldVal) {
|
||||
if (newVal === 'json') {
|
||||
if (scope[fld] && !/^---$/.test(scope[fld])) {
|
||||
// convert YAML to JSON
|
||||
try {
|
||||
json_obj = jsyaml.load(scope[fld]); //parse yaml into an obj
|
||||
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.
|
||||
}
|
||||
} else {
|
||||
scope[fld] = "{}";
|
||||
}
|
||||
} else {
|
||||
if (scope[fld] && !/^\{\}$/.test(scope[fld])) {
|
||||
// convert JSON to YAML
|
||||
try {
|
||||
json_obj = JSON.parse(scope[fld]);
|
||||
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.
|
||||
}
|
||||
} else {
|
||||
scope[fld] = "---";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
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
|
||||
try {
|
||||
var json_obj = jsyaml.load(scope[fld]); //parse yaml into an obj
|
||||
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.
|
||||
}
|
||||
}
|
||||
else {
|
||||
scope[fld] = "\{\}";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( scope[fld] && !/^\{\}$/.test(scope[fld]) ) {
|
||||
// convert JSON to YAML
|
||||
try {
|
||||
var json_obj = JSON.parse(scope[fld]);
|
||||
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.
|
||||
}
|
||||
}
|
||||
else {
|
||||
scope[fld] = "---";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}]);
|
||||
]);
|
||||
@ -6,43 +6,42 @@
|
||||
* Functions shared amongst Permission related controllers
|
||||
*
|
||||
*/
|
||||
angular.module('PermissionsHelper', [])
|
||||
|
||||
// Handle category change event
|
||||
.factory('PermissionCategoryChange', [ function() {
|
||||
return function(params) {
|
||||
var scope = params.scope;
|
||||
var reset = params.reset;
|
||||
angular.module('PermissionsHelper', [])
|
||||
|
||||
if (scope.category == 'Inventory') {
|
||||
scope.projectrequired = false;
|
||||
scope.permissionTypeHelp =
|
||||
"<dl>\n" +
|
||||
"<dt>Read</dt>\n" +
|
||||
"<dd>Only allow the user or team to view the inventory.</dd>\n" +
|
||||
"<dt>Write</dt>\n" +
|
||||
"<dd>Allow the user or team to modify hosts and groups contained in the inventory, add new hosts and groups, and perform inventory sync operations.\n" +
|
||||
"<dt>Admin</dt>\n" +
|
||||
"<dd>Allow the user or team full access to the inventory. This includes reading, writing, deletion of the inventory and inventory sync operations.</dd>\n" +
|
||||
"</dl>\n";
|
||||
}
|
||||
else {
|
||||
scope.projectrequired = true;
|
||||
scope.permissionTypeHelp =
|
||||
"<dl>\n" +
|
||||
"<dt>Run</dt>\n" +
|
||||
"<dd>Allow the user or team to perform a live deployment of the project against the inventory. In Run mode modules will " +
|
||||
"be executed, and changes to the inventory will occur.</dd>\n" +
|
||||
"<dt>Check</dt>\n" +
|
||||
"<dd>Only allow the user or team to deploy the project against the inventory as a dry-run operation. In Check mode, module operations " +
|
||||
"will only be simulated. No changes will occur.</dd>\n" +
|
||||
"</dl>\n";
|
||||
}
|
||||
// Handle category change event
|
||||
.factory('PermissionCategoryChange', [
|
||||
function () {
|
||||
return function (params) {
|
||||
var scope = params.scope,
|
||||
reset = params.reset;
|
||||
|
||||
if (reset) {
|
||||
scope.permission_type = (scope.category == 'Inventory') ? 'read' : 'run'; //default to the first option
|
||||
}
|
||||
|
||||
}
|
||||
}]);
|
||||
|
||||
if (scope.category === 'Inventory') {
|
||||
scope.projectrequired = false;
|
||||
scope.permissionTypeHelp =
|
||||
"<dl>\n" +
|
||||
"<dt>Read</dt>\n" +
|
||||
"<dd>Only allow the user or team to view the inventory.</dd>\n" +
|
||||
"<dt>Write</dt>\n" +
|
||||
"<dd>Allow the user or team to modify hosts and groups contained in the inventory, add new hosts and groups, and perform inventory sync operations.\n" +
|
||||
"<dt>Admin</dt>\n" +
|
||||
"<dd>Allow the user or team full access to the inventory. This includes reading, writing, deletion of the inventory and inventory sync operations.</dd>\n" +
|
||||
"</dl>\n";
|
||||
} else {
|
||||
scope.projectrequired = true;
|
||||
scope.permissionTypeHelp =
|
||||
"<dl>\n" +
|
||||
"<dt>Run</dt>\n" +
|
||||
"<dd>Allow the user or team to perform a live deployment of the project against the inventory. In Run mode modules will " +
|
||||
"be executed, and changes to the inventory will occur.</dd>\n" +
|
||||
"<dt>Check</dt>\n" +
|
||||
"<dd>Only allow the user or team to deploy the project against the inventory as a dry-run operation. In Check mode, module operations " +
|
||||
"will only be simulated. No changes will occur.</dd>\n" +
|
||||
"</dl>\n";
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
scope.permission_type = (scope.category === 'Inventory') ? 'read' : 'run'; //default to the first option
|
||||
}
|
||||
};
|
||||
}
|
||||
]);
|
||||
@ -3,73 +3,79 @@
|
||||
*
|
||||
* ProjectPathHelper
|
||||
*
|
||||
* Use GetProjectPath({ scope: <scope>, master: <master obj> }) to
|
||||
* Use GetProjectPath({ scope: <scope>, master: <master obj> }) to
|
||||
* load scope.project_local_paths (array of options for drop-down) and
|
||||
* scope.base_dir (readonly field).
|
||||
* scope.base_dir (readonly field).
|
||||
*
|
||||
*/
|
||||
angular.module('ProjectPathHelper', ['RestServices', 'Utilities'])
|
||||
.factory('GetProjectPath', ['Alert', 'Rest', 'GetBasePath', 'ProcessErrors',
|
||||
function (Alert, Rest, GetBasePath, ProcessErrors) {
|
||||
return function (params) {
|
||||
|
||||
angular.module('ProjectPathHelper', ['RestServices', 'Utilities'])
|
||||
.factory('GetProjectPath', ['Alert', 'Rest', 'GetBasePath','ProcessErrors',
|
||||
function(Alert, Rest, GetBasePath, ProcessErrors) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var master = params.master;
|
||||
|
||||
function arraySort(data) {
|
||||
//Sort nodes by name
|
||||
var names = [];
|
||||
var newData = [];
|
||||
for (var 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]) {
|
||||
newData.push(data[i]);
|
||||
var scope = params.scope,
|
||||
master = params.master;
|
||||
|
||||
function arraySort(data) {
|
||||
//Sort nodes by name
|
||||
var i, j, names = [],
|
||||
newData = [];
|
||||
for (i = 0; i < data.length; i++) {
|
||||
names.push(data[i].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return newData;
|
||||
}
|
||||
|
||||
scope.showMissingPlaybooksAlert = false;
|
||||
|
||||
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] });
|
||||
}
|
||||
if (scope.local_path) {
|
||||
// List only includes paths not assigned to projects, so add the
|
||||
// path assigned to the current project.
|
||||
opts.push({ label: scope.local_path, value: scope.local_path });
|
||||
}
|
||||
scope.project_local_paths = arraySort(opts);
|
||||
if (scope.local_path) {
|
||||
for (var i=0; scope.project_local_paths.length; i++) {
|
||||
if (scope.project_local_paths[i].value == scope.local_path) {
|
||||
scope.local_path = scope.project_local_paths[i];
|
||||
break;
|
||||
}
|
||||
names.sort();
|
||||
for (j = 0; j < names.length; j++) {
|
||||
for (i = 0; i < data.length; i++) {
|
||||
if (data[i].value === names[j]) {
|
||||
newData.push(data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return newData;
|
||||
}
|
||||
scope.base_dir = data.project_base_dir;
|
||||
master.local_path = scope.local_path;
|
||||
master.base_dir = scope.base_dir; // Keep in master object so that it doesn't get
|
||||
// wiped out on form reset.
|
||||
if (opts.length == 0) {
|
||||
// trigger display of alert block when scm_type == manual
|
||||
scope.showMissingPlaybooksAlert = true;
|
||||
}
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Failed to access API config. GET status: ' + status });
|
||||
});
|
||||
|
||||
scope.showMissingPlaybooksAlert = false;
|
||||
|
||||
Rest.setUrl(GetBasePath('config'));
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
var opts = [], i;
|
||||
for (i = 0; i < data.project_local_paths.length; i++) {
|
||||
opts.push({
|
||||
label: data.project_local_paths[i],
|
||||
value: data.project_local_paths[i]
|
||||
});
|
||||
}
|
||||
if (scope.local_path) {
|
||||
// List only includes paths not assigned to projects, so add the
|
||||
// path assigned to the current project.
|
||||
opts.push({
|
||||
label: scope.local_path,
|
||||
value: scope.local_path
|
||||
});
|
||||
}
|
||||
scope.project_local_paths = arraySort(opts);
|
||||
if (scope.local_path) {
|
||||
for (i = 0; scope.project_local_paths.length; i++) {
|
||||
if (scope.project_local_paths[i].value === scope.local_path) {
|
||||
scope.local_path = scope.project_local_paths[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
scope.base_dir = data.project_base_dir;
|
||||
master.local_path = scope.local_path;
|
||||
master.base_dir = scope.base_dir; // Keep in master object so that it doesn't get
|
||||
// wiped out on form reset.
|
||||
if (opts.length === 0) {
|
||||
// trigger display of alert block when scm_type == manual
|
||||
scope.showMissingPlaybooksAlert = true;
|
||||
}
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'Failed to access API config. GET status: ' + status });
|
||||
});
|
||||
};
|
||||
}
|
||||
}]);
|
||||
]);
|
||||
@ -3,125 +3,133 @@
|
||||
*
|
||||
* ProjectsHelper
|
||||
*
|
||||
* Use GetProjectPath({ scope: <scope>, master: <master obj> }) to
|
||||
* Use GetProjectPath({ scope: <scope>, master: <master obj> }) to
|
||||
* load scope.project_local_paths (array of options for drop-down) and
|
||||
* scope.base_dir (readonly field).
|
||||
* scope.base_dir (readonly field).
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('ProjectsHelper', ['RestServices', 'Utilities', 'ProjectStatusDefinition', 'ProjectFormDefinition'])
|
||||
|
||||
.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,
|
||||
FormatDate, ProjectStatusForm, Wait) {
|
||||
return function(params) {
|
||||
.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,
|
||||
FormatDate, ProjectStatusForm, Wait) {
|
||||
return function (params) {
|
||||
|
||||
var project_id = params.project_id;
|
||||
var last_update = params.last_update;
|
||||
|
||||
var generator = GenerateForm;
|
||||
var form = ProjectStatusForm;
|
||||
|
||||
Wait('start');
|
||||
var project_id = params.project_id,
|
||||
last_update = params.last_update,
|
||||
generator = GenerateForm,
|
||||
form = ProjectStatusForm,
|
||||
html, scope, ww, wh, x, y, maxrows;
|
||||
|
||||
// Using jquery dialog for its expandable property
|
||||
var html = "<div id=\"status-modal-dialog\"><div id=\"form-container\" style=\"width: 100%;\"></div></div>\n";
|
||||
$('#projects-modal-container').empty().append(html);
|
||||
Wait('start');
|
||||
|
||||
var scope = generator.inject(form, { mode: 'edit', id: 'form-container', related: false, breadCrumbs: false });
|
||||
generator.reset();
|
||||
// Using jquery dialog for its expandable property
|
||||
html = "<div id=\"status-modal-dialog\"><div id=\"form-container\" style=\"width: 100%;\"></div></div>\n";
|
||||
$('#projects-modal-container').empty().append(html);
|
||||
|
||||
// Set modal dimensions based on viewport width
|
||||
var ww = $(document).width();
|
||||
var wh = $('body').height();
|
||||
var x, y, maxrows;
|
||||
if (ww > 1199) {
|
||||
// desktop
|
||||
x = 675;
|
||||
y = (750 > wh) ? wh - 20 : 750;
|
||||
maxrows = 20;
|
||||
}
|
||||
else if (ww <= 1199 && ww >= 768) {
|
||||
x = 550;
|
||||
y = (620 > wh) ? wh - 15 : 620;
|
||||
maxrows = 15;
|
||||
}
|
||||
else {
|
||||
x = (ww - 20);
|
||||
y = (500 > wh) ? wh : 500;
|
||||
maxrows = 10;
|
||||
}
|
||||
// Create the modal
|
||||
$('#status-modal-dialog').dialog({
|
||||
buttons: { "OK": function() { $( this ).dialog( "close" ); } },
|
||||
modal: true,
|
||||
width: x,
|
||||
height: y,
|
||||
autoOpen: false,
|
||||
create: function (e, ui) {
|
||||
// fix the close button
|
||||
$('.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' });
|
||||
scope = generator.inject(form, { mode: 'edit', id: 'form-container', related: false, breadCrumbs: false });
|
||||
generator.reset();
|
||||
|
||||
// Set modal dimensions based on viewport width
|
||||
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) {
|
||||
x = 550;
|
||||
y = (620 > wh) ? wh - 15 : 620;
|
||||
maxrows = 15;
|
||||
} else {
|
||||
x = (ww - 20);
|
||||
y = (500 > wh) ? wh : 500;
|
||||
maxrows = 10;
|
||||
}
|
||||
// Create the modal
|
||||
$('#status-modal-dialog').dialog({
|
||||
buttons: {
|
||||
"OK": function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
},
|
||||
resizeStop: function(e, ui) {
|
||||
// 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 );
|
||||
modal: true,
|
||||
width: x,
|
||||
height: y,
|
||||
autoOpen: false,
|
||||
create: function () {
|
||||
// fix the close button
|
||||
$('.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'
|
||||
});
|
||||
},
|
||||
close: function(e, ui) {
|
||||
// Destroy on close
|
||||
// Destroy on close
|
||||
$('.tooltip').each( function(index) {
|
||||
// Remove any lingering tooltip <div> elements
|
||||
$(this).remove();
|
||||
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"]'),
|
||||
content = dialog.find('#status-modal-dialog');
|
||||
content.width(dialog.width() - 28);
|
||||
},
|
||||
close: function () {
|
||||
// Destroy on close
|
||||
// Destroy on close
|
||||
$('.tooltip').each(function () {
|
||||
// Remove any lingering tooltip <div> elements
|
||||
$(this).remove();
|
||||
});
|
||||
$('.popover').each(function(index) {
|
||||
// remove lingering popover <div> elements
|
||||
$(this).remove();
|
||||
$('.popover').each(function () {
|
||||
// remove lingering popover <div> elements
|
||||
$(this).remove();
|
||||
});
|
||||
$('#status-modal-dialog').dialog('destroy');
|
||||
$('#projects-modal-container').empty();
|
||||
$('#status-modal-dialog').dialog('destroy');
|
||||
$('#projects-modal-container').empty();
|
||||
},
|
||||
open: function(e, ui) {
|
||||
Wait('stop');
|
||||
open: function () {
|
||||
Wait('stop');
|
||||
}
|
||||
});
|
||||
|
||||
// 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) {
|
||||
if (results[fld]) {
|
||||
if (fld == 'created') {
|
||||
scope[fld] = FormatDate(new Date(results[fld]));
|
||||
}
|
||||
else {
|
||||
scope[fld] = results[fld];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (results.summary_fields.project[fld]) {
|
||||
scope[fld] = results.summary_fields.project[fld]
|
||||
}
|
||||
}
|
||||
}
|
||||
$('#status-modal-dialog')
|
||||
.dialog({ title: results.summary_fields.project.name + ' Status'})
|
||||
.dialog('open');
|
||||
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
$('#form-modal').modal("hide");
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve status of project: ' + project_id + '. GET status: ' + status });
|
||||
});
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Rest.setUrl(last_update);
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
var results = data, fld;
|
||||
for (fld in form.fields) {
|
||||
if (results[fld]) {
|
||||
if (fld === 'created') {
|
||||
scope[fld] = FormatDate(new Date(results[fld]));
|
||||
} else {
|
||||
scope[fld] = results[fld];
|
||||
}
|
||||
} else {
|
||||
if (results.summary_fields.project[fld]) {
|
||||
scope[fld] = results.summary_fields.project[fld];
|
||||
}
|
||||
}
|
||||
}
|
||||
$('#status-modal-dialog')
|
||||
.dialog({
|
||||
title: results.summary_fields.project.name + ' Status'
|
||||
})
|
||||
.dialog('open');
|
||||
|
||||
})
|
||||
.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
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
]);
|
||||
@ -3,167 +3,172 @@
|
||||
*
|
||||
* SelectionHelper
|
||||
* Used in list controllers where the list might also be used as a selection list.
|
||||
*
|
||||
*
|
||||
* SelectionInit( {
|
||||
* scope: <list scope>,
|
||||
* list: <list object>
|
||||
* })
|
||||
*/
|
||||
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('SelectionHelper', ['Utilities', 'RestServices'])
|
||||
|
||||
.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;
|
||||
.factory('SelectionInit', ['Rest', 'Alert', 'ProcessErrors', 'ReturnToCaller', 'Wait',
|
||||
function (Rest, Alert, ProcessErrors, ReturnToCaller, Wait) {
|
||||
return function (params) {
|
||||
|
||||
if (params.selected !== undefined) {
|
||||
var selected = params.selected;
|
||||
}
|
||||
else {
|
||||
var selected = []; //array of selected row IDs
|
||||
}
|
||||
var scope = params.scope,
|
||||
list = params.list,
|
||||
target_url = params.url,
|
||||
returnToCaller = params.returnToCaller,
|
||||
selected;
|
||||
|
||||
scope.formModalActionDisabled = true;
|
||||
scope.disableSelectBtn = true;
|
||||
if (params.selected !== undefined) {
|
||||
selected = params.selected;
|
||||
} else {
|
||||
selected = []; //array of selected row IDs
|
||||
}
|
||||
|
||||
// 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) ) {
|
||||
// select the row
|
||||
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 = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
selected.push(scope[list.name][i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// unselect the row
|
||||
scope[list.name][i]['checked'] = '0';
|
||||
scope[list.name][i]['success_class'] = '';
|
||||
|
||||
// remove selected object from the array
|
||||
for (var j=0; j < selected.length; j++) {
|
||||
if (selected[j].id == id) {
|
||||
selected.splice(j,1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (selected.length > 0) {
|
||||
scope.formModalActionDisabled = false;
|
||||
scope.disableSelectBtn = false;
|
||||
}
|
||||
else {
|
||||
scope.formModalActionDisabled = true;
|
||||
scope.disableSelectBtn = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the selections
|
||||
scope.finishSelection = function() {
|
||||
Rest.setUrl(target_url);
|
||||
var queue = [];
|
||||
scope.formModalActionDisabled = true;
|
||||
scope.disableSelectBtn = true;
|
||||
|
||||
Wait('start');
|
||||
|
||||
function finished() {
|
||||
selected = [];
|
||||
if (returnToCaller !== undefined) {
|
||||
ReturnToCaller(returnToCaller);
|
||||
// toggle row selection
|
||||
scope['toggle_' + list.iterator] = function (id, ischeckbox) {
|
||||
var i, j, found;
|
||||
for (i = 0; i < scope[list.name].length; i++) {
|
||||
if (scope[list.name][i].id === id) {
|
||||
if ((scope[list.name][i].checked === "0" && !ischeckbox) || (scope[list.name][i].checked === "1" && ischeckbox)) {
|
||||
// select the row
|
||||
scope[list.name][i].checked = '1';
|
||||
scope[list.name][i].success_class = 'success';
|
||||
// add selected object to the array
|
||||
found = false;
|
||||
for (j = 0; j < selected.length; j++) {
|
||||
if (selected[j].id === id) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
selected.push(scope[list.name][i]);
|
||||
}
|
||||
} else {
|
||||
// unselect the row
|
||||
scope[list.name][i].checked = '0';
|
||||
scope[list.name][i].success_class = '';
|
||||
|
||||
// remove selected object from the array
|
||||
for (j = 0; j < selected.length; j++) {
|
||||
if (selected[j].id === id) {
|
||||
selected.splice(j, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$('#form-modal').modal('hide');
|
||||
scope.$emit('modalClosed');
|
||||
if (selected.length > 0) {
|
||||
console.log('selected.length: ' + selected.length);
|
||||
scope.formModalActionDisabled = false;
|
||||
scope.disableSelectBtn = false;
|
||||
} else {
|
||||
scope.formModalActionDisabled = true;
|
||||
scope.disableSelectBtn = true;
|
||||
}
|
||||
};
|
||||
|
||||
// Add the selections
|
||||
scope.finishSelection = function () {
|
||||
Rest.setUrl(target_url);
|
||||
|
||||
var queue = [], j;
|
||||
|
||||
scope.formModalActionDisabled = true;
|
||||
scope.disableSelectBtn = true;
|
||||
|
||||
Wait('start');
|
||||
|
||||
function finished() {
|
||||
selected = [];
|
||||
if (returnToCaller !== undefined) {
|
||||
ReturnToCaller(returnToCaller);
|
||||
} else {
|
||||
$('#form-modal').modal('hide');
|
||||
scope.$emit('modalClosed');
|
||||
}
|
||||
}
|
||||
|
||||
if (scope.callFinishedRemove) {
|
||||
scope.callFinishedRemove();
|
||||
}
|
||||
scope.callFinishedRemove = scope.$on('callFinished', function() {
|
||||
// We call the API for each selected item. We need to hang out until all the api
|
||||
// calls are finished.
|
||||
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 });
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
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');
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
finished();
|
||||
}
|
||||
}
|
||||
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');
|
||||
});
|
||||
}
|
||||
|
||||
scope.formModalAction = scope.finishSelection;
|
||||
if (scope.callFinishedRemove) {
|
||||
scope.callFinishedRemove();
|
||||
}
|
||||
scope.callFinishedRemove = scope.$on('callFinished', function () {
|
||||
// We call the API for each selected item. We need to hang out until all the api
|
||||
// calls are finished.
|
||||
var i, errors=0;
|
||||
if (queue.length === selected.length) {
|
||||
Wait('stop');
|
||||
for (i = 0; i < queue.length; i++) {
|
||||
if (queue[i].result === 'error') {
|
||||
ProcessErrors(scope, queue[i].data, queue[i].status, null, { hdr: 'POST Failure',
|
||||
msg: 'Failed to add ' + list.iterator + '. POST returned status: ' + queue[i].status });
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
if (errors === 0) {
|
||||
finished();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize our data set after a refresh (page change or search)
|
||||
if (scope.SelectPostRefreshRemove) {
|
||||
scope.SelectPostRefreshRemove();
|
||||
}
|
||||
scope.SelectPostRefreshRemove = scope.$on('PostRefresh', function() {
|
||||
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) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
scope[list.name][i]['checked'] = '1';
|
||||
scope[list.name][i]['success_class'] = 'success';
|
||||
}
|
||||
else {
|
||||
scope[list.name][i]['checked'] = '0';
|
||||
scope[list.name][i]['success_class'] = '';
|
||||
}
|
||||
}
|
||||
if (selected.length > 0) {
|
||||
for (j = 0; j < selected.length; j++) {
|
||||
postIt(selected[j]);
|
||||
}
|
||||
} else {
|
||||
finished();
|
||||
}
|
||||
};
|
||||
|
||||
scope.formModalAction = scope.finishSelection;
|
||||
|
||||
// Initialize our data set after a refresh (page change or search)
|
||||
if (scope.SelectPostRefreshRemove) {
|
||||
scope.SelectPostRefreshRemove();
|
||||
}
|
||||
scope.SelectPostRefreshRemove = scope.$on('PostRefresh', function () {
|
||||
var i, j, found;
|
||||
if (scope[list.name]) {
|
||||
for (i = 0; i < scope[list.name].length; i++) {
|
||||
found = false;
|
||||
for (j = 0; j < selected.length; j++) {
|
||||
if (selected[j].id === scope[list.name][i].id) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
scope[list.name][i].checked = '1';
|
||||
scope[list.name][i].success_class = 'success';
|
||||
} else {
|
||||
scope[list.name][i].checked = '0';
|
||||
scope[list.name][i].success_class = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}]);
|
||||
};
|
||||
}
|
||||
]);
|
||||
@ -2,27 +2,38 @@
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* UserHelper
|
||||
* Routines shared amongst the user controllers
|
||||
* Routines shared amongst the user controllers
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
}]);
|
||||
'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;
|
||||
};
|
||||
}
|
||||
]);
|
||||
|
||||
@ -3,87 +3,89 @@
|
||||
*
|
||||
* APIDefaults
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('APIDefaults', ['RestServices', 'Utilities'])
|
||||
.factory('GetAPIDefaults', ['Alert', 'Rest', '$rootScope', function(Alert, Rest, $rootScope) {
|
||||
return function(key) {
|
||||
|
||||
//Reload a related collection on pagination or search change
|
||||
|
||||
var answer;
|
||||
var result = {};
|
||||
var cnt=0;
|
||||
'use strict';
|
||||
|
||||
function lookup(key) {
|
||||
var result = {};
|
||||
for (id in $rootScope.apiDefaults) {
|
||||
if (id == key || id.iterator == key) {
|
||||
result[id] = defaults[id];
|
||||
break;
|
||||
}
|
||||
angular.module('APIDefaults', ['RestServices', 'Utilities'])
|
||||
.factory('GetAPIDefaults', ['Alert', 'Rest', '$rootScope',
|
||||
function (Alert, Rest, $rootScope) {
|
||||
return function (key) {
|
||||
|
||||
//Reload a related collection on pagination or search change
|
||||
|
||||
var result = {}, cnt = 0, url;
|
||||
|
||||
function lookup(key) {
|
||||
var id, result = {};
|
||||
for (id in $rootScope.apiDefaults) {
|
||||
if (id === key || id.iterator === key) {
|
||||
result[id] = $rootScope.apiDefaults[id];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function wait() {
|
||||
if ($.isEmptyObject(result) && cnt < 5) {
|
||||
cnt++;
|
||||
setTimeout(1000, wait());
|
||||
} else if (result.status === 'success') {
|
||||
return lookup(key);
|
||||
}
|
||||
}
|
||||
|
||||
if ($rootScope.apiDefaults === null || $rootScope.apiDefaults === undefined) {
|
||||
url = '/api/v1/';
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
var id, defaults = data;
|
||||
for (id in defaults) {
|
||||
switch (id) {
|
||||
case 'organizations':
|
||||
defaults[id].iterator = 'organization';
|
||||
break;
|
||||
case 'jobs':
|
||||
defaults[id].iterator = 'job';
|
||||
break;
|
||||
case 'users':
|
||||
defaults[id].iterator = 'user';
|
||||
break;
|
||||
case 'teams':
|
||||
defaults[id].iterator = 'team';
|
||||
break;
|
||||
case 'hosts':
|
||||
defaults[id].iterator = 'host';
|
||||
break;
|
||||
case 'groups':
|
||||
defaults[id].iterator = 'group';
|
||||
break;
|
||||
case 'projects':
|
||||
defaults[id].iterator = 'project';
|
||||
break;
|
||||
case 'inventories':
|
||||
defaults[id].iterator = 'inventory';
|
||||
break;
|
||||
}
|
||||
}
|
||||
$rootScope.apiDefaults = defaults;
|
||||
result = {
|
||||
status: 'success'
|
||||
};
|
||||
})
|
||||
.error(function (data, status) {
|
||||
result = {
|
||||
status: 'error',
|
||||
msg: 'Call to ' + url + ' failed. GET returned status: ' + status
|
||||
};
|
||||
});
|
||||
return wait();
|
||||
} else {
|
||||
return lookup(key);
|
||||
}
|
||||
};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function wait() {
|
||||
var answer;
|
||||
if ( result == {} && cnt < 5) {
|
||||
cnt++;
|
||||
setTimeout(1000, wait());
|
||||
}
|
||||
else {
|
||||
if (result.status == 'success') {
|
||||
return lookup(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($rootScope.apiDefaults == null || $rootScope.apiDefaults == undefined) {
|
||||
var result = {};
|
||||
var url = '/api/v1';
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
defaults = data;
|
||||
for (var id in defaults) {
|
||||
switch (id) {
|
||||
case 'organizations':
|
||||
dafaults[id].iterator = 'organization';
|
||||
break;
|
||||
case 'jobs':
|
||||
defaults[id].iterator = 'job';
|
||||
break;
|
||||
case 'users':
|
||||
defaults[id].iterator = 'user';
|
||||
break;
|
||||
case 'teams':
|
||||
defaults[id].iterator = 'team';
|
||||
break;
|
||||
case 'hosts':
|
||||
defaults[id].iterator = 'host';
|
||||
break;
|
||||
case 'groups':
|
||||
defaults[id].iterator = 'group';
|
||||
break;
|
||||
case 'projects':
|
||||
defaults[id].iterator = 'project';
|
||||
break;
|
||||
}
|
||||
}
|
||||
$rootScope.apiDefaults = defaults;
|
||||
result = {status: 'success'};
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
result = {status: 'error', msg: 'Call to ' + url + ' failed. GET returned status: ' + status};
|
||||
});
|
||||
return wait();
|
||||
}
|
||||
else {
|
||||
return lookup(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}]);
|
||||
]);
|
||||
@ -5,250 +5,250 @@
|
||||
* Routines for building the tree. Everything related to the tree is here except
|
||||
* for the menu piece. The routine for building the menu is in InventoriesEdit controller
|
||||
* (controllers/Inventories.js)
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
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() {
|
||||
clearTimeout(timeOut);
|
||||
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) ) + '%';
|
||||
$(this).find('.group-name').css({ width: pct });
|
||||
/* globals console:false */
|
||||
|
||||
'use strict';
|
||||
|
||||
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 () {
|
||||
clearTimeout(timeOut);
|
||||
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(),
|
||||
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');
|
||||
ApplyEllipsis('#groups_table .group-name a');
|
||||
ApplyEllipsis('#hosts_table .host-name a');
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
}])
|
||||
});
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
.factory('SaveInventory', ['InventoryForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList',
|
||||
'GetBasePath', 'ParseTypeChange', 'Wait',
|
||||
function(InventoryForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, Wait) {
|
||||
return function(params) {
|
||||
|
||||
// Save inventory property modifications
|
||||
.factory('SaveInventory', ['InventoryForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList',
|
||||
'GetBasePath', 'ParseTypeChange', 'Wait',
|
||||
function (InventoryForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, Wait) {
|
||||
return function (params) {
|
||||
|
||||
var scope = params.scope;
|
||||
|
||||
var form = InventoryForm;
|
||||
var defaultUrl=GetBasePath('inventory');
|
||||
// Save inventory property modifications
|
||||
|
||||
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
|
||||
}
|
||||
var scope = params.scope,
|
||||
form = InventoryForm,
|
||||
defaultUrl = GetBasePath('inventory'),
|
||||
fld, json_data, data;
|
||||
|
||||
// Make sure our JSON is actually an object
|
||||
if (typeof json_data !== 'object') {
|
||||
throw "failed to return an object!";
|
||||
}
|
||||
Wait('start');
|
||||
|
||||
var data = {}
|
||||
for (var 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];
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
// Make sure we have valid variable data
|
||||
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
|
||||
}
|
||||
|
||||
Rest.setUrl(defaultUrl + scope['inventory_id'] + '/');
|
||||
Rest.put(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
if (scope.inventory_variables) {
|
||||
Rest.setUrl(data.related.variable_data);
|
||||
Rest.put(json_data)
|
||||
.success( function(data, status, headers, config) {
|
||||
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 });
|
||||
});
|
||||
}
|
||||
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 });
|
||||
});
|
||||
}
|
||||
catch(err) {
|
||||
Wait('stop');
|
||||
Alert("Error", "Error parsing inventory variables. Parser returned: " + err);
|
||||
}
|
||||
}
|
||||
}])
|
||||
// Make sure our JSON is actually an object
|
||||
if (typeof json_data !== 'object') {
|
||||
throw "failed to return an object!";
|
||||
}
|
||||
|
||||
|
||||
.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,
|
||||
Wait, Store, SearchInit) {
|
||||
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');
|
||||
|
||||
form.well = false;
|
||||
|
||||
var scope = generator.inject(form, {mode: 'edit', modal: true, related: false, modal_show: false });
|
||||
|
||||
/* Reset form properties. Otherwise it screws up future requests of the Inventories detail page */
|
||||
form.well = true;
|
||||
|
||||
ParseTypeChange(scope,'inventory_variables', 'inventoryParseType');
|
||||
scope.inventoryParseType = 'yaml';
|
||||
scope.formModalActionLabel = 'Save';
|
||||
scope.formModalCancelShow = true;
|
||||
scope.formModalInfo = false;
|
||||
scope.formModalHeader = 'Inventory Properties';
|
||||
|
||||
Wait('start');
|
||||
Rest.setUrl(GetBasePath('inventory') + inventory_id + '/');
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
for (var fld in form.fields) {
|
||||
if (fld == 'inventory_variables') {
|
||||
// Parse variables, converting to YAML.
|
||||
if ($.isEmptyObject(data.variables) || data.variables == "\{\}" ||
|
||||
data.variables == "null" || data.variables == "") {
|
||||
scope.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];
|
||||
}
|
||||
else {
|
||||
try {
|
||||
var json_obj = JSON.parse(data.variables);
|
||||
scope.inventory_variables = jsyaml.safeDump(json_obj);
|
||||
}
|
||||
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') {
|
||||
scope[fld] = data.name;
|
||||
master[fld] = scope[fld];
|
||||
}
|
||||
else if (fld == 'inventory_description') {
|
||||
scope[fld] = data.description;
|
||||
master[fld] = scope[fld];
|
||||
}
|
||||
else if (data[fld]) {
|
||||
scope[fld] = data[fld];
|
||||
master[fld] = scope[fld];
|
||||
}
|
||||
|
||||
if (form.fields[fld].sourceModel && data.summary_fields &&
|
||||
data.summary_fields[form.fields[fld].sourceModel]) {
|
||||
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
||||
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
|
||||
master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
||||
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
|
||||
}
|
||||
}
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: scope.organization,
|
||||
list: OrganizationList,
|
||||
field: 'organization'
|
||||
});
|
||||
|
||||
Rest.setUrl(defaultUrl + scope.inventory_id + '/');
|
||||
Rest.put(data)
|
||||
.success(function (data) {
|
||||
if (scope.inventory_variables) {
|
||||
Rest.setUrl(data.related.variable_data);
|
||||
Rest.put(json_data)
|
||||
.success(function () {
|
||||
Wait('stop');
|
||||
scope.$emit('InventorySaved');
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
|
||||
msg: 'Failed to update inventory varaibles. PUT returned status: ' + status
|
||||
});
|
||||
});
|
||||
} else {
|
||||
scope.$emit('InventorySaved');
|
||||
}
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
|
||||
msg: 'Failed to update inventory. POST returned status: ' + status });
|
||||
});
|
||||
} catch (err) {
|
||||
Wait('stop');
|
||||
$('#form-modal').modal('show');
|
||||
Alert("Error", "Error parsing inventory variables. Parser returned: " + err);
|
||||
}
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
.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,
|
||||
Wait, Store, SearchInit) {
|
||||
return function (params) {
|
||||
|
||||
var parent_scope = params.scope,
|
||||
inventory_id = params.inventory_id,
|
||||
generator = GenerateForm,
|
||||
form = InventoryForm,
|
||||
master = {},
|
||||
PreviousSearchParams = Store('CurrentSearchParams'),
|
||||
scope;
|
||||
|
||||
form.well = 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.inventoryParseType = 'yaml';
|
||||
scope.formModalActionLabel = 'Save';
|
||||
scope.formModalCancelShow = true;
|
||||
scope.formModalInfo = false;
|
||||
scope.formModalHeader = 'Inventory Properties';
|
||||
|
||||
Wait('start');
|
||||
Rest.setUrl(GetBasePath('inventory') + inventory_id + '/');
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
var fld, 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 === "") {
|
||||
scope.inventory_variables = "---";
|
||||
} else {
|
||||
try {
|
||||
json_obj = JSON.parse(data.variables);
|
||||
scope.inventory_variables = jsyaml.safeDump(json_obj);
|
||||
} 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') {
|
||||
scope[fld] = data.name;
|
||||
master[fld] = scope[fld];
|
||||
} else if (fld === 'inventory_description') {
|
||||
scope[fld] = data.description;
|
||||
master[fld] = scope[fld];
|
||||
} else if (data[fld]) {
|
||||
scope[fld] = data[fld];
|
||||
master[fld] = scope[fld];
|
||||
}
|
||||
|
||||
if (form.fields[fld].sourceModel && data.summary_fields &&
|
||||
data.summary_fields[form.fields[fld].sourceModel]) {
|
||||
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
||||
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
|
||||
master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
||||
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
|
||||
}
|
||||
}
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: scope.organization,
|
||||
list: OrganizationList,
|
||||
field: 'organization'
|
||||
});
|
||||
|
||||
Wait('stop');
|
||||
$('#form-modal').modal('show');
|
||||
|
||||
})
|
||||
.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() {
|
||||
$('#form-modal').modal('hide');
|
||||
// Restore prior search state
|
||||
if (scope.searchCleanp) {
|
||||
scope.searchCleanup();
|
||||
|
||||
if (scope.removeInventorySaved) {
|
||||
scope.removeInventorySaved();
|
||||
}
|
||||
SearchInit({
|
||||
scope: parent_scope,
|
||||
set: PreviousSearchParams.set,
|
||||
list: PreviousSearchParams.list,
|
||||
url: PreviousSearchParams.defaultUrl,
|
||||
iterator: PreviousSearchParams.iterator,
|
||||
sort_order: PreviousSearchParams.sort_order,
|
||||
setWidgets: false
|
||||
scope.removeInventorySaved = scope.$on('InventorySaved', function () {
|
||||
$('#form-modal').modal('hide');
|
||||
// Restore prior search state
|
||||
if (scope.searchCleanp) {
|
||||
scope.searchCleanup();
|
||||
}
|
||||
SearchInit({
|
||||
scope: parent_scope,
|
||||
set: PreviousSearchParams.set,
|
||||
list: PreviousSearchParams.list,
|
||||
url: PreviousSearchParams.defaultUrl,
|
||||
iterator: PreviousSearchParams.iterator,
|
||||
sort_order: PreviousSearchParams.sort_order,
|
||||
setWidgets: false
|
||||
});
|
||||
parent_scope.$emit('RefreshInventories');
|
||||
parent_scope.$emit('RefreshInventories');
|
||||
});
|
||||
|
||||
scope.cancelModal = function() {
|
||||
// Restore prior search state
|
||||
if (scope.searchCleanp) {
|
||||
scope.searchCleanup();
|
||||
}
|
||||
SearchInit({
|
||||
scope: parent_scope,
|
||||
set: PreviousSearchParams.set,
|
||||
list: PreviousSearchParams.list,
|
||||
url: PreviousSearchParams.defaultUrl,
|
||||
iterator: PreviousSearchParams.iterator,
|
||||
sort_order: PreviousSearchParams.sort_order,
|
||||
setWidgets: false
|
||||
scope.cancelModal = function () {
|
||||
// Restore prior search state
|
||||
if (scope.searchCleanp) {
|
||||
scope.searchCleanup();
|
||||
}
|
||||
SearchInit({
|
||||
scope: parent_scope,
|
||||
set: PreviousSearchParams.set,
|
||||
list: PreviousSearchParams.list,
|
||||
url: PreviousSearchParams.defaultUrl,
|
||||
iterator: PreviousSearchParams.iterator,
|
||||
sort_order: PreviousSearchParams.sort_order,
|
||||
setWidgets: false
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
scope.formModalAction = function() {
|
||||
parent_scope.inventory_id = inventory_id;
|
||||
parent_scope.inventory_name = scope.inventory_name;
|
||||
SaveInventory({ scope: scope });
|
||||
}
|
||||
|
||||
}
|
||||
}]);
|
||||
scope.formModalAction = function () {
|
||||
parent_scope.inventory_id = inventory_id;
|
||||
parent_scope.inventory_name = scope.inventory_name;
|
||||
SaveInventory({
|
||||
scope: scope
|
||||
});
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
]);
|
||||
@ -8,33 +8,33 @@
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('md5Helper', ['RestServices', 'Utilities'])
|
||||
.factory('md5Setup', ['Alert', 'Rest', 'GetBasePath','ProcessErrors',
|
||||
function(Alert, Rest, GetBasePath, ProcessErrors) {
|
||||
return function(params) {
|
||||
|
||||
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
|
||||
|
||||
scope[check_field] = default_val;
|
||||
master[check_field] = default_val;
|
||||
'use strict';
|
||||
|
||||
scope.genMD5 = function(fld) {
|
||||
var now = new Date();
|
||||
scope[fld] = $.md5('AnsibleWorks' + now.getTime());
|
||||
}
|
||||
angular.module('md5Helper', ['RestServices', 'Utilities'])
|
||||
.factory('md5Setup', [ function () {
|
||||
return function (params) {
|
||||
|
||||
var scope = params.scope,
|
||||
master = params.master,
|
||||
check_field = params.check_field,
|
||||
default_val = params.default_val;
|
||||
|
||||
scope.toggleCallback = function(fld) {
|
||||
if (scope.allow_callbacks == 'false') {
|
||||
scope[fld] = '';
|
||||
}
|
||||
}
|
||||
scope[check_field] = default_val;
|
||||
master[check_field] = default_val;
|
||||
|
||||
scope.selectAll = function(fld) {
|
||||
$('input[name="' + fld +'"]').focus().select();
|
||||
}
|
||||
|
||||
}
|
||||
}]);
|
||||
scope.genMD5 = function (fld) {
|
||||
var now = new Date();
|
||||
scope[fld] = $.md5('AnsibleWorks' + now.getTime());
|
||||
};
|
||||
|
||||
scope.toggleCallback = function (fld) {
|
||||
if (scope.allow_callbacks === 'false') {
|
||||
scope[fld] = '';
|
||||
}
|
||||
};
|
||||
|
||||
scope.selectAll = function (fld) {
|
||||
$('input[name="' + fld + '"]').focus().select();
|
||||
};
|
||||
};
|
||||
}]);
|
||||
@ -9,35 +9,43 @@
|
||||
* scope: <current scope>,
|
||||
* set: <model>,
|
||||
* iterator: <model name in singular form (i.e. organization),
|
||||
* url: <the api url to call>
|
||||
* });
|
||||
* url: <the api url to call>
|
||||
* });
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('RefreshRelatedHelper', ['RestServices', 'Utilities', 'PaginationHelpers'])
|
||||
.factory('RefreshRelated', ['ProcessErrors', 'Rest', 'Wait', 'PageRangeSetup',
|
||||
function(ProcessErrors, Rest, Wait, PageRangeSetup) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var set = params.set;
|
||||
var iterator = params.iterator;
|
||||
var 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'];
|
||||
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 });
|
||||
});
|
||||
'use strict';
|
||||
|
||||
angular.module('RefreshRelatedHelper', ['RestServices', 'Utilities', 'PaginationHelpers'])
|
||||
.factory('RefreshRelated', ['ProcessErrors', 'Rest', 'Wait', 'PageRangeSetup',
|
||||
function (ProcessErrors, Rest, Wait, PageRangeSetup) {
|
||||
return function (params) {
|
||||
|
||||
var scope = params.scope,
|
||||
set = params.set,
|
||||
iterator = params.iterator,
|
||||
url = params.url;
|
||||
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
PageRangeSetup({
|
||||
scope: scope,
|
||||
count: data.count,
|
||||
next: data.next,
|
||||
previous: data.previous,
|
||||
iterator: iterator
|
||||
});
|
||||
scope[set] = data.results;
|
||||
scope[iterator + 'Loading'] = false;
|
||||
scope[iterator + 'HoldInput'] = false;
|
||||
Wait('stop');
|
||||
scope.$emit('related' + set);
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'Failed to retrieve ' + set + '. GET returned status: ' + status });
|
||||
});
|
||||
};
|
||||
}
|
||||
}]);
|
||||
]);
|
||||
@ -9,40 +9,52 @@
|
||||
* scope: <current scope>,
|
||||
* set: <model>,
|
||||
* iterator: <model name in singular form (i.e. organization),
|
||||
* url: <the api url to call>
|
||||
* });
|
||||
* url: <the api url to call>
|
||||
* });
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('RefreshHelper', ['RestServices', 'Utilities', 'PaginationHelpers'])
|
||||
.factory('Refresh', ['ProcessErrors', 'Rest', 'Wait', 'Empty', 'PageRangeSetup',
|
||||
function(ProcessErrors, Rest, Wait, Empty, PageRangeSetup) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var set = params.set;
|
||||
var iterator = params.iterator;
|
||||
var 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 });
|
||||
scope[iterator + 'Loading'] = false;
|
||||
for (var i=1; i <= 3; i++) {
|
||||
var modifier = (i == 1) ? '' : i;
|
||||
scope[iterator + 'HoldInput' + modifier] = false;
|
||||
}
|
||||
scope[set] = data['results'];
|
||||
window.scrollTo(0,0);
|
||||
Wait('stop');
|
||||
scope.$emit('PostRefresh');
|
||||
})
|
||||
.error ( function(data, status, headers, config) {
|
||||
scope[iterator + 'HoldInput'] = false;
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve ' + set + '. GET returned status: ' + status });
|
||||
});
|
||||
'use strict';
|
||||
|
||||
angular.module('RefreshHelper', ['RestServices', 'Utilities', 'PaginationHelpers'])
|
||||
.factory('Refresh', ['ProcessErrors', 'Rest', 'Wait', 'Empty', 'PageRangeSetup',
|
||||
function (ProcessErrors, Rest, Wait, Empty, PageRangeSetup) {
|
||||
return function (params) {
|
||||
|
||||
var scope = params.scope,
|
||||
set = params.set,
|
||||
iterator = params.iterator,
|
||||
url = params.url;
|
||||
|
||||
scope.current_url = url;
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
var i, modifier;
|
||||
PageRangeSetup({
|
||||
scope: scope,
|
||||
count: data.count,
|
||||
next: data.next,
|
||||
previous: data.previous,
|
||||
iterator: iterator
|
||||
});
|
||||
scope[iterator + 'Loading'] = false;
|
||||
for (i = 1; i <= 3; i++) {
|
||||
modifier = (i === 1) ? '' : i;
|
||||
scope[iterator + 'HoldInput' + modifier] = false;
|
||||
}
|
||||
scope[set] = data.results;
|
||||
window.scrollTo(0, 0);
|
||||
Wait('stop');
|
||||
scope.$emit('PostRefresh');
|
||||
})
|
||||
.error(function (data, status) {
|
||||
scope[iterator + 'HoldInput'] = false;
|
||||
ProcessErrors(scope, data, status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to retrieve ' + set + '. GET returned status: ' + status
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
}]);
|
||||
]);
|
||||
@ -3,247 +3,241 @@
|
||||
*
|
||||
* RelatedSearchHelper
|
||||
*
|
||||
* All the parts for controlling the search widget on
|
||||
* All the parts for controlling the search widget on
|
||||
* related collections.
|
||||
*
|
||||
* SearchInit({
|
||||
* scope: <scope>,
|
||||
* relatedSets: <array of related collections {model_name, url, iterator}>,
|
||||
* form: <form object used by FormGenerator>
|
||||
* });
|
||||
* });
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('RelatedSearchHelper', ['RestServices', 'Utilities','RefreshRelatedHelper'])
|
||||
.factory('RelatedSearchInit', ['$timeout', 'Alert', 'Rest', 'RefreshRelated', 'Wait',
|
||||
function($timeout, Alert, Rest, RefreshRelated, Wait) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var relatedSets = params.relatedSets;
|
||||
var form = params.form;
|
||||
|
||||
// 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)) {
|
||||
iterator = form.related[set].iterator;
|
||||
for (var fld in form.related[set].fields) {
|
||||
if (form.related[set].fields[fld].key) {
|
||||
scope[iterator + 'SearchField'] = fld
|
||||
scope[iterator + 'SearchFieldLabel'] = form.related[set].fields[fld].label;
|
||||
break;
|
||||
'use strict';
|
||||
|
||||
angular.module('RelatedSearchHelper', ['RestServices', 'Utilities', 'RefreshRelatedHelper'])
|
||||
.factory('RelatedSearchInit', ['$timeout', 'Alert', 'Rest', 'RefreshRelated', 'Wait', 'Empty',
|
||||
function ($timeout, Alert, Rest, RefreshRelated, Wait, Empty) {
|
||||
return function (params) {
|
||||
|
||||
var scope = params.scope,
|
||||
relatedSets = params.relatedSets,
|
||||
form = params.form, f;
|
||||
|
||||
// Set default values
|
||||
function setDefaults(inIterator) {
|
||||
var iterator, f, fld, set;
|
||||
for (set in form.related) {
|
||||
if (form.related[set].type !== 'tree' && (inIterator === undefined || inIterator === form.related[set].iterator)) {
|
||||
iterator = form.related[set].iterator;
|
||||
for (fld in form.related[set].fields) {
|
||||
if (form.related[set].fields[fld].key) {
|
||||
scope[iterator + 'SearchField'] = fld;
|
||||
scope[iterator + 'SearchFieldLabel'] = form.related[set].fields[fld].label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
scope[iterator + 'SortOrder'] = null;
|
||||
scope[iterator + 'SearchType'] = 'icontains';
|
||||
scope[iterator + 'SearchTypeLabel'] = 'Contains';
|
||||
scope[iterator + 'SearchValue'] = null;
|
||||
scope[iterator + 'SelectShow'] = false;
|
||||
//scope[iterator + 'HideSearchType'] = false;
|
||||
scope[iterator + 'ShowStartBtn'] = true;
|
||||
scope[iterator + 'HideAllStartBtn'] = false;
|
||||
|
||||
f = scope[iterator + 'SearchField'];
|
||||
if (form.related[set].fields[f].searchType &&
|
||||
(form.related[set].fields[f].searchType === 'boolean' || form.related[set].fields[f].searchType === 'select')) {
|
||||
scope[iterator + 'SelectShow'] = true;
|
||||
scope[iterator + 'SearchSelectOpts'] = form.fields[f].searchOptions;
|
||||
}
|
||||
if (form.related[set].fields[f].searchType && form.related[set].fields[f].searchType === 'gtzero') {
|
||||
scope[iterator + "InputHide"] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
scope[iterator + 'SortOrder'] = null;
|
||||
scope[iterator + 'SearchType'] = 'icontains';
|
||||
scope[iterator + 'SearchTypeLabel'] = 'Contains';
|
||||
scope[iterator + 'SearchValue'] = null;
|
||||
}
|
||||
|
||||
setDefaults();
|
||||
|
||||
scope.resetSearch = function (iterator) {
|
||||
setDefaults(iterator);
|
||||
scope.search(iterator);
|
||||
};
|
||||
|
||||
// Functions to handle search widget changes
|
||||
scope.setSearchField = function (iterator, fld, label) {
|
||||
|
||||
var f, related;
|
||||
|
||||
for (related in form.related) {
|
||||
if (form.related[related].iterator === iterator) {
|
||||
f = form.related[related].fields[fld];
|
||||
}
|
||||
}
|
||||
|
||||
scope[iterator + 'SearchFieldLabel'] = label;
|
||||
scope[iterator + 'SearchField'] = fld;
|
||||
scope[iterator + 'SearchValue'] = '';
|
||||
scope[iterator + 'SelectShow'] = false;
|
||||
//scope[iterator + 'HideSearchType'] = false;
|
||||
scope[iterator + 'InputHide'] = false;
|
||||
scope[iterator + 'ShowStartBtn'] = true;
|
||||
scope[iterator + 'HideAllStartBtn'] = false;
|
||||
|
||||
f = scope[iterator + 'SearchField']
|
||||
if (form.related[set].fields[f].searchType && ( form.related[set].fields[f].searchType == 'boolean'
|
||||
|| form.related[set].fields[f].searchType == 'select')) {
|
||||
scope[iterator + 'SelectShow'] = true;
|
||||
scope[iterator + 'SearchSelectOpts'] = list.fields[f].searchOptions;
|
||||
if (f.searchType !== undefined && f.searchType === 'gtzero') {
|
||||
scope[iterator + "InputHide"] = true;
|
||||
scope[iterator + 'ShowStartBtn'] = false;
|
||||
}
|
||||
if (form.related[set].fields[f].searchType && form.related[set].fields[f].searchType == 'gtzero') {
|
||||
scope[iterator + "InputHide"] = true;
|
||||
if (f.searchType !== undefined && (f.searchType === 'boolean' || f.searchType === 'select')) {
|
||||
scope[iterator + 'SelectShow'] = true;
|
||||
scope[iterator + 'SearchSelectOpts'] = f.searchOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setDefaults();
|
||||
if (f.searchType !== undefined && f.searchType === 'int') {
|
||||
//scope[iterator + 'HideSearchType'] = true;
|
||||
scope[iterator + 'SearchType'] = 'int';
|
||||
}
|
||||
|
||||
scope.resetSearch = function(iterator) {
|
||||
setDefaults(iterator);
|
||||
scope.search(iterator);
|
||||
}
|
||||
|
||||
// Functions to handle search widget changes
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
scope[iterator + 'SearchFieldLabel'] = label;
|
||||
scope[iterator + 'SearchField'] = fld;
|
||||
scope[iterator + 'SearchValue'] = '';
|
||||
scope[iterator + 'SelectShow'] = false;
|
||||
//scope[iterator + 'HideSearchType'] = false;
|
||||
scope[iterator + 'InputHide'] = false;
|
||||
scope[iterator + 'ShowStartBtn'] = true;
|
||||
scope.search(iterator);
|
||||
|
||||
if (f.searchType !== undefined && f.searchType == 'gtzero') {
|
||||
scope[iterator + "InputHide"] = true;
|
||||
scope[iterator + 'ShowStartBtn'] = false;
|
||||
}
|
||||
if (f.searchType !== undefined && (f.searchType == 'boolean'
|
||||
|| f.searchType == 'select')) {
|
||||
scope[iterator + 'SelectShow'] = true;
|
||||
scope[iterator + 'SearchSelectOpts'] = f.searchOptions;
|
||||
}
|
||||
if (f.searchType !== undefined && f.searchType == 'int') {
|
||||
//scope[iterator + 'HideSearchType'] = true;
|
||||
scope[model + 'SearchType'] = 'int';
|
||||
}
|
||||
};
|
||||
|
||||
scope.search(iterator);
|
||||
scope.setSearchType = function (model, type, label) {
|
||||
scope[model + 'SearchTypeLabel'] = label;
|
||||
scope[model + 'SearchType'] = type;
|
||||
scope.search(model);
|
||||
};
|
||||
|
||||
}
|
||||
scope.startSearch = function (e, iterator) {
|
||||
// If use clicks enter while on input field, start the search
|
||||
if (e.keyCode === 13) {
|
||||
scope.search(iterator);
|
||||
}
|
||||
};
|
||||
|
||||
scope.setSearchType = function(model, type, label) {
|
||||
scope[model + 'SearchTypeLabel'] = label;
|
||||
scope[model + 'SearchType'] = type;
|
||||
scope.search(model);
|
||||
}
|
||||
scope.search = function (iterator) {
|
||||
//scope[iterator + 'SearchSpin'] = true;
|
||||
Wait('start');
|
||||
scope[iterator + 'Loading'] = true;
|
||||
scope[iterator + 'HoldInput'] = true;
|
||||
|
||||
scope.startSearch = function(e,iterator) {
|
||||
// If use clicks enter while on input field, start the search
|
||||
if (e.keyCode == 13) {
|
||||
scope.search(iterator);
|
||||
}
|
||||
}
|
||||
if (scope[iterator + 'SearchValue']) {
|
||||
// User typed a value in input field
|
||||
scope[iterator + 'ShowStartBtn'] = false;
|
||||
}
|
||||
|
||||
scope.search = function(iterator) {
|
||||
//scope[iterator + 'SearchSpin'] = true;
|
||||
Wait('start');
|
||||
scope[iterator + 'Loading'] = true;
|
||||
scope[iterator + 'HoldInput'] = true;
|
||||
|
||||
if (scope[iterator + 'SearchValue']) {
|
||||
// User typed a value in input field
|
||||
scope[iterator + 'ShowStartBtn'] = false;
|
||||
}
|
||||
if (iterator === 'host') {
|
||||
if (scope.hostSearchField === 'has_active_failures') {
|
||||
if (scope.hostSearchSelectValue && scope.hostSearchSelectValue.value === 1) {
|
||||
scope.hostFailureFilter = true;
|
||||
} else {
|
||||
scope.hostFailureFilter = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iterator == 'host') {
|
||||
if (scope['hostSearchField'] == 'has_active_failures') {
|
||||
if (scope['hostSearchSelectValue'] && scope['hostSearchSelectValue'].value == 1) {
|
||||
scope['hostFailureFilter'] = true;
|
||||
}
|
||||
else {
|
||||
scope['hostFailureFilter'] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
var fld, key, set, url, sort_order;
|
||||
for (key in relatedSets) {
|
||||
if (relatedSets[key].iterator === iterator) {
|
||||
set = key;
|
||||
url = relatedSets[key].url;
|
||||
for (fld in form.related[key].fields) {
|
||||
if (form.related[key].fields[fld].key) {
|
||||
if (form.related[key].fields[fld].desc) {
|
||||
sort_order = '-' + fld;
|
||||
} else {
|
||||
sort_order = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var set, url, iterator, sort_order;
|
||||
for (var key in relatedSets) {
|
||||
if (relatedSets[key].iterator == iterator) {
|
||||
set = key;
|
||||
url = relatedSets[key].url;
|
||||
for (var fld in form.related[key].fields) {
|
||||
if (form.related[key].fields[fld].key) {
|
||||
if (form.related[key].fields[fld].desc) {
|
||||
sort_order = '-' + fld;
|
||||
}
|
||||
else {
|
||||
sort_order = fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sort_order = (scope[iterator + 'SortOrder'] == null) ? sort_order : scope[iterator + 'SortOrder'];
|
||||
sort_order = (scope[iterator + 'SortOrder'] === null) ? sort_order : scope[iterator + 'SortOrder'];
|
||||
f = form.related[set].fields[scope[iterator + 'SearchField']];
|
||||
if ((scope[iterator + 'SelectShow'] === false && !Empty(scope[iterator + 'SearchValue'])) ||
|
||||
(scope[iterator + 'SelectShow'] && scope[iterator + 'SearchSelectValue']) ||
|
||||
(f.searchType && f.searchType === 'gtzero')) {
|
||||
if (f.sourceModel) {
|
||||
// handle fields whose source is a related model e.g. inventories.organization
|
||||
scope[iterator + 'SearchParams'] = f.sourceModel + '__' + f.sourceField + '__';
|
||||
} else if (f.searchField) {
|
||||
scope[iterator + 'SearchParams'] = f.searchField + '__';
|
||||
} else {
|
||||
scope[iterator + 'SearchParams'] = scope[iterator + 'SearchField'] + '__';
|
||||
}
|
||||
|
||||
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') ) {
|
||||
if (f.sourceModel) {
|
||||
// handle fields whose source is a related model e.g. inventories.organization
|
||||
scope[iterator + 'SearchParams'] = f.sourceModel + '__' + f.sourceField + '__';
|
||||
}
|
||||
else if (f.searchField) {
|
||||
scope[iterator + 'SearchParams'] = f.searchField + '__';
|
||||
}
|
||||
else {
|
||||
scope[iterator + 'SearchParams'] = scope[iterator + 'SearchField'] + '__';
|
||||
}
|
||||
|
||||
if ( f.searchType && (f.searchType == 'int' || f.searchType == 'boolean' ) ) {
|
||||
scope[iterator + 'SearchParams'] += 'int=';
|
||||
}
|
||||
else if ( f.searchType && f.searchType == 'gtzero' ) {
|
||||
scope[iterator + 'SearchParams'] += 'gt=0';
|
||||
}
|
||||
else {
|
||||
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchType'] + '=';
|
||||
}
|
||||
|
||||
if ( f.searchType && (f.searchType == 'boolean' || f.searchType == 'select') ) {
|
||||
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchSelectValue'].value;
|
||||
}
|
||||
else if ( f.searchType == undefined || f.searchType == 'gtzero' ) {
|
||||
scope[iterator + 'SearchParams'] += 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 + '_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 });
|
||||
}
|
||||
if (f.searchType && (f.searchType === 'int' || f.searchType === 'boolean')) {
|
||||
scope[iterator + 'SearchParams'] += 'int=';
|
||||
} else if (f.searchType && f.searchType === 'gtzero') {
|
||||
scope[iterator + 'SearchParams'] += 'gt=0';
|
||||
} else {
|
||||
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchType'] + '=';
|
||||
}
|
||||
|
||||
if (f.searchType && (f.searchType === 'boolean' || f.searchType === 'select')) {
|
||||
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchSelectValue'].value;
|
||||
} else if (f.searchType === undefined || f.searchType === 'gtzero') {
|
||||
scope[iterator + 'SearchParams'] += encodeURI(scope[iterator + 'SearchValue']);
|
||||
}
|
||||
scope[iterator + 'SearchParams'] += (sort_order) ? '&order_by=' + encodeURI(sort_order) : '';
|
||||
} else {
|
||||
scope[iterator + 'SearchParams'] = (sort_order) ? 'order_by=' + encodeURI(sort_order) : '';
|
||||
}
|
||||
scope[iterator + '_page'] = 1;
|
||||
url += (url.match(/\/$/)) ? '?' : '&';
|
||||
url += scope[iterator + 'SearchParams'];
|
||||
url += (scope[iterator + '_page_size']) ? '&page_size=' + scope[iterator + '_page_size'] : "";
|
||||
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: url });
|
||||
};
|
||||
|
||||
|
||||
scope.sort = function(iterator, fld) {
|
||||
var sort_order;
|
||||
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') {
|
||||
var icon = $(this).find('i');
|
||||
icon.attr('class','icon-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');
|
||||
direction = '-';
|
||||
}
|
||||
else if (icon.hasClass('icon-sort-down')) {
|
||||
icon.removeClass('icon-sort-down');
|
||||
icon.addClass('icon-sort-up');
|
||||
}
|
||||
// reset sort icons back to 'icon-sort' on all columns
|
||||
// except the one clicked
|
||||
$('.' + iterator + ' .list-header').each(function () {
|
||||
if ($(this).attr('id') !== iterator + '-' + fld + '-header') {
|
||||
var icon = $(this).find('i');
|
||||
icon.attr('class', 'fa fa-sort');
|
||||
}
|
||||
});
|
||||
|
||||
// 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) {
|
||||
if (form.related[set].fields[fld].sourceModel) {
|
||||
sort_order = direction + form.related[set].fields[fld].sourceModel + '__' +
|
||||
form.related[set].fields[fld].sourceField;
|
||||
}
|
||||
else {
|
||||
sort_order = direction + fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
scope[iterator + 'SortOrder'] = sort_order;
|
||||
scope.search(iterator);
|
||||
}
|
||||
// Toggle the icon for the clicked column
|
||||
// and set the sort direction
|
||||
icon = $('#' + iterator + '-' + fld + '-header i');
|
||||
direction = '';
|
||||
if (icon.hasClass('fa-sort')) {
|
||||
icon.removeClass('fa-sort');
|
||||
icon.addClass('fa-sort-up');
|
||||
} else if (icon.hasClass('fa-sort-up')) {
|
||||
icon.removeClass('fa-sort-up');
|
||||
icon.addClass('fa-sort-down');
|
||||
direction = '-';
|
||||
} else if (icon.hasClass('fa-sort-down')) {
|
||||
icon.removeClass('fa-sort-down');
|
||||
icon.addClass('fa-sort-up');
|
||||
}
|
||||
|
||||
// Set the sorder order value and call the API to refresh the list with the new order
|
||||
for (set in form.related) {
|
||||
if (form.related[set].iterator === iterator) {
|
||||
if (form.related[set].fields[fld].sourceModel) {
|
||||
sort_order = direction + form.related[set].fields[fld].sourceModel + '__' +
|
||||
form.related[set].fields[fld].sourceField;
|
||||
} else {
|
||||
sort_order = direction + fld;
|
||||
}
|
||||
}
|
||||
}
|
||||
scope[iterator + 'SortOrder'] = sort_order;
|
||||
scope.search(iterator);
|
||||
};
|
||||
};
|
||||
}
|
||||
}]);
|
||||
]);
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
*
|
||||
* SearchHelper
|
||||
*
|
||||
* All the parts for controlling the search widget on
|
||||
* All the parts for controlling the search widget on
|
||||
* related collections.
|
||||
*
|
||||
* SearchInit({
|
||||
@ -11,26 +11,122 @@
|
||||
* set: <model name (i.e. organizations) used in ng-repeat>
|
||||
* url: <default api url used to load data>
|
||||
* list: <list object used by ListGenerator>
|
||||
* });
|
||||
* });
|
||||
*
|
||||
*/
|
||||
|
||||
'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) {
|
||||
|
||||
var scope = params.scope,
|
||||
set = params.set,
|
||||
defaultUrl = params.url,
|
||||
list = params.list,
|
||||
iterator = (params.iterator) ? params.iterator : list.iterator,
|
||||
setWidgets = (params.setWidgets === false) ? false : true,
|
||||
sort_order = params.sort_order || '',
|
||||
widgets, i, modifier, current_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,
|
||||
defaultUrl = params.url,
|
||||
list = params.list,
|
||||
iterator = (params.iterator) ? params.iterator : list.iterator,
|
||||
setWidgets = (params.setWidgets === false) ? false : true,
|
||||
sort_order = params.sort_order || '',
|
||||
widgets, i, modifier, current_params;
|
||||
|
||||
function setDefaults(widget) {
|
||||
// Set default values
|
||||
var f, fld, fka, modifier;
|
||||
modifier = (widget === undefined || widget === 1) ? '' : widget;
|
||||
scope[iterator + 'SearchField' + modifier] = '';
|
||||
scope[iterator + 'SearchFieldLabel' + modifier] = '';
|
||||
for (fld in list.fields) {
|
||||
if (list.fields[fld].searchWidget === undefined && widget === 1 ||
|
||||
list.fields[fld].searchWidget === widget) {
|
||||
if (list.fields[fld].key) {
|
||||
if (list.fields[fld].sourceModel) {
|
||||
fka = list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField;
|
||||
sort_order = (list.fields[fld].desc) ? '-' + fka : fka;
|
||||
} else {
|
||||
sort_order = (list.fields[fld].desc) ? '-' + fld : fld;
|
||||
}
|
||||
if (list.fields[fld].searchable === undefined || list.fields[fld].searchable === true) {
|
||||
scope[iterator + 'SearchField' + modifier] = fld;
|
||||
scope[iterator + 'SearchFieldLabel' + modifier] = list.fields[fld].label;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Empty(scope[iterator + 'SearchField' + modifier])) {
|
||||
// A field marked as key may not be 'searchable'. Find the first searchable field.
|
||||
for (fld in list.fields) {
|
||||
if (list.fields[fld].searchWidget === undefined && widget === 1 ||
|
||||
list.fields[fld].searchWidget === widget) {
|
||||
if (list.fields[fld].searchable === undefined || list.fields[fld].searchable === true) {
|
||||
scope[iterator + 'SearchField' + modifier] = fld;
|
||||
scope[iterator + 'SearchFieldLabel' + modifier] = list.fields[fld].label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scope[iterator + 'SearchType' + modifier] = 'icontains';
|
||||
scope[iterator + 'SearchTypeLabel' + modifier] = 'Contains';
|
||||
scope[iterator + 'SearchParams' + modifier] = '';
|
||||
scope[iterator + 'SearchValue' + modifier] = '';
|
||||
scope[iterator + 'SelectShow' + modifier] = false; // show/hide the Select
|
||||
scope[iterator + 'HideSearchType' + modifier] = false;
|
||||
scope[iterator + 'InputDisable' + modifier] = false;
|
||||
scope[iterator + 'ExtraParms' + modifier] = '';
|
||||
scope[iterator + 'ShowStartBtn' + modifier] = true;
|
||||
scope[iterator + 'HideAllStartBtn' + modifier] = false;
|
||||
|
||||
if (list.fields[scope[iterator + 'SearchField' + modifier]] &&
|
||||
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 {
|
||||
// Set to a string value in the list definition
|
||||
scope[iterator + 'SearchPlaceholder' + modifier] = list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder;
|
||||
}
|
||||
} else {
|
||||
// Default value
|
||||
scope[iterator + 'SearchPlaceholder' + modifier] = 'Search';
|
||||
}
|
||||
|
||||
scope[iterator + 'InputDisable' + modifier] =
|
||||
(list.fields[scope[iterator + 'SearchField' + modifier]] &&
|
||||
list.fields[scope[iterator + 'SearchField' + modifier]].searchObject === 'all') ? true : false;
|
||||
|
||||
f = scope[iterator + 'SearchField' + modifier];
|
||||
if (list.fields[f]) {
|
||||
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;
|
||||
}
|
||||
if (list.fields[f].searchType && list.fields[f].searchType === 'int') {
|
||||
scope[iterator + 'HideSearchType' + modifier] = true;
|
||||
}
|
||||
if (list.fields[f].searchType && list.fields[f].searchType === 'gtzero') {
|
||||
scope[iterator + 'InputHide' + modifier] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (setWidgets) {
|
||||
// Set default values for each search widget on the page
|
||||
widgets = (list.searchWidgets) ? list.searchWidgets : 1;
|
||||
for (i = 1; i <= widgets; i++) {
|
||||
modifier = (i === 1) ? '' : i;
|
||||
if ($('#search-widget-container' + modifier)) {
|
||||
setDefaults(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current_params = {
|
||||
set: set,
|
||||
defaultUrl: defaultUrl,
|
||||
@ -38,471 +134,351 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
|
||||
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;
|
||||
modifier = (widget === undefined || widget === 1) ? '' : widget;
|
||||
scope[iterator + 'SearchField' + modifier] = '';
|
||||
scope[iterator + 'SearchFieldLabel' + modifier] = '';
|
||||
for (fld in list.fields) {
|
||||
if (list.fields[fld].searchWidget === undefined && widget === 1 ||
|
||||
list.fields[fld].searchWidget === widget) {
|
||||
if (list.fields[fld].key) {
|
||||
if (list.fields[fld].sourceModel) {
|
||||
fka = list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField;
|
||||
sort_order = (list.fields[fld].desc) ? '-' + fka : fka;
|
||||
}
|
||||
else {
|
||||
sort_order = (list.fields[fld].desc) ? '-' + fld : fld;
|
||||
}
|
||||
if (list.fields[fld].searchable === undefined || list.fields[fld].searchable === true) {
|
||||
scope[iterator + 'SearchField' + modifier] = fld;
|
||||
scope[iterator + 'SearchFieldLabel' + modifier] = list.fields[fld].label;
|
||||
}
|
||||
break;
|
||||
Store('CurrentSearchParams', current_params); // Save in case Activity Stream widget needs to restore
|
||||
|
||||
|
||||
// Functions to handle search widget changes
|
||||
scope.setSearchField = function (iterator, fld, label, widget) {
|
||||
|
||||
var modifier = (widget === undefined || widget === 1) ? '' : widget;
|
||||
scope[iterator + 'SearchFieldLabel' + modifier] = label;
|
||||
scope[iterator + 'SearchField' + modifier] = fld;
|
||||
scope[iterator + 'SearchValue' + modifier] = '';
|
||||
scope[iterator + 'SelectShow' + modifier] = false;
|
||||
scope[iterator + 'HideSearchType' + modifier] = false;
|
||||
scope[iterator + 'InputHide' + modifier] = false;
|
||||
scope[iterator + 'SearchType' + modifier] = 'icontains';
|
||||
scope[iterator + 'InputDisable' + modifier] = (list.fields[fld].searchObject === 'all') ? true : false;
|
||||
scope[iterator + 'ShowStartBtn' + modifier] = true;
|
||||
|
||||
if (list.fields[scope[iterator + 'SearchField' + modifier]] &&
|
||||
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 {
|
||||
// Set to a string value in the list definition
|
||||
scope[iterator + 'SearchPlaceholder' + modifier] = list.fields[scope[iterator + 'SearchField' +
|
||||
modifier]].searchPlaceholder;
|
||||
}
|
||||
} else {
|
||||
// Default value
|
||||
scope[iterator + 'SearchPlaceholder' + modifier] = 'Search';
|
||||
}
|
||||
}
|
||||
|
||||
if (Empty(scope[iterator + 'SearchField' + modifier])) {
|
||||
// A field marked as key may not be 'searchable'. Find the first searchable field.
|
||||
for (fld in list.fields) {
|
||||
if (list.fields[fld].searchWidget === undefined && widget === 1 ||
|
||||
list.fields[fld].searchWidget === widget) {
|
||||
if (list.fields[fld].searchable === undefined || list.fields[fld].searchable === true) {
|
||||
scope[iterator + 'SearchField' + modifier] = fld;
|
||||
scope[iterator + 'SearchFieldLabel' + modifier] = list.fields[fld].label;
|
||||
break;
|
||||
}
|
||||
if (list.fields[fld].searchType && list.fields[fld].searchType === 'gtzero') {
|
||||
scope[iterator + "InputDisable" + modifier] = true;
|
||||
scope[iterator + 'ShowStartBtn' + modifier] = false;
|
||||
scope.search(iterator);
|
||||
} else if (list.fields[fld].searchSingleValue) {
|
||||
// Query a specific attribute for one specific value
|
||||
// searchSingleValue: true
|
||||
// searchType: 'boolean|int|etc.'
|
||||
// searchValue: < value to match for boolean use 'true'|'false' >
|
||||
scope[iterator + 'InputDisable' + modifier] = true;
|
||||
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 + 'SearchType' + modifier] = 'icontains';
|
||||
scope[iterator + 'SearchTypeLabel' + modifier] = 'Contains';
|
||||
scope[iterator + 'SearchParams' + modifier] = '';
|
||||
scope[iterator + 'SearchValue' + modifier] = '';
|
||||
scope[iterator + 'SelectShow' + modifier] = false; // show/hide the Select
|
||||
scope[iterator + 'HideSearchType' + modifier] = false;
|
||||
scope[iterator + 'InputDisable' + modifier] = false;
|
||||
scope[iterator + 'ExtraParms' + modifier] = '';
|
||||
scope[iterator + 'ShowStartBtn' + modifier] = true;
|
||||
scope[iterator + 'HideAllStartBtn' + modifier] = false;
|
||||
|
||||
if (list.fields[scope[iterator + 'SearchField' + modifier]] &&
|
||||
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 {
|
||||
// Set to a string value in the list definition
|
||||
scope[iterator + 'SearchPlaceholder' + modifier] = list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Default value
|
||||
scope[iterator + 'SearchPlaceholder' + modifier] = 'Search';
|
||||
}
|
||||
|
||||
scope[iterator + 'InputDisable' + modifier] =
|
||||
(list.fields[scope[iterator + 'SearchField' + modifier]] &&
|
||||
list.fields[scope[iterator + 'SearchField' + modifier]].searchObject === 'all') ? true : false;
|
||||
|
||||
f = scope[iterator + 'SearchField' + modifier];
|
||||
if (list.fields[f]) {
|
||||
if ( list.fields[f].searchType && (list.fields[f].searchType === 'boolean' ||
|
||||
list.fields[f].searchType === 'select') ) {
|
||||
scope[iterator + 'ShowStartBtn' + modifier] = false;
|
||||
} 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' ||
|
||||
list.fields[fld].searchType === 'select' || list.fields[fld].searchType === 'select_or')) {
|
||||
scope[iterator + 'SelectShow' + modifier] = true;
|
||||
scope[iterator + 'SearchSelectOpts' + modifier] = list.fields[f].searchOptions;
|
||||
scope[iterator + 'SearchSelectOpts' + modifier] = list.fields[fld].searchOptions;
|
||||
} 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') {
|
||||
scope[iterator + 'SearchType' + modifier] = 'isnull';
|
||||
scope[iterator + 'InputDisable' + modifier] = true;
|
||||
scope[iterator + 'SearchValue' + modifier] = 'true';
|
||||
scope[iterator + 'ShowStartBtn' + modifier] = false;
|
||||
}
|
||||
if (list.fields[f].searchType && list.fields[f].searchType === 'int') {
|
||||
scope[iterator + 'HideSearchType' + modifier] = true;
|
||||
}
|
||||
if (list.fields[f].searchType && list.fields[f].searchType === 'gtzero') {
|
||||
scope[iterator + 'InputHide' + modifier] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (setWidgets) {
|
||||
// Set default values for each search widget on the page
|
||||
widgets = (list.searchWidgets) ? list.searchWidgets : 1;
|
||||
for (i=1; i <= widgets; i++) {
|
||||
modifier = (i === 1) ? '' : i;
|
||||
if ( $('#search-widget-container' + modifier) ) {
|
||||
|
||||
scope.search(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++) {
|
||||
// Clear each search widget
|
||||
setDefaults(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
// Functions to handle search widget changes
|
||||
scope.setSearchField = function(iterator, fld, label, widget) {
|
||||
|
||||
var modifier = (widget === undefined || widget === 1) ? '' : widget;
|
||||
scope[iterator + 'SearchFieldLabel' + modifier] = label;
|
||||
scope[iterator + 'SearchField' + modifier] = fld;
|
||||
scope[iterator + 'SearchValue' + modifier] = '';
|
||||
scope[iterator + 'SelectShow' + modifier] = false;
|
||||
scope[iterator + 'HideSearchType' + modifier] = false;
|
||||
scope[iterator + 'InputHide' + modifier] = false;
|
||||
scope[iterator + 'SearchType' + modifier] = 'icontains';
|
||||
scope[iterator + 'InputDisable' + modifier] = (list.fields[fld].searchObject === 'all') ? true : false;
|
||||
scope[iterator + 'ShowStartBtn' + modifier] = true;
|
||||
|
||||
if (list.fields[scope[iterator + 'SearchField' + modifier]] &&
|
||||
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 {
|
||||
// Set to a string value in the list definition
|
||||
scope[iterator + 'SearchPlaceholder' + modifier] = list.fields[scope[iterator + 'SearchField' + modifier]].searchPlaceholder;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Default value
|
||||
scope[iterator + 'SearchPlaceholder' + modifier] = 'Search';
|
||||
}
|
||||
|
||||
if (list.fields[fld].searchType && list.fields[fld].searchType === 'gtzero') {
|
||||
scope[iterator + "InputDisable" + modifier] = true;
|
||||
scope[iterator + 'ShowStartBtn' + modifier] = false;
|
||||
// Force removal of search keys from the URL
|
||||
window.location = '/#' + $location.path();
|
||||
scope.search(iterator);
|
||||
}
|
||||
else if (list.fields[fld].searchSingleValue){
|
||||
// Query a specific attribute for one specific value
|
||||
// searchSingleValue: true
|
||||
// searchType: 'boolean|int|etc.'
|
||||
// searchValue: < value to match for boolean use 'true'|'false' >
|
||||
scope[iterator + 'InputDisable' + modifier] = true;
|
||||
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 + 'ShowStartBtn' + modifier] = false;
|
||||
}
|
||||
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' ||
|
||||
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') {
|
||||
//scope[iterator + 'HideSearchType' + modifier] = true;
|
||||
scope[iterator + 'SearchType' + modifier] = 'int';
|
||||
}
|
||||
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';
|
||||
scope[iterator + 'ShowStartBtn' + modifier] = false;
|
||||
}
|
||||
|
||||
scope.search(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++) {
|
||||
// Clear each search widget
|
||||
setDefaults(i);
|
||||
if (scope.removeDoSearch) {
|
||||
scope.removeDoSearch();
|
||||
}
|
||||
// Force removal of search keys from the URL
|
||||
window.location = '/#' + $location.path();
|
||||
scope.search(iterator);
|
||||
};
|
||||
|
||||
if (scope.removeDoSearch) {
|
||||
scope.removeDoSearch();
|
||||
}
|
||||
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;
|
||||
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;
|
||||
|
||||
//finalize and execute the query
|
||||
scope[iterator + 'Page'] = (page) ? parseInt(page) - 1 : 0;
|
||||
if (scope[iterator + 'SearchParams']) {
|
||||
if (/\/$/.test(url)) {
|
||||
url += '?' + scope[iterator + 'SearchParams'];
|
||||
//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 {
|
||||
url += '&' + scope[iterator + 'SearchParams'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
url += '&' + scope[iterator + 'SearchParams'];
|
||||
}
|
||||
}
|
||||
connect = (/\/$/.test(url)) ? '?' : '&';
|
||||
url += (scope[iterator + '_page_size']) ? connect + 'page_size=' + scope[iterator + '_page_size'] : "";
|
||||
if (page) {
|
||||
connect = (/\/$/.test(url)) ? '?' : '&';
|
||||
url += connect + 'page=' + page;
|
||||
}
|
||||
if (scope[iterator + 'ExtraParms']) {
|
||||
connect = (/\/$/.test(url)) ? '?' : '&';
|
||||
url += connect + scope[iterator + 'ExtraParms'];
|
||||
}
|
||||
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) {
|
||||
//
|
||||
// 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).
|
||||
//
|
||||
Wait('start');
|
||||
scope[iterator + 'SearchParams'] = '';
|
||||
var i, modifier,
|
||||
widgets = (list.searchWidgets) ? list.searchWidgets : 1;
|
||||
|
||||
for (i=1; i <= widgets; i++) {
|
||||
modifier = (i === 1) ? '' : i;
|
||||
if ( $('#search-widget-container' + modifier) ) {
|
||||
if (list.fields[scope[iterator + 'SearchField' + modifier]] &&
|
||||
list.fields[scope[iterator + 'SearchField' + modifier]].searchObject) {
|
||||
// Search field of object type
|
||||
if (list.fields[scope[iterator + 'SearchField' + modifier]].searchObject !== 'all') {
|
||||
// An object type is selected
|
||||
scope[iterator + 'HideAllStartBtn' + modifier] = false;
|
||||
if (scope[iterator + 'SearchValue' + modifier]) {
|
||||
// A search value was entered
|
||||
scope[iterator + 'ShowStartBtn' + modifier] = false;
|
||||
if (list.fields[scope[iterator + 'SearchField' + modifier]].searchOnID) {
|
||||
scope[iterator + 'SearchParams'] += '&' +
|
||||
list.fields[scope[iterator + 'SearchField' + modifier]].searchObject +
|
||||
'__id=' + scope[iterator + 'SearchValue' + modifier];
|
||||
}
|
||||
else {
|
||||
scope[iterator + 'SearchParams'] += '&' +
|
||||
list.fields[scope[iterator + 'SearchField' + modifier]].searchObject +
|
||||
'__name__icontains=' +
|
||||
scope[iterator + 'SearchValue' + modifier];
|
||||
}
|
||||
}
|
||||
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 {
|
||||
// Object Type set to All
|
||||
scope[iterator + 'HideAllStartBtn' + modifier] = true;
|
||||
}
|
||||
}
|
||||
url += (scope[iterator + '_page_size']) ? connect + 'page_size=' + scope[iterator + '_page_size'] : "";
|
||||
if (page) {
|
||||
connect = (/\/$/.test(url)) ? '?' : '&';
|
||||
url += connect + 'page=' + page;
|
||||
}
|
||||
}
|
||||
scope.$emit('prepareSearch2', iterator, page, load, spin);
|
||||
});
|
||||
|
||||
if (scope.removePrepareSearch2) {
|
||||
scope.removePrepareSearch2();
|
||||
}
|
||||
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++) {
|
||||
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) {
|
||||
|
||||
// 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 {
|
||||
scope[iterator + 'ShowStartBtn' + modifier] = true;
|
||||
}
|
||||
|
||||
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') ) {
|
||||
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) {
|
||||
// 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') &&
|
||||
(scope[iterator + 'SearchSelectValue' + modifier].value === '' ||
|
||||
scope[iterator + 'SearchSelectValue' + modifier].value === null) ) {
|
||||
scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchField' + modifier] + '__';
|
||||
}
|
||||
else {
|
||||
scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchField' + modifier] + '__';
|
||||
}
|
||||
|
||||
if ( list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
|
||||
(list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'int' ||
|
||||
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' ) {
|
||||
scope[iterator + 'SearchParams'] += 'gt=0';
|
||||
}
|
||||
else if ( (list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'select') &&
|
||||
(scope[iterator + 'SearchSelectValue' + modifier].value === '' ||
|
||||
scope[iterator + 'SearchSelectValue' + modifier].value === null) ) {
|
||||
scope[iterator + 'SearchParams'] += 'iexact=';
|
||||
}
|
||||
else {
|
||||
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchType' + modifier] + '=';
|
||||
}
|
||||
|
||||
if ( list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
|
||||
(list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'boolean' ||
|
||||
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) ||
|
||||
(list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
|
||||
list.fields[scope[iterator + 'SearchField' + modifier]].searchType !== 'or' &&
|
||||
list.fields[scope[iterator + 'SearchField' + modifier]].searchType !== 'gtzero') ) {
|
||||
scope[iterator + 'SearchParams'] += encodeURI(scope[iterator + 'SearchValue' + modifier]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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';
|
||||
}
|
||||
|
||||
if (sort_order) {
|
||||
scope[iterator + 'SearchParams'] += (scope[iterator + 'SearchParams']) ? '&' : '';
|
||||
scope[iterator + 'SearchParams'] += 'order_by=' + encodeURI(sort_order);
|
||||
}
|
||||
|
||||
scope.$emit('doSearch', iterator, page, load, spin);
|
||||
});
|
||||
|
||||
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) {
|
||||
// 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.
|
||||
// Load optional -set to false if loading message not desired
|
||||
load = (load === undefined) ? true : false;
|
||||
if (load) {
|
||||
scope[set] = [];
|
||||
}
|
||||
scope.$emit('prepareSearch', iterator, page, load);
|
||||
};
|
||||
|
||||
|
||||
scope.sort = function(fld) {
|
||||
// reset sort icons back to 'icon-sort' on all columns
|
||||
// except the one clicked
|
||||
$('.list-header').each(function() {
|
||||
if ($(this).attr('id') !== fld + '-header') {
|
||||
var icon = $(this).find('i');
|
||||
icon.attr('class','fa fa-sort');
|
||||
if (scope[iterator + 'ExtraParms']) {
|
||||
connect = (/\/$/.test(url)) ? '?' : '&';
|
||||
url += connect + scope[iterator + 'ExtraParms'];
|
||||
}
|
||||
url = url.replace(/\&\&/, '&');
|
||||
Refresh({
|
||||
scope: scope,
|
||||
set: set,
|
||||
iterator: iterator,
|
||||
url: url
|
||||
});
|
||||
});
|
||||
|
||||
// Toggle the icon for the clicked column
|
||||
// and set the sort direction
|
||||
var icon = $('#' + fld + '-header i'),
|
||||
direction = '';
|
||||
if (icon.hasClass('fa-sort')) {
|
||||
icon.removeClass('fa-sort');
|
||||
icon.addClass('fa-sort-up');
|
||||
}
|
||||
else if (icon.hasClass('fa-sort-up')) {
|
||||
icon.removeClass('fa-sort-up');
|
||||
icon.addClass('fa-sort-down');
|
||||
direction = '-';
|
||||
}
|
||||
else if (icon.hasClass('fa-sort-down')) {
|
||||
icon.removeClass('fa-sort-down');
|
||||
icon.addClass('fa-sort-up');
|
||||
}
|
||||
|
||||
// Set the sorder order value and call the API to refresh the list with the new order
|
||||
if (list.fields[fld].searchField) {
|
||||
sort_order = direction + list.fields[fld].searchField;
|
||||
|
||||
if (scope.removePrepareSearch) {
|
||||
scope.removePrepareSearch();
|
||||
}
|
||||
else if (list.fields[fld].sortField) {
|
||||
sort_order = direction + list.fields[fld].sortField;
|
||||
}
|
||||
else {
|
||||
if (list.fields[fld].sourceModel) {
|
||||
sort_order = direction + list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField;
|
||||
}
|
||||
else {
|
||||
sort_order = direction + fld;
|
||||
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).
|
||||
//
|
||||
Wait('start');
|
||||
scope[iterator + 'SearchParams'] = '';
|
||||
var i, modifier,
|
||||
widgets = (list.searchWidgets) ? list.searchWidgets : 1;
|
||||
|
||||
for (i = 1; i <= widgets; i++) {
|
||||
modifier = (i === 1) ? '' : i;
|
||||
if ($('#search-widget-container' + modifier)) {
|
||||
if (list.fields[scope[iterator + 'SearchField' + modifier]] &&
|
||||
list.fields[scope[iterator + 'SearchField' + modifier]].searchObject) {
|
||||
// Search field of object type
|
||||
if (list.fields[scope[iterator + 'SearchField' + modifier]].searchObject !== 'all') {
|
||||
// An object type is selected
|
||||
scope[iterator + 'HideAllStartBtn' + modifier] = false;
|
||||
if (scope[iterator + 'SearchValue' + modifier]) {
|
||||
// A search value was entered
|
||||
scope[iterator + 'ShowStartBtn' + modifier] = false;
|
||||
if (list.fields[scope[iterator + 'SearchField' + modifier]].searchOnID) {
|
||||
scope[iterator + 'SearchParams'] += '&' +
|
||||
list.fields[scope[iterator + 'SearchField' + modifier]].searchObject +
|
||||
'__id=' + scope[iterator + 'SearchValue' + modifier];
|
||||
} else {
|
||||
scope[iterator + 'SearchParams'] += '&' +
|
||||
list.fields[scope[iterator + 'SearchField' + modifier]].searchObject +
|
||||
'__name__icontains=' +
|
||||
scope[iterator + 'SearchValue' + modifier];
|
||||
}
|
||||
} 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 {
|
||||
// Object Type set to All
|
||||
scope[iterator + 'HideAllStartBtn' + modifier] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope.$emit('prepareSearch2', iterator, page, load, spin);
|
||||
});
|
||||
|
||||
if (scope.removePrepareSearch2) {
|
||||
scope.removePrepareSearch2();
|
||||
}
|
||||
scope.search(list.iterator);
|
||||
};
|
||||
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;
|
||||
|
||||
// Call after modal dialogs to remove any lingering callbacks
|
||||
scope.searchCleanup = function() {
|
||||
scope.removeDoSearch();
|
||||
scope.removePrepareSearch();
|
||||
scope.removePrepareSearch2();
|
||||
};
|
||||
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) {
|
||||
|
||||
};
|
||||
}]);
|
||||
// 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 {
|
||||
scope[iterator + 'ShowStartBtn' + modifier] = true;
|
||||
}
|
||||
|
||||
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')) {
|
||||
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) {
|
||||
// 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') &&
|
||||
(scope[iterator + 'SearchSelectValue' + modifier].value === '' ||
|
||||
scope[iterator + 'SearchSelectValue' + modifier].value === null)) {
|
||||
scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchField' + modifier] + '__';
|
||||
} else {
|
||||
scope[iterator + 'SearchParams'] += '&' + scope[iterator + 'SearchField' + modifier] + '__';
|
||||
}
|
||||
|
||||
if (list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
|
||||
(list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'int' ||
|
||||
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') {
|
||||
scope[iterator + 'SearchParams'] += 'gt=0';
|
||||
} else if ((list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'select') &&
|
||||
(scope[iterator + 'SearchSelectValue' + modifier].value === '' ||
|
||||
scope[iterator + 'SearchSelectValue' + modifier].value === null)) {
|
||||
scope[iterator + 'SearchParams'] += 'iexact=';
|
||||
} else {
|
||||
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchType' + modifier] + '=';
|
||||
}
|
||||
|
||||
if (list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
|
||||
(list.fields[scope[iterator + 'SearchField' + modifier]].searchType === 'boolean' ||
|
||||
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) ||
|
||||
(list.fields[scope[iterator + 'SearchField' + modifier]].searchType &&
|
||||
list.fields[scope[iterator + 'SearchField' + modifier]].searchType !== 'or' &&
|
||||
list.fields[scope[iterator + 'SearchField' + modifier]].searchType !== 'gtzero')) {
|
||||
scope[iterator + 'SearchParams'] += encodeURI(scope[iterator + 'SearchValue' + modifier]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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';
|
||||
}
|
||||
|
||||
if (sort_order) {
|
||||
scope[iterator + 'SearchParams'] += (scope[iterator + 'SearchParams']) ? '&' : '';
|
||||
scope[iterator + 'SearchParams'] += 'order_by=' + encodeURI(sort_order);
|
||||
}
|
||||
|
||||
scope.$emit('doSearch', iterator, page, load, spin);
|
||||
});
|
||||
|
||||
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) {
|
||||
// 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.
|
||||
// Load optional -set to false if loading message not desired
|
||||
load = (load === undefined) ? true : false;
|
||||
if (load) {
|
||||
scope[set] = [];
|
||||
}
|
||||
scope.$emit('prepareSearch', iterator, page, load);
|
||||
};
|
||||
|
||||
|
||||
scope.sort = function (fld) {
|
||||
// reset sort icons back to 'icon-sort' on all columns
|
||||
// except the one clicked
|
||||
$('.list-header').each(function () {
|
||||
if ($(this).attr('id') !== fld + '-header') {
|
||||
var icon = $(this).find('i');
|
||||
icon.attr('class', 'fa fa-sort');
|
||||
}
|
||||
});
|
||||
|
||||
// Toggle the icon for the clicked column
|
||||
// and set the sort direction
|
||||
var icon = $('#' + fld + '-header i'),
|
||||
direction = '';
|
||||
if (icon.hasClass('fa-sort')) {
|
||||
icon.removeClass('fa-sort');
|
||||
icon.addClass('fa-sort-up');
|
||||
} else if (icon.hasClass('fa-sort-up')) {
|
||||
icon.removeClass('fa-sort-up');
|
||||
icon.addClass('fa-sort-down');
|
||||
direction = '-';
|
||||
} else if (icon.hasClass('fa-sort-down')) {
|
||||
icon.removeClass('fa-sort-down');
|
||||
icon.addClass('fa-sort-up');
|
||||
}
|
||||
|
||||
// Set the sorder order value and call the API to refresh the list with the new order
|
||||
if (list.fields[fld].searchField) {
|
||||
sort_order = direction + list.fields[fld].searchField;
|
||||
} else if (list.fields[fld].sortField) {
|
||||
sort_order = direction + list.fields[fld].sortField;
|
||||
} else {
|
||||
if (list.fields[fld].sourceModel) {
|
||||
sort_order = direction + list.fields[fld].sourceModel + '__' + list.fields[fld].sourceField;
|
||||
} else {
|
||||
sort_order = direction + fld;
|
||||
}
|
||||
}
|
||||
scope.search(list.iterator);
|
||||
};
|
||||
|
||||
// Call after modal dialogs to remove any lingering callbacks
|
||||
scope.searchCleanup = function () {
|
||||
scope.removeDoSearch();
|
||||
scope.removePrepareSearch();
|
||||
scope.removePrepareSearch2();
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
]);
|
||||
@ -2,106 +2,126 @@
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* TeamHelper
|
||||
* Routines shared amongst the team controllers
|
||||
* 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) {
|
||||
|
||||
var scope = params.scope;
|
||||
var set = params.set;
|
||||
var iterator = params.iterator;
|
||||
|
||||
// Listeners to perform lookups after main inventory list loads
|
||||
'use strict';
|
||||
|
||||
scope.$on('TeamResultFound', function(e, results, lookup_results) {
|
||||
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) {
|
||||
results[i][property] = lookup_results[j].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
scope[iterator + 'SearchSpin'] = false;
|
||||
scope[set] = results;
|
||||
}
|
||||
});
|
||||
angular.module('TeamHelper', ['RestServices', 'Utilities', 'OrganizationListDefinition', 'SearchHelper',
|
||||
'PaginationHelpers', 'ListGenerator'
|
||||
])
|
||||
.factory('SetTeamListeners', ['Alert', 'Rest',
|
||||
function (Alert, Rest) {
|
||||
return function (params) {
|
||||
|
||||
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 = [];
|
||||
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
Rest.setUrl('/api/v1/organizations/' + results[i].organization + '/');
|
||||
Rest.get()
|
||||
.success( function( data, status, headers, config) {
|
||||
lookup_results.push({ id: data.id, value: data.name });
|
||||
scope.$emit('TeamResultFound', results, lookup_results);
|
||||
})
|
||||
.error( function( data, status, headers, config) {
|
||||
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) {
|
||||
|
||||
var scope = params.scope;
|
||||
var scope = params.scope,
|
||||
set = params.set,
|
||||
iterator = params.iterator;
|
||||
|
||||
// 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/';
|
||||
// Listeners to perform lookups after main inventory list loads
|
||||
|
||||
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") {
|
||||
found = true;
|
||||
scope['organization'] = listScope[list.name][i].id;
|
||||
scope['organization_name'] = listScope[list.name][i].name;
|
||||
scope['team_form'].$setDirty();
|
||||
listGenerator.hide();
|
||||
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 (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;
|
||||
}
|
||||
}
|
||||
}
|
||||
scope[iterator + 'SearchSpin'] = false;
|
||||
scope[set] = results;
|
||||
}
|
||||
}
|
||||
if (found == false) {
|
||||
Alert('No Selection', 'Click on a row to select an Organization before clicking the Select button.');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
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++) {
|
||||
listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] = "";
|
||||
}
|
||||
}
|
||||
if (id != null && id != undefined) {
|
||||
listScope[list.iterator + "_" + id + "_class"] = "success";
|
||||
}
|
||||
}
|
||||
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.
|
||||
|
||||
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);
|
||||
}
|
||||
var i, lookup_results = [], url;
|
||||
|
||||
function getOrganization(url) {
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
lookup_results.push({ id: data.id, value: data.name });
|
||||
scope.$emit('TeamResultFound', results, lookup_results);
|
||||
})
|
||||
.error(function () {
|
||||
lookup_results.push({ id: 'error' });
|
||||
scope.$emit('TeamResultFound', results, lookup_results);
|
||||
});
|
||||
}
|
||||
|
||||
for (i = 0; i < results.length; i++) {
|
||||
url = '/api/v1/organizations/' + results[i].organization + '/';
|
||||
getOrganization(url);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
}]);
|
||||
])
|
||||
|
||||
.factory('TeamLookUpOrganizationInit', ['Alert', 'Rest', 'OrganizationList', 'GenerateList', 'SearchInit', 'PaginateInit',
|
||||
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,
|
||||
listGenerator = GenerateList,
|
||||
listScope = listGenerator.inject(list, { mode: 'lookup', hdr: 'Select Organization' }),
|
||||
defaultUrl = '/api/v1/organizations/';
|
||||
|
||||
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();
|
||||
listGenerator.hide();
|
||||
}
|
||||
}
|
||||
if (found === false) {
|
||||
Alert('No Selection', 'Click on a row to select an Organization before clicking the Select button.');
|
||||
}
|
||||
};
|
||||
|
||||
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++) {
|
||||
listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] = "";
|
||||
}
|
||||
}
|
||||
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'
|
||||
});
|
||||
scope.search(list.iterator);
|
||||
listScope.toggle_organization(scope.organization);
|
||||
};
|
||||
};
|
||||
}
|
||||
]);
|
||||
@ -1,41 +1,41 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Admins.js
|
||||
* Admins.js
|
||||
* List view object for Admins data model.
|
||||
*
|
||||
* @dict
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('AdminListDefinition', [])
|
||||
.value(
|
||||
'AdminList', {
|
||||
|
||||
.value('AdminList', {
|
||||
|
||||
name: 'admins',
|
||||
iterator: 'admin',
|
||||
selectTitle: 'Add Administrators',
|
||||
editTitle: 'Admins',
|
||||
selectInstructions: '<p>Select existing users by clicking each user or checking the related checkbox. When finished, click the blue ' +
|
||||
'<em>Select</em> button, located bottom right.</p>',
|
||||
'<em>Select</em> button, located bottom right.</p>',
|
||||
base: 'users',
|
||||
index: true,
|
||||
hover: true,
|
||||
|
||||
hover: true,
|
||||
|
||||
fields: {
|
||||
username: {
|
||||
key: true,
|
||||
label: 'Username'
|
||||
},
|
||||
first_name: {
|
||||
},
|
||||
first_name: {
|
||||
label: 'First Name'
|
||||
},
|
||||
last_name: {
|
||||
},
|
||||
last_name: {
|
||||
label: 'Last Name'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
actions: {},
|
||||
|
||||
fieldActions: {}
|
||||
});
|
||||
@ -1,15 +1,17 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* CloudCredentials.js
|
||||
* CloudCredentials.js
|
||||
* List view object for Credential data model.
|
||||
*
|
||||
* @dict
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('CloudCredentialsListDefinition', [])
|
||||
.value(
|
||||
'CloudCredentialList', {
|
||||
|
||||
.value('CloudCredentialList', {
|
||||
|
||||
name: 'cloudcredentials',
|
||||
iterator: 'cloudcredential',
|
||||
selectTitle: 'Add Cloud Credentials',
|
||||
@ -18,58 +20,58 @@ angular.module('CloudCredentialsListDefinition', [])
|
||||
'<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,
|
||||
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
excludeModal: false
|
||||
},
|
||||
},
|
||||
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: {
|
||||
add: {
|
||||
mode: 'all', // One of: edit, select, all
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addCredential()',
|
||||
"class": 'btn-sm',
|
||||
awToolTip: 'Create a new credential'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "editCredential(\{\{ credential.id \}\})",
|
||||
ngClick: "editCredential(credential.id)",
|
||||
icon: 'fa-edit',
|
||||
label: 'Edit',
|
||||
"class": 'btn-sm',
|
||||
awToolTip: 'Edit credential',
|
||||
dataPlacement: 'top'
|
||||
},
|
||||
},
|
||||
|
||||
"delete": {
|
||||
ngClick: "deleteCredential(\{\{ credential.id \}\},'\{\{ credential.name \}\}')",
|
||||
ngClick: "deleteCredential(credential.id, credential.name)",
|
||||
icon: 'fa-trash-o',
|
||||
label: 'Delete',
|
||||
"class": 'btn-sm',
|
||||
awToolTip: 'Delete credential',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1,88 +1,75 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Credentials.js
|
||||
* Credentials.js
|
||||
* List view object for Credential data model.
|
||||
*
|
||||
* @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,
|
||||
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
excludeModal: false
|
||||
},
|
||||
},
|
||||
kind: {
|
||||
label: 'Type',
|
||||
searchType: 'select',
|
||||
searchOptions: [], // will be set by Options call to credentials resource
|
||||
searchOptions: [], // will be set by Options call to credentials resource
|
||||
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: {
|
||||
add: {
|
||||
mode: 'all', // One of: edit, select, all
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addCredential()',
|
||||
awToolTip: 'Create a new credential'
|
||||
},
|
||||
},
|
||||
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',
|
||||
awToolTip: 'Edit credential',
|
||||
dataPlacement: 'top'
|
||||
},
|
||||
},
|
||||
|
||||
"delete": {
|
||||
ngClick: "deleteCredential(\{\{ credential.id \}\},'\{\{ credential.name \}\}')",
|
||||
ngClick: "deleteCredential(credential.id, credential.name)",
|
||||
icon: 'fa-trash',
|
||||
label: 'Delete',
|
||||
"class": 'btn-sm',
|
||||
awToolTip: 'Delete credential',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1,60 +1,62 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Groups.js
|
||||
* Groups.js
|
||||
* List view object for Group data model.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('GroupListDefinition', [])
|
||||
.value(
|
||||
'GroupList', {
|
||||
|
||||
.value('GroupList', {
|
||||
|
||||
name: 'groups',
|
||||
iterator: 'group',
|
||||
selectTitle: 'Copy Groups',
|
||||
editTitle: 'Groups',
|
||||
index: true,
|
||||
well: false,
|
||||
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
help: {
|
||||
help: {
|
||||
awPopOver: "Choose groups by clicking on each group you wish to add. Click the <em>Select</em> button to add the groups to " +
|
||||
"the selected inventory group.",
|
||||
dataContainer: '#form-modal .modal-content',
|
||||
mode: 'all',
|
||||
awToolTip: 'Click for help',
|
||||
dataTitle: 'Adding Groups'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
label: 'Edit',
|
||||
ngClick: "editGroup(\{\{ group.id \}\})",
|
||||
ngClick: "editGroup(group.id)",
|
||||
icon: 'icon-edit',
|
||||
"class": 'btn-xs',
|
||||
awToolTip: 'Edit group',
|
||||
dataPlacement: 'top'
|
||||
},
|
||||
},
|
||||
|
||||
"delete": {
|
||||
label: 'Delete',
|
||||
ngClick: "deleteGroup(\{\{ group.id \}\},'\{\{ group.name \}\}')",
|
||||
ngClick: "deleteGroup(group.id, group.name)",
|
||||
icon: 'icon-trash',
|
||||
"class": 'btn-xs',
|
||||
awToolTip: 'Delete group',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1,16 +1,18 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* HomeGroups.js
|
||||
* HomeGroups.js
|
||||
*
|
||||
* List view object for Group data model. Used
|
||||
* on the home tab.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('HomeGroupListDefinition', [])
|
||||
.value(
|
||||
'HomeGroupList', {
|
||||
|
||||
.value('HomeGroupList', {
|
||||
|
||||
name: 'home_groups',
|
||||
iterator: 'group',
|
||||
editTitle: 'Groups',
|
||||
@ -24,40 +26,46 @@ angular.module('HomeGroupListDefinition', [])
|
||||
label: 'Group',
|
||||
ngClick: "editGroup(group.id, group.inventory)",
|
||||
columnClass: 'col-lg-4 col-md3 col-sm-3 col-xs-6 ellipsis'
|
||||
},
|
||||
},
|
||||
inventory_name: {
|
||||
label: 'Inventory',
|
||||
label: 'Inventory',
|
||||
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
|
||||
},
|
||||
},
|
||||
has_external_source: {
|
||||
label: 'Has external source?',
|
||||
searchType: 'in',
|
||||
label: 'Has external source?',
|
||||
searchType: 'in',
|
||||
searchValue: 'ec2,rax',
|
||||
searchOnly: true,
|
||||
sourceModel: 'inventory_source',
|
||||
sourceField: 'source'
|
||||
},
|
||||
},
|
||||
has_active_failures: {
|
||||
label: 'Has failed hosts?',
|
||||
searchSingleValue: true,
|
||||
searchType: 'boolean',
|
||||
searchValue: 'true',
|
||||
searchOnly: true
|
||||
},
|
||||
},
|
||||
last_update_failed: {
|
||||
label: 'Update failed?',
|
||||
searchType: 'select',
|
||||
@ -66,66 +74,66 @@ angular.module('HomeGroupListDefinition', [])
|
||||
searchOnly: true,
|
||||
sourceModel: 'inventory_source',
|
||||
sourceField: 'status'
|
||||
},
|
||||
},
|
||||
id: {
|
||||
label: 'ID',
|
||||
searchOnly: true
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
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"
|
||||
},
|
||||
},
|
||||
failed_hosts: {
|
||||
mode: 'all',
|
||||
awToolTip: "{{ group.hosts_status_tip }}",
|
||||
dataPlacement: "top",
|
||||
ngHref: "/#/inventories/{{ group.inventory }}/",
|
||||
iconClass: "{{ 'fa icon-failures-' + group.hosts_status_class }}"
|
||||
},
|
||||
},
|
||||
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"
|
||||
},
|
||||
},
|
||||
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')",
|
||||
dataPlacement: "top"
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
label: 'Edit',
|
||||
mode: 'all',
|
||||
ngClick: "editGroup(group.id)",
|
||||
awToolTip: 'Edit group',
|
||||
dataPlacement: "top"
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
refresh: {
|
||||
mode: 'all',
|
||||
awToolTip: "Refresh the page",
|
||||
ngClick: "refresh()"
|
||||
},
|
||||
},
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'all'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
@ -1,16 +1,18 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* HomeHosts.js
|
||||
* HomeHosts.js
|
||||
*
|
||||
* List view object for Hosts data model. Used
|
||||
* on the home tab.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('HomeHostListDefinition', [])
|
||||
.value(
|
||||
'HomeHostList', {
|
||||
|
||||
.value('HomeHostList', {
|
||||
|
||||
name: 'hosts',
|
||||
iterator: 'host',
|
||||
selectTitle: 'Add Existing Hosts',
|
||||
@ -24,41 +26,41 @@ 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',
|
||||
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?',
|
||||
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
|
||||
},
|
||||
},
|
||||
id: {
|
||||
label: 'ID',
|
||||
searchOnly: true
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
enabled_flag: {
|
||||
@ -68,7 +70,7 @@ angular.module('HomeHostListDefinition', [])
|
||||
awToolTip: "{{ host.enabledToolTip }}",
|
||||
dataTipWatch: "host.enabledToolTip",
|
||||
ngClick: "toggleHostEnabled(host.id, host.has_inventory_sources)"
|
||||
},
|
||||
},
|
||||
active_failures: {
|
||||
//label: 'Job Status',
|
||||
//ngHref: "\{\{'/#/hosts/' + host.id + '/job_host_summaries/?inventory=' + inventory_id \}\}",
|
||||
@ -78,22 +80,22 @@ angular.module('HomeHostListDefinition', [])
|
||||
awTipPlacement: 'top',
|
||||
dataPlacement: 'left',
|
||||
iconClass: "{{ 'fa icon-failures-' + host.has_active_failures }}"
|
||||
},
|
||||
},
|
||||
edit: {
|
||||
label: 'Edit',
|
||||
ngClick: "editHost(host.id)",
|
||||
icon: 'icon-edit',
|
||||
awToolTip: 'Edit host',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'all'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
@ -1,15 +1,17 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Hosts.js
|
||||
* Hosts.js
|
||||
* List view object for Users data model.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('HostListDefinition', [])
|
||||
.value(
|
||||
'HostList', {
|
||||
|
||||
.value('HostList', {
|
||||
|
||||
name: 'hosts',
|
||||
iterator: 'host',
|
||||
selectTitle: 'Add Existing Hosts',
|
||||
@ -21,13 +23,13 @@ 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'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
help: {
|
||||
awPopOver: "Select hosts by clicking on each host you wish to add. Add the selected hosts to the group by clicking the <em>Select</em> button.",
|
||||
@ -35,26 +37,26 @@ angular.module('HostListDefinition', [])
|
||||
mode: 'all',
|
||||
awToolTip: 'Click for help',
|
||||
dataTitle: 'Selecting Hosts'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
label: 'Edit',
|
||||
ngClick: "editHost(\{\{ host.id \}\})",
|
||||
ngClick: "editHost({{ host.id }})",
|
||||
icon: 'icon-edit',
|
||||
"class": 'btn-xs',
|
||||
awToolTip: 'Edit host',
|
||||
dataPlacement: 'top'
|
||||
},
|
||||
},
|
||||
|
||||
"delete": {
|
||||
label: 'Delete',
|
||||
ngClick: "deleteHost(\{\{ host.id \}\},'\{\{ host.name \}\}')",
|
||||
ngClick: "deleteHost(host.id, host.name)",
|
||||
icon: 'icon-trash',
|
||||
"class": 'btn-xs',
|
||||
awToolTip: 'Delete host',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1,27 +1,30 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Inventories.js
|
||||
* Inventories.js
|
||||
* 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,
|
||||
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
organization: {
|
||||
label: 'Organization',
|
||||
ngBind: 'inventory.summary_fields.organization.name',
|
||||
@ -29,69 +32,69 @@ angular.module('InventoriesListDefinition', [])
|
||||
sourceModel: 'organization',
|
||||
sourceField: 'name',
|
||||
excludeModal: true
|
||||
},
|
||||
},
|
||||
has_inventory_sources: {
|
||||
label: 'Cloud sourced?',
|
||||
searchSingleValue: true,
|
||||
searchType: 'boolean',
|
||||
searchValue: 'true',
|
||||
searchOnly: true
|
||||
},
|
||||
},
|
||||
has_active_failures: {
|
||||
label: 'Failed hosts?',
|
||||
searchSingleValue: true,
|
||||
searchType: 'boolean',
|
||||
searchValue: 'true',
|
||||
searchOnly: true
|
||||
},
|
||||
},
|
||||
inventory_sources_with_failures: {
|
||||
label: 'Sync failures?',
|
||||
searchType: 'gtzero',
|
||||
searchValue: 'true',
|
||||
searchOnly: true
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
mode: 'all', // One of: edit, select, all
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addInventory()',
|
||||
awToolTip: 'Create a new inventory'
|
||||
},
|
||||
},
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'all'
|
||||
}
|
||||
},
|
||||
mode: 'edit'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
status: {
|
||||
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: {
|
||||
},
|
||||
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: {
|
||||
label: 'Edit',
|
||||
ngClick: 'editInventoryProperties(inventory.id)',
|
||||
awToolTip: 'Edit inventory',
|
||||
dataPlacement: 'top'
|
||||
},
|
||||
},
|
||||
"delete": {
|
||||
label: 'Delete',
|
||||
ngClick: "deleteInventory(\{\{ inventory.id \}\},'\{\{ inventory.name \}\}')",
|
||||
ngClick: "deleteInventory(inventory.id, inventory.names')",
|
||||
awToolTip: 'Delete inventory',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1,14 +1,16 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* InventoryHosts.js
|
||||
* InventoryHosts.js
|
||||
*
|
||||
* 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',
|
||||
@ -19,34 +21,34 @@ angular.module('InventoryHostsDefinition', [])
|
||||
hover: false,
|
||||
hasChildren: true,
|
||||
'class': 'table-condensed table-no-border',
|
||||
|
||||
|
||||
fields: {
|
||||
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"
|
||||
},
|
||||
},
|
||||
enabled: {
|
||||
label: 'Disabled?',
|
||||
searchSingleValue: true,
|
||||
searchType: 'boolean',
|
||||
searchValue: 'false',
|
||||
searchOnly: true
|
||||
},
|
||||
},
|
||||
has_active_failures: {
|
||||
label: 'Failed jobs?',
|
||||
searchSingleValue: true,
|
||||
searchType: 'boolean',
|
||||
searchValue: 'true',
|
||||
searchOnly: true
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
enabled_flag: {
|
||||
iconClass: "{{ 'fa icon-enabled-' + host.enabled }}",
|
||||
@ -54,7 +56,7 @@ angular.module('InventoryHostsDefinition', [])
|
||||
awToolTip: "{{ host.enabledToolTip }}",
|
||||
dataTipWatch: "host.enabledToolTip",
|
||||
ngClick: "toggleHostEnabled(host.id, host.has_inventory_sources)"
|
||||
},
|
||||
},
|
||||
active_failures: {
|
||||
awPopOver: "{{ host.job_status_html }}",
|
||||
dataTitle: "{{ host.job_status_title }}",
|
||||
@ -62,22 +64,22 @@ angular.module('InventoryHostsDefinition', [])
|
||||
awTipPlacement: 'top',
|
||||
dataPlacement: 'left',
|
||||
iconClass: "{{ 'fa icon-failures-' + host.has_active_failures }}"
|
||||
},
|
||||
},
|
||||
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'
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
|
||||
@ -86,15 +88,14 @@ angular.module('InventoryHostsDefinition', [])
|
||||
create: {
|
||||
mode: 'all',
|
||||
ngClick: "createHost()",
|
||||
ngHide: 'selected_tree_id == 1', //disable when 'All Hosts' selected
|
||||
ngHide: 'selected_tree_id == 1', //disable when 'All Hosts' selected
|
||||
awToolTip: "Create a new host"
|
||||
},
|
||||
},
|
||||
stream: {
|
||||
ngClick: "showHostActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'all'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@ -1,15 +1,17 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Jobs.js
|
||||
* Jobs.js
|
||||
* List view object for Team data model.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('JobEventsListDefinition', [])
|
||||
.value(
|
||||
'JobEventList', {
|
||||
|
||||
.value('JobEventList', {
|
||||
|
||||
name: 'jobevents',
|
||||
iterator: 'jobevent',
|
||||
editTitle: 'Job Events',
|
||||
@ -37,7 +39,7 @@ angular.module('JobEventsListDefinition', [])
|
||||
icon: 'icon-laptop'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
fields: {
|
||||
created: {
|
||||
label: 'Created On',
|
||||
@ -53,7 +55,13 @@ 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 }})',
|
||||
@ -86,7 +94,7 @@ angular.module('JobEventsListDefinition', [])
|
||||
columnClass: 'col-lg-2 hidden-sm hidden-xs'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
actions: {
|
||||
refresh: {
|
||||
mode: 'all',
|
||||
@ -106,4 +114,4 @@ angular.module('JobEventsListDefinition', [])
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -1,20 +1,23 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* JobHosts.js
|
||||
* JobHosts.js
|
||||
* List view object for Job Host Summary data model.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('JobHostDefinition', [])
|
||||
.value('JobHostList', {
|
||||
|
||||
|
||||
name: 'jobhosts',
|
||||
iterator: 'jobhost',
|
||||
editTitle: 'All summaries',
|
||||
index: true,
|
||||
hover: true,
|
||||
|
||||
|
||||
navigationLinks: {
|
||||
ngHide: 'host_id !== null',
|
||||
details: {
|
||||
@ -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?',
|
||||
@ -99,7 +108,7 @@ angular.module('JobHostDefinition', [])
|
||||
searchable: false
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
actions: {
|
||||
help: {
|
||||
awPopOver: "<dl>\n<dt>Success</dt><dd>Tasks successfully executed on the host.</dd>\n" +
|
||||
@ -121,10 +130,10 @@ angular.module('JobHostDefinition', [])
|
||||
'class': 'btn-xs',
|
||||
awToolTip: "Refresh the page",
|
||||
ngClick: "refresh()",
|
||||
ngShow: "host_id == null" //don't show when viewing from inventory->hosts
|
||||
ngShow: "host_id == null" //don't show when viewing from inventory->hosts
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {}
|
||||
|
||||
});
|
||||
});
|
||||
@ -1,73 +1,76 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* JobTemplates.js
|
||||
* JobTemplates.js
|
||||
* List view object for Job Templates data model.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'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,
|
||||
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
mode: 'all', // One of: edit, select, all
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addJobTemplate()',
|
||||
basePaths: ['job_templates'],
|
||||
basePaths: ['job_templates'],
|
||||
awToolTip: 'Create a new template'
|
||||
},
|
||||
},
|
||||
stream: {
|
||||
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',
|
||||
dataPlacement: 'top'
|
||||
},
|
||||
},
|
||||
submit: {
|
||||
label: 'Launch',
|
||||
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'
|
||||
},
|
||||
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',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -6,6 +6,9 @@
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('JobsListDefinition', [])
|
||||
.value( 'JobList', {
|
||||
|
||||
|
||||
@ -1,44 +1,46 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Organizations.js
|
||||
* Organizations.js
|
||||
* List view object for Organizations data model.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'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: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
mode: 'all', // One of: edit, select, all
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addOrganization()',
|
||||
awToolTip: 'Create a new organization'
|
||||
},
|
||||
},
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'all'
|
||||
}
|
||||
},
|
||||
mode: 'edit'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
@ -48,7 +50,7 @@ angular.module('OrganizationListDefinition', [])
|
||||
"class": 'btn-xs btn-default',
|
||||
awToolTip: 'Edit organization',
|
||||
dataPlacement: 'top'
|
||||
},
|
||||
},
|
||||
|
||||
"delete": {
|
||||
label: 'Delete',
|
||||
@ -57,6 +59,6 @@ angular.module('OrganizationListDefinition', [])
|
||||
"class": 'btn-xs btn-danger',
|
||||
awToolTip: 'Delete organization',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1,78 +1,81 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Permissions.js
|
||||
* Permissions.js
|
||||
* List view object for Permissions data model.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'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,
|
||||
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name',
|
||||
ngClick: 'editPermission(\{\{ permission.id \}\})'
|
||||
},
|
||||
ngClick: 'editPermission(permission.id)'
|
||||
},
|
||||
inventory: {
|
||||
label: 'Inventory',
|
||||
sourceModel: 'inventory',
|
||||
sourceField: 'name',
|
||||
ngBind: 'permission.summary_fields.inventory.name'
|
||||
},
|
||||
},
|
||||
project: {
|
||||
label: 'Project',
|
||||
sourceModel: 'project',
|
||||
sourceField: 'name',
|
||||
ngBind: 'permission.summary_fields.project.name'
|
||||
},
|
||||
},
|
||||
permission_type: {
|
||||
label: 'Permission'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
mode: 'all', // One of: edit, select, all
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addPermission()',
|
||||
awToolTip: 'Add a new permission',
|
||||
ngShow: 'PermissionAddAllowed'
|
||||
},
|
||||
},
|
||||
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',
|
||||
dataPlacement: 'top'
|
||||
},
|
||||
},
|
||||
|
||||
"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',
|
||||
ngShow: 'PermissionAddAllowed',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1,66 +1,68 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Projects.js
|
||||
* Projects.js
|
||||
* List view object for Project data model.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('ProjectsListDefinition', [])
|
||||
.value(
|
||||
'ProjectList', {
|
||||
|
||||
.value('ProjectList', {
|
||||
|
||||
name: 'projects',
|
||||
iterator: 'project',
|
||||
selectTitle: 'Add Project',
|
||||
editTitle: 'Projects',
|
||||
selectInstructions: '<p>Select existing projects by clicking each project or checking the related checkbox. When finished, click the blue ' +
|
||||
'<em>Select</em> button, located bottom right.</p> <p>Create a brand new project by clicking the green <em>Create New</em> button.</p>',
|
||||
'<em>Select</em> button, located bottom right.</p> <p>Create a brand new project by clicking the green <em>Create New</em> button.</p>',
|
||||
index: true,
|
||||
hover: true,
|
||||
|
||||
hover: true,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
columnClass: 'hidden-sm hidden-xs',
|
||||
excludeModal: true
|
||||
},
|
||||
},
|
||||
scm_type: {
|
||||
label: 'Type',
|
||||
searchType: 'select',
|
||||
searchOptions: [], // will be set by Options call to projects resource
|
||||
searchOptions: [], // will be set by Options call to projects resource
|
||||
excludeModal: true,
|
||||
nosort: true
|
||||
},
|
||||
},
|
||||
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
|
||||
searchOptions: [], // will be set by Options call to projects resource
|
||||
excludeModal: true
|
||||
},
|
||||
},
|
||||
last_updated: {
|
||||
label: 'Last Updated',
|
||||
type: 'date',
|
||||
excludeModal: true,
|
||||
searchable: false
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
mode: 'all', // One of: edit, select, all
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addProject()',
|
||||
awToolTip: 'Create a new project'
|
||||
},
|
||||
},
|
||||
help: {
|
||||
awPopOver: "<dl>\n<dt>Updating</dt><dd>A source control update is in progress.</dd>\n" +
|
||||
"<dt>Never Updated</dt><dd>This project has not yet been updated from source control.</dd>\n" +
|
||||
@ -75,46 +77,46 @@ angular.module('ProjectsListDefinition', [])
|
||||
mode: 'all',
|
||||
awToolTip: 'Click for help',
|
||||
awTipPlacement: 'top'
|
||||
},
|
||||
},
|
||||
refresh: {
|
||||
mode: 'all',
|
||||
awToolTip: "Refresh the page",
|
||||
ngClick: "refresh()"
|
||||
},
|
||||
},
|
||||
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'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1,24 +1,26 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Streams.js
|
||||
* Streams.js
|
||||
* List view object for activity stream data model.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('StreamListDefinition', [])
|
||||
.value(
|
||||
'StreamList', {
|
||||
|
||||
.value('StreamList', {
|
||||
|
||||
name: 'activities',
|
||||
iterator: 'activity',
|
||||
editTitle: 'Activity Stream',
|
||||
selectInstructions: '',
|
||||
selectInstructions: '',
|
||||
index: false,
|
||||
hover: true,
|
||||
"class": "table-condensed",
|
||||
searchWidgets: 3,
|
||||
|
||||
|
||||
fields: {
|
||||
timestamp: {
|
||||
label: 'Event Time',
|
||||
@ -26,7 +28,7 @@ angular.module('StreamListDefinition', [])
|
||||
desc: true,
|
||||
noLink: true,
|
||||
searchable: false
|
||||
},
|
||||
},
|
||||
user: {
|
||||
label: 'Initiated by',
|
||||
ngBindHtml: 'activity.user',
|
||||
@ -36,22 +38,22 @@ angular.module('StreamListDefinition', [])
|
||||
//dataPlacement: 'top',
|
||||
searchPlaceholder: 'Username',
|
||||
searchWidget: 1
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Action',
|
||||
ngBindHtml: 'activity.description',
|
||||
nosort: true,
|
||||
nosort: true,
|
||||
searchable: false,
|
||||
columnClass: 'col-lg-7'
|
||||
},
|
||||
},
|
||||
system_event: {
|
||||
label: 'System event',
|
||||
searchOnly: true,
|
||||
searchOnly: true,
|
||||
searchType: 'isnull',
|
||||
sourceModel: 'actor',
|
||||
sourceField: 'username',
|
||||
searchWidget: 1
|
||||
},
|
||||
},
|
||||
|
||||
// The following fields exist to force loading each type of object into the search
|
||||
// dropdown
|
||||
@ -61,7 +63,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchObject: 'all',
|
||||
searchPlaceholder: 'All resources',
|
||||
searchWidget: 2
|
||||
},
|
||||
},
|
||||
credential_search: {
|
||||
label: 'Credential',
|
||||
searchOnly: true,
|
||||
@ -69,7 +71,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Credential name',
|
||||
searchWidget: 2,
|
||||
searchField: 'object1'
|
||||
},
|
||||
},
|
||||
group_search: {
|
||||
label: 'Group',
|
||||
searchOnly: true,
|
||||
@ -77,7 +79,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Group name',
|
||||
searchWidget: 2,
|
||||
searchField: 'object1'
|
||||
},
|
||||
},
|
||||
host_search: {
|
||||
label: 'Host',
|
||||
searchOnly: true,
|
||||
@ -85,7 +87,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Host name',
|
||||
searchWidget: 2,
|
||||
searchField: 'object1'
|
||||
},
|
||||
},
|
||||
inventory_search: {
|
||||
label: 'Inventory',
|
||||
searchOnly: true,
|
||||
@ -93,7 +95,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Inventory name',
|
||||
searchWidget: 2,
|
||||
searchField: 'object1'
|
||||
},
|
||||
},
|
||||
job_template_search: {
|
||||
label: 'Job Template',
|
||||
searchOnly: true,
|
||||
@ -101,7 +103,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Job template name',
|
||||
searchWidget: 2,
|
||||
searchField: 'object1'
|
||||
},
|
||||
},
|
||||
job_search: {
|
||||
label: 'Job',
|
||||
searchOnly: true,
|
||||
@ -110,7 +112,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchOnID: true,
|
||||
searchWidget: 2,
|
||||
searchField: 'object1'
|
||||
},
|
||||
},
|
||||
organization_search: {
|
||||
label: 'Organization',
|
||||
searchOnly: true,
|
||||
@ -118,7 +120,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Organization name',
|
||||
searchWidget: 2,
|
||||
searchField: 'object1'
|
||||
},
|
||||
},
|
||||
project_search: {
|
||||
label: 'Project',
|
||||
searchOnly: true,
|
||||
@ -126,7 +128,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Project name',
|
||||
searchWidget: 2,
|
||||
searchField: 'object1'
|
||||
},
|
||||
},
|
||||
user_search: {
|
||||
label: 'User',
|
||||
searchOnly: true,
|
||||
@ -134,18 +136,18 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Primary username',
|
||||
searchWidget: 2,
|
||||
searchField: 'object1'
|
||||
},
|
||||
},
|
||||
|
||||
// The following fields exist to force loading each type of object into the search
|
||||
// dropdown
|
||||
all_objects3: {
|
||||
label: 'All',
|
||||
searchOnly: true,
|
||||
searchOnly: true,
|
||||
searchObject: 'all',
|
||||
searchPlaceholder: 'All related resources',
|
||||
searchWidget: 3,
|
||||
searchField: 'object2'
|
||||
},
|
||||
},
|
||||
credential_search3: {
|
||||
label: 'Credential',
|
||||
searchOnly: true,
|
||||
@ -153,7 +155,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Related credential name',
|
||||
searchWidget: 3,
|
||||
searchField: 'object2'
|
||||
},
|
||||
},
|
||||
group_search3: {
|
||||
label: 'Group',
|
||||
searchOnly: true,
|
||||
@ -161,7 +163,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Related group name',
|
||||
searchWidget: 3,
|
||||
searchField: 'object2'
|
||||
},
|
||||
},
|
||||
host_search3: {
|
||||
label: 'Host',
|
||||
searchOnly: true,
|
||||
@ -169,7 +171,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Related host name',
|
||||
searchWidget: 3,
|
||||
searchField: 'object2'
|
||||
},
|
||||
},
|
||||
inventory_search3: {
|
||||
label: 'Inventory',
|
||||
searchOnly: true,
|
||||
@ -177,7 +179,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Related inventory name',
|
||||
searchWidget: 3,
|
||||
searchField: 'object2'
|
||||
},
|
||||
},
|
||||
job_search3: {
|
||||
label: 'Job',
|
||||
searchOnly: true,
|
||||
@ -186,7 +188,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchOnID: true,
|
||||
searchWidget: 3,
|
||||
searchField: 'object2'
|
||||
},
|
||||
},
|
||||
job_template_search3: {
|
||||
label: 'Job Template',
|
||||
searchOnly: true,
|
||||
@ -194,7 +196,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Related job template name',
|
||||
searchWidget: 3,
|
||||
searchField: 'object2'
|
||||
},
|
||||
},
|
||||
organization_search3: {
|
||||
label: 'Organization',
|
||||
searchOnly: true,
|
||||
@ -202,7 +204,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Related organization name',
|
||||
searchWidget: 3,
|
||||
searchField: 'object2'
|
||||
},
|
||||
},
|
||||
project_search3: {
|
||||
label: 'Project',
|
||||
searchOnly: true,
|
||||
@ -210,7 +212,7 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Related project name',
|
||||
searchWidget: 3,
|
||||
searchField: 'object2'
|
||||
},
|
||||
},
|
||||
user_search3: {
|
||||
label: 'User',
|
||||
searchOnly: true,
|
||||
@ -218,32 +220,32 @@ angular.module('StreamListDefinition', [])
|
||||
searchPlaceholder: 'Related username',
|
||||
searchWidget: 3,
|
||||
searchField: 'object2'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
refresh: {
|
||||
mode: 'all',
|
||||
'class': 'btn-xs',
|
||||
awToolTip: "Refresh the page",
|
||||
ngClick: "refreshStream()"
|
||||
},
|
||||
},
|
||||
close: {
|
||||
mode: 'all',
|
||||
awToolTip: "Close Activity Stream view",
|
||||
ngClick: "closeStream()"
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
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',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
@ -1,69 +1,71 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Teams.js
|
||||
* 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,
|
||||
hover: true,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
},
|
||||
},
|
||||
organization: {
|
||||
label: 'Organization',
|
||||
ngBind: 'team.organization_name',
|
||||
sourceModel: 'organization',
|
||||
sourceField: 'name'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
mode: 'all', // One of: edit, select, all
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addTeam()',
|
||||
awToolTip: 'Create a new team'
|
||||
},
|
||||
},
|
||||
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',
|
||||
dataPlacement: 'top'
|
||||
},
|
||||
},
|
||||
|
||||
"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',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1,71 +1,72 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Users.js
|
||||
* Users.js
|
||||
* List view object for Users data model.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('UserListDefinition', [])
|
||||
.value(
|
||||
'UserList', {
|
||||
|
||||
.value('UserList', {
|
||||
|
||||
name: 'users',
|
||||
iterator: 'user',
|
||||
selectTitle: 'Add Users',
|
||||
editTitle: 'Users',
|
||||
selectInstructions: '<p>Select existing users by clicking each user or checking the related checkbox. When finished, click the blue ' +
|
||||
'<em>Select</em> button, located bottom right.</p> <p>When available, a brand new user can be created by clicking the green ' +
|
||||
'<em>Create New</em> button.</p>',
|
||||
'<em>Create New</em> button.</p>',
|
||||
index: true,
|
||||
hover: true,
|
||||
|
||||
hover: true,
|
||||
|
||||
fields: {
|
||||
username: {
|
||||
key: true,
|
||||
label: 'Username'
|
||||
},
|
||||
},
|
||||
first_name: {
|
||||
label: 'First Name'
|
||||
},
|
||||
},
|
||||
last_name: {
|
||||
label: 'Last Name'
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
label: 'Create New',
|
||||
mode: 'all', // One of: edit, select, all
|
||||
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',
|
||||
dataPlacement: 'top'
|
||||
},
|
||||
},
|
||||
|
||||
"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',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1,7 +1,7 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* InventorySyncStatus.js
|
||||
* InventorySyncStatus.js
|
||||
*
|
||||
* Dashboard widget showing object counts and license availability.
|
||||
*
|
||||
@ -10,94 +10,98 @@
|
||||
'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) {
|
||||
|
||||
var scope = params.scope;
|
||||
var target = params.target;
|
||||
var dashboard = params.dashboard;
|
||||
|
||||
var 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";
|
||||
html += "<thead>\n";
|
||||
html += "<tr>\n";
|
||||
html += "<th class=\"col-md-4 col-lg-3\"></th>\n";
|
||||
html += "<th class=\"col-md-2 col-lg-1 text-right\">Failed</th>\n";
|
||||
html += "<th class=\"col-md-2 col-lg-1 text-right\">Total</th>\n";
|
||||
html += "</tr>\n";
|
||||
html += "</thead>\n";
|
||||
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";
|
||||
html += "<td><a href=\"" + link + "\"";
|
||||
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 += "<a href=\"" + link + "\">" + count + "</a>";
|
||||
html += "</td></tr>\n";
|
||||
return html;
|
||||
.factory('InventorySyncStatus', ['$rootScope', '$compile', function ($rootScope, $compile) {
|
||||
return function (params) {
|
||||
|
||||
var scope = params.scope,
|
||||
target = params.target,
|
||||
dashboard = params.dashboard,
|
||||
html, group_total, group_fail, element, src;
|
||||
|
||||
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";
|
||||
html += "<thead>\n";
|
||||
html += "<tr>\n";
|
||||
html += "<th class=\"col-md-4 col-lg-3\"></th>\n";
|
||||
html += "<th class=\"col-md-2 col-lg-1 text-right\">Failed</th>\n";
|
||||
html += "<th class=\"col-md-2 col-lg-1 text-right\">Total</th>\n";
|
||||
html += "</tr>\n";
|
||||
html += "</thead>\n";
|
||||
html += "<tbody>\n";
|
||||
|
||||
function makeRow(params) {
|
||||
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 + "</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 += "<a href=\"" + link + "\">" + count + "</a>";
|
||||
html += "</td></tr>\n";
|
||||
return html;
|
||||
}
|
||||
|
||||
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,
|
||||
link: '/#/inventories/?has_inventory_sources=true',
|
||||
fail_link: '/#/inventories/?inventory_sources_with_failures=true'
|
||||
});
|
||||
|
||||
var group_total = 0;
|
||||
var group_fail = 0;
|
||||
if (dashboard.inventory_sources) {
|
||||
for (var 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',
|
||||
count: group_total,
|
||||
fail: group_fail,
|
||||
link: '/#/home/groups/?has_external_source=true',
|
||||
fail_link: '/#/home/groups/?status=failed'
|
||||
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,
|
||||
link: '/#/inventories/?has_inventory_sources=true',
|
||||
fail_link: '/#/inventories/?inventory_sources_with_failures=true'
|
||||
});
|
||||
|
||||
// Each inventory source
|
||||
for (var src in dashboard.inventory_sources) {
|
||||
if (dashboard.inventory_sources[src].total) {
|
||||
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,
|
||||
fail_link: '/#/home/groups/?status=failed&source=' + src
|
||||
group_total = 0;
|
||||
group_fail = 0;
|
||||
if (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',
|
||||
count: group_total,
|
||||
fail: group_fail,
|
||||
link: '/#/home/groups/?has_external_source=true',
|
||||
fail_link: '/#/home/groups/?status=failed'
|
||||
});
|
||||
|
||||
// Each inventory source
|
||||
for (src in dashboard.inventory_sources) {
|
||||
if (dashboard.inventory_sources[src].total) {
|
||||
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,
|
||||
fail_link: '/#/home/groups/?status=failed&source=' + src
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
html += "</tbody>\n";
|
||||
html += "</table>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
|
||||
var element = angular.element(document.getElementById(target));
|
||||
element.html(html);
|
||||
$compile(element)(scope);
|
||||
scope.$emit('WidgetLoaded');
|
||||
html += "</tbody>\n";
|
||||
html += "</table>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
|
||||
}
|
||||
}]);
|
||||
element = angular.element(document.getElementById(target));
|
||||
element.html(html);
|
||||
$compile(element)(scope);
|
||||
scope.$emit('WidgetLoaded');
|
||||
|
||||
};
|
||||
}
|
||||
]);
|
||||
@ -1,7 +1,7 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* JobStatus.js
|
||||
* JobStatus.js
|
||||
*
|
||||
* Dashboard widget showing object counts and license availability.
|
||||
*
|
||||
@ -11,88 +11,89 @@
|
||||
|
||||
angular.module('JobStatusWidget', ['RestServices', 'Utilities'])
|
||||
.factory('JobStatus', ['$rootScope', '$compile', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait',
|
||||
function($rootScope, $compile, Rest, GetBasePath, ProcessErrors, Wait) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var target = params.target;
|
||||
var dashboard = params.dashboard;
|
||||
|
||||
var html = '';
|
||||
var 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";
|
||||
html += "<thead>\n";
|
||||
html += "<tr>\n";
|
||||
html += "<th class=\"col-md-4 col-lg-3\"></th>\n";
|
||||
html += "<th class=\"col-md-2 col-lg-1 text-right\">Failed</th>\n";
|
||||
html += "<th class=\"col-md-2 col-lg-1 text-right\">Total</th>\n";
|
||||
html += "</tr>\n";
|
||||
html += "</thead>\n";
|
||||
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;
|
||||
html += "<tr>\n";
|
||||
html += "<td><a href=\"" + link + "\"";
|
||||
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 += "<a href=\"" + link + "\" >" + count + "</a>";
|
||||
html += "</td></tr>\n";
|
||||
return html;
|
||||
}
|
||||
|
||||
html += makeRow({
|
||||
label: 'Jobs',
|
||||
link: '/#/jobs',
|
||||
count: (dashboard.jobs && dashboard.jobs.total) ? dashboard.jobs.total : 0,
|
||||
fail: (dashboard.jobs && dashboard.jobs.failed) ? dashboard.jobs.failed : 0,
|
||||
fail_link: '/#/jobs/?status=failed'
|
||||
});
|
||||
html += makeRow({
|
||||
label: 'Inventories',
|
||||
link: '/#/inventories',
|
||||
count: (dashboard.inventories && dashboard.inventories.total) ? dashboard.inventories.total : 0,
|
||||
fail: (dashboard.inventories && dashboard.inventories.job_failed) ? dashboard.inventories.job_failed : 0,
|
||||
fail_link: '/#/inventories/?has_active_failures=true'
|
||||
});
|
||||
html += makeRow({
|
||||
label: 'Groups',
|
||||
link: '/#/home/groups',
|
||||
count: (dashboard.groups && dashboard.groups.total) ? dashboard.groups.total : 0,
|
||||
fail: (dashboard.groups && dashboard.groups.job_failed) ? dashboard.groups.job_failed : 0,
|
||||
fail_link: '/#/home/groups/?has_active_failures=true'
|
||||
});
|
||||
html += makeRow({
|
||||
label: 'Hosts',
|
||||
link: '/#/home/hosts',
|
||||
count: (dashboard.hosts && dashboard.hosts.total) ? dashboard.hosts.total : 0,
|
||||
fail: (dashboard.hosts && dashboard.hosts.failed) ? dashboard.hosts.failed : 0,
|
||||
fail_link: '/#/home/hosts/?has_active_failures=true'
|
||||
});
|
||||
function ($rootScope, $compile) {
|
||||
return function (params) {
|
||||
|
||||
html += "</tbody>\n";
|
||||
html += "</table>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
var scope = params.scope,
|
||||
target = params.target,
|
||||
dashboard = params.dashboard,
|
||||
html = '', element;
|
||||
|
||||
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";
|
||||
html += "<thead>\n";
|
||||
html += "<tr>\n";
|
||||
html += "<th class=\"col-md-4 col-lg-3\"></th>\n";
|
||||
html += "<th class=\"col-md-2 col-lg-1 text-right\">Failed</th>\n";
|
||||
html += "<th class=\"col-md-2 col-lg-1 text-right\">Total</th>\n";
|
||||
html += "</tr>\n";
|
||||
html += "</thead>\n";
|
||||
html += "<tbody>\n";
|
||||
|
||||
var element = angular.element(document.getElementById(target));
|
||||
element.html(html);
|
||||
$compile(element)(scope);
|
||||
scope.$emit('WidgetLoaded');
|
||||
function makeRow(params) {
|
||||
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 + "</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 += "<a href=\"" + link + "\" >" + count + "</a>";
|
||||
html += "</td></tr>\n";
|
||||
return html;
|
||||
}
|
||||
|
||||
html += makeRow({
|
||||
label: 'Jobs',
|
||||
link: '/#/jobs',
|
||||
count: (dashboard.jobs && dashboard.jobs.total) ? dashboard.jobs.total : 0,
|
||||
fail: (dashboard.jobs && dashboard.jobs.failed) ? dashboard.jobs.failed : 0,
|
||||
fail_link: '/#/jobs/?status=failed'
|
||||
});
|
||||
html += makeRow({
|
||||
label: 'Inventories',
|
||||
link: '/#/inventories',
|
||||
count: (dashboard.inventories && dashboard.inventories.total) ? dashboard.inventories.total : 0,
|
||||
fail: (dashboard.inventories && dashboard.inventories.job_failed) ? dashboard.inventories.job_failed : 0,
|
||||
fail_link: '/#/inventories/?has_active_failures=true'
|
||||
});
|
||||
html += makeRow({
|
||||
label: 'Groups',
|
||||
link: '/#/home/groups',
|
||||
count: (dashboard.groups && dashboard.groups.total) ? dashboard.groups.total : 0,
|
||||
fail: (dashboard.groups && dashboard.groups.job_failed) ? dashboard.groups.job_failed : 0,
|
||||
fail_link: '/#/home/groups/?has_active_failures=true'
|
||||
});
|
||||
html += makeRow({
|
||||
label: 'Hosts',
|
||||
link: '/#/home/hosts',
|
||||
count: (dashboard.hosts && dashboard.hosts.total) ? dashboard.hosts.total : 0,
|
||||
fail: (dashboard.hosts && dashboard.hosts.failed) ? dashboard.hosts.failed : 0,
|
||||
fail_link: '/#/home/hosts/?has_active_failures=true'
|
||||
});
|
||||
|
||||
html += "</tbody>\n";
|
||||
html += "</table>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
|
||||
element = angular.element(document.getElementById(target));
|
||||
element.html(html);
|
||||
$compile(element)(scope);
|
||||
scope.$emit('WidgetLoaded');
|
||||
|
||||
};
|
||||
}
|
||||
}]);
|
||||
]);
|
||||
@ -1,7 +1,7 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* ObjectCount.js
|
||||
* ObjectCount.js
|
||||
*
|
||||
* Dashboard widget showing object counts and license availability.
|
||||
*
|
||||
@ -11,60 +11,60 @@
|
||||
|
||||
angular.module('ObjectCountWidget', ['RestServices', 'Utilities'])
|
||||
.factory('ObjectCount', ['$rootScope', '$compile', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait',
|
||||
function($rootScope, $compile, Rest, GetBasePath, ProcessErrors, Wait) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var target = params.target;
|
||||
var dashboard = params.dashboard;
|
||||
|
||||
|
||||
var keys=[ 'organizations', 'users', 'teams', 'credentials', 'projects', 'inventories', 'groups', 'hosts',
|
||||
'job_templates', 'jobs' ];
|
||||
|
||||
var html = "<div class=\"panel panel-default\">\n";
|
||||
html += "<div class=\"panel-heading\">System Summary</div>\n";
|
||||
html += "<div class=\"panel-body\">\n";
|
||||
html += "<table class=\"table table-condensed table-hover\">\n";
|
||||
html += "<thead>\n";
|
||||
html += "<tr>\n";
|
||||
html += "<th class=\"col-md-5 col-lg-4\"></th>\n";
|
||||
html += "<th class=\"col-md-1 col-lg-1 text-right\">Total</th>\n";
|
||||
html += "</tr>\n";
|
||||
html += "</thead>\n";
|
||||
html += "<tbody>\n";
|
||||
|
||||
function makeRow(params) {
|
||||
var html = '';
|
||||
var label = params.label;
|
||||
var link = params.link;
|
||||
var count = params.count;
|
||||
html += "<tr>\n";
|
||||
html += "<td class=\"capitalize\"><a href=\"" + link + "\"";
|
||||
html += (label == 'hosts' || label == 'groups') ? " class=\"pad-left-sm\" " : "";
|
||||
html += ">" + label.replace(/\_/g,' ') + "</a></td>\n";
|
||||
html += "<td class=\"text-right\">"
|
||||
html += "<a href=\"" + link + "\" >" + count + "</a>";
|
||||
html += "</td></tr>\n";
|
||||
return html;
|
||||
}
|
||||
|
||||
for (var i=0; i < keys.length; i++) {
|
||||
html += makeRow({
|
||||
label: keys[i],
|
||||
link: '/#/' + ( (keys[i] == 'hosts' || keys[i] == 'groups') ? 'home/' + keys[i] : keys[i] ),
|
||||
count: (dashboard[keys[i]] && dashboard[keys[i]].total) ? dashboard[keys[i]].total : 0
|
||||
});
|
||||
}
|
||||
function ($rootScope, $compile) {
|
||||
return function (params) {
|
||||
|
||||
html += "</tbody>\n";
|
||||
html += "</table>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n"
|
||||
var element = angular.element(document.getElementById(target));
|
||||
element.html(html);
|
||||
$compile(element)(scope);
|
||||
scope.$emit('WidgetLoaded');
|
||||
|
||||
var scope = params.scope,
|
||||
target = params.target,
|
||||
dashboard = params.dashboard,
|
||||
keys = ['organizations', 'users', 'teams', 'credentials', 'projects', 'inventories', 'groups', 'hosts',
|
||||
'job_templates', 'jobs'
|
||||
],
|
||||
i, html, element;
|
||||
|
||||
html = "<div class=\"panel panel-default\">\n";
|
||||
html += "<div class=\"panel-heading\">System Summary</div>\n";
|
||||
html += "<div class=\"panel-body\">\n";
|
||||
html += "<table class=\"table table-condensed table-hover\">\n";
|
||||
html += "<thead>\n";
|
||||
html += "<tr>\n";
|
||||
html += "<th class=\"col-md-5 col-lg-4\"></th>\n";
|
||||
html += "<th class=\"col-md-1 col-lg-1 text-right\">Total</th>\n";
|
||||
html += "</tr>\n";
|
||||
html += "</thead>\n";
|
||||
html += "<tbody>\n";
|
||||
|
||||
function makeRow(params) {
|
||||
var html = '',
|
||||
label = params.label,
|
||||
link = params.link,
|
||||
count = params.count;
|
||||
html += "<tr>\n";
|
||||
html += "<td class=\"capitalize\"><a href=\"" + link + "\"";
|
||||
html += (label === 'hosts' || label === 'groups') ? " class=\"pad-left-sm\" " : "";
|
||||
html += ">" + label.replace(/\_/g, ' ') + "</a></td>\n";
|
||||
html += "<td class=\"text-right\">";
|
||||
html += "<a href=\"" + link + "\" >" + count + "</a>";
|
||||
html += "</td></tr>\n";
|
||||
return html;
|
||||
}
|
||||
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
html += makeRow({
|
||||
label: keys[i],
|
||||
link: '/#/' + ((keys[i] === 'hosts' || keys[i] === 'groups') ? 'home/' + keys[i] : keys[i]),
|
||||
count: (dashboard[keys[i]] && dashboard[keys[i]].total) ? dashboard[keys[i]].total : 0
|
||||
});
|
||||
}
|
||||
|
||||
html += "</tbody>\n";
|
||||
html += "</table>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
element = angular.element(document.getElementById(target));
|
||||
element.html(html);
|
||||
$compile(element)(scope);
|
||||
scope.$emit('WidgetLoaded');
|
||||
};
|
||||
}
|
||||
}]);
|
||||
]);
|
||||
@ -1,99 +1,100 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* SCMSyncStatus.js
|
||||
* SCMSyncStatus.js
|
||||
*
|
||||
* Dashboard widget showing object counts and license availability.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('SCMSyncStatusWidget', ['RestServices', 'Utilities'])
|
||||
.factory('SCMSyncStatus', ['$rootScope', '$compile', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait', 'GetChoices',
|
||||
function($rootScope, $compile, Rest, GetBasePath, ProcessErrors, Wait, GetChoices) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var target = params.target;
|
||||
var dashboard = params.dashboard;
|
||||
|
||||
var html = "<div class=\"panel panel-default\">\n";
|
||||
html += "<div class=\"panel-heading\">Project SCM Status</div>\n";
|
||||
html += "<div class=\"panel-body\">\n";
|
||||
html += "<table class=\"table table-condensed table-hover\">\n";
|
||||
html += "<thead>\n";
|
||||
html += "<tr>\n";
|
||||
html += "<th class=\"col-md-4 col-lg-3\"></th>\n";
|
||||
html += "<th class=\"col-md-2 col-lg-1 text-right\">Failed</th>\n";
|
||||
html += "<th class=\"col-md-2 col-lg-1 text-right\">Total</th>\n";
|
||||
html += "</tr>\n";
|
||||
html += "</thead>\n";
|
||||
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;
|
||||
html += "<tr>\n";
|
||||
html += "<td><a href=\"" + link + "\">" + 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 += "<a href=\"" + link + "\" >" + count + "</a>";
|
||||
html += "</td></tr>\n";
|
||||
return html;
|
||||
}
|
||||
.factory('SCMSyncStatus', ['$rootScope', '$compile',
|
||||
function ($rootScope, $compile) {
|
||||
return function (params) {
|
||||
|
||||
var total_count = 0;
|
||||
if (dashboard.scm_types) {
|
||||
for (var type in dashboard.scm_types) {
|
||||
total_count += (dashboard.scm_types[type].total) ? dashboard.scm_types[type].total : 0;
|
||||
}
|
||||
}
|
||||
var scope = params.scope,
|
||||
target = params.target,
|
||||
dashboard = params.dashboard,
|
||||
i, html, total_count, element, type, labelList;
|
||||
|
||||
html = "<div class=\"panel panel-default\">\n";
|
||||
html += "<div class=\"panel-heading\">Project SCM Status</div>\n";
|
||||
html += "<div class=\"panel-body\">\n";
|
||||
html += "<table class=\"table table-condensed table-hover\">\n";
|
||||
html += "<thead>\n";
|
||||
html += "<tr>\n";
|
||||
html += "<th class=\"col-md-4 col-lg-3\"></th>\n";
|
||||
html += "<th class=\"col-md-2 col-lg-1 text-right\">Failed</th>\n";
|
||||
html += "<th class=\"col-md-2 col-lg-1 text-right\">Total</th>\n";
|
||||
html += "</tr>\n";
|
||||
html += "</thead>\n";
|
||||
html += "<tbody>\n";
|
||||
|
||||
function makeRow(params) {
|
||||
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 + "\">" + 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 += "<a href=\"" + link + "\" >" + count + "</a>";
|
||||
html += "</td></tr>\n";
|
||||
return html;
|
||||
}
|
||||
|
||||
total_count = 0;
|
||||
if (dashboard.scm_types) {
|
||||
for (type in dashboard.scm_types) {
|
||||
total_count += (dashboard.scm_types[type].total) ? dashboard.scm_types[type].total : 0;
|
||||
}
|
||||
}
|
||||
|
||||
html += makeRow({ label: 'Projects',
|
||||
link: '/#/projects',
|
||||
count: total_count,
|
||||
fail: (dashboard.projects && dashboard.projects.failed) ? dashboard.projects.failed : 0,
|
||||
fail_link: '/#/projects/?status=failed'
|
||||
});
|
||||
|
||||
var labelList = [];
|
||||
for (var type in dashboard.scm_types) {
|
||||
labelList.push(type);
|
||||
}
|
||||
labelList.sort();
|
||||
var type;
|
||||
for (var i=0; i < labelList.length; i++) {
|
||||
type = labelList[i];
|
||||
if (dashboard.scm_types[type].total) {
|
||||
html += makeRow({
|
||||
label: dashboard.scm_types[type].label,
|
||||
link: '/#/projects/?scm_type=' + type,
|
||||
count: (dashboard.scm_types[type].total) ? dashboard.scm_types[type].total : 0,
|
||||
fail: (dashboard.scm_types[type].failed) ? dashboard.scm_types[type].failed : 0,
|
||||
fail_link: '/#/projects/?scm_type=' + type + '&status=failed'
|
||||
});
|
||||
}
|
||||
label: 'Projects',
|
||||
link: '/#/projects',
|
||||
count: total_count,
|
||||
fail: (dashboard.projects && dashboard.projects.failed) ? dashboard.projects.failed : 0,
|
||||
fail_link: '/#/projects/?status=failed'
|
||||
});
|
||||
|
||||
labelList = [];
|
||||
for (type in dashboard.scm_types) {
|
||||
labelList.push(type);
|
||||
}
|
||||
labelList.sort();
|
||||
for (i = 0; i < labelList.length; i++) {
|
||||
type = labelList[i];
|
||||
if (dashboard.scm_types[type].total) {
|
||||
html += makeRow({
|
||||
label: dashboard.scm_types[type].label,
|
||||
link: '/#/projects/?scm_type=' + type,
|
||||
count: (dashboard.scm_types[type].total) ? dashboard.scm_types[type].total : 0,
|
||||
fail: (dashboard.scm_types[type].failed) ? dashboard.scm_types[type].failed : 0,
|
||||
fail_link: '/#/projects/?scm_type=' + type + '&status=failed'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
html += "</tbody>\n";
|
||||
html += "</table>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
|
||||
element = angular.element(document.getElementById(target));
|
||||
element.html(html);
|
||||
$compile(element)(scope);
|
||||
scope.$emit('WidgetLoaded');
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
html += "</tbody>\n";
|
||||
html += "</table>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
|
||||
var element = angular.element(document.getElementById(target));
|
||||
element.html(html);
|
||||
$compile(element)(scope);
|
||||
scope.$emit('WidgetLoaded');
|
||||
|
||||
}
|
||||
}]);
|
||||
]);
|
||||
@ -1,7 +1,7 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* Stream.js
|
||||
* Stream.js
|
||||
*
|
||||
* Activity stream widget that can be called from anywhere
|
||||
*
|
||||
@ -10,457 +10,469 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('StreamWidget', ['RestServices', 'Utilities', 'StreamListDefinition', 'SearchHelper', 'PaginationHelpers',
|
||||
'RefreshHelper', 'ListGenerator', 'StreamWidget', 'AuthService'])
|
||||
|
||||
.factory('setStreamHeight', [ function() {
|
||||
return function() {
|
||||
// Try not to overlap footer. Because stream is positioned absolute, the parent
|
||||
// doesn't resize correctly when stream is loaded.
|
||||
var sheight = $('#stream-content').height();
|
||||
var theight = parseInt($('#tab-content-container').css('min-height').replace(/px/,''));
|
||||
var height = (theight < sheight) ? sheight : theight;
|
||||
$('#tab-content-container').css({ "min-height": height });
|
||||
}
|
||||
}])
|
||||
'RefreshHelper', 'ListGenerator', 'StreamWidget', 'AuthService'
|
||||
])
|
||||
|
||||
.factory('ShowStream', [ 'setStreamHeight', 'Authorization', function(setStreamHeight, Authorization) {
|
||||
return function() {
|
||||
// Slide in the Stream widget
|
||||
|
||||
// Make some style/position adjustments adjustments
|
||||
var stream = $('#stream-container');
|
||||
stream.css({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
'min-height': '100%',
|
||||
'background-color': '#FFF'
|
||||
.factory('setStreamHeight', [
|
||||
function () {
|
||||
return function () {
|
||||
// Try not to overlap footer. Because stream is positioned absolute, the parent
|
||||
// doesn't resize correctly when stream is loaded.
|
||||
var sheight = $('#stream-content').height(),
|
||||
theight = parseInt($('#tab-content-container').css('min-height').replace(/px/, '')),
|
||||
height = (theight < sheight) ? sheight : theight;
|
||||
$('#tab-content-container').css({
|
||||
"min-height": height
|
||||
});
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
.factory('ShowStream', ['setStreamHeight', 'Authorization',
|
||||
function (setStreamHeight) {
|
||||
return function () {
|
||||
// Slide in the Stream widget
|
||||
|
||||
// Make some style/position adjustments adjustments
|
||||
var stream = $('#stream-container');
|
||||
stream.css({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
'min-height': '100%',
|
||||
'background-color': '#FFF'
|
||||
});
|
||||
|
||||
setStreamHeight();
|
||||
setStreamHeight();
|
||||
|
||||
// Slide in stream
|
||||
stream.show('slide', {'direction': 'left'}, {'duration': 500, 'queue': false });
|
||||
|
||||
}
|
||||
}])
|
||||
// Slide in stream
|
||||
stream.show('slide', {
|
||||
'direction': 'left'
|
||||
}, {
|
||||
'duration': 500,
|
||||
'queue': false
|
||||
});
|
||||
|
||||
.factory('HideStream', [ 'LoadBreadCrumbs', function(LoadBreadCrumbs) {
|
||||
return function() {
|
||||
// Remove the stream widget
|
||||
|
||||
var stream = $('#stream-container');
|
||||
stream.hide('slide', {'direction': 'left'}, {'duration': 500, 'queue': false });
|
||||
|
||||
// Completely destroy the container so we don't experience random flashes of it later.
|
||||
// There was some sort of weirdness with the tab 'show' causing the stream to slide in when
|
||||
// a tab was clicked, after the stream had been hidden. Seemed like timing- wait long enough
|
||||
// before clicking a tab, and it would not happen.
|
||||
setTimeout( function() {
|
||||
stream.detach();
|
||||
stream.empty();
|
||||
stream.unbind();
|
||||
$('#tab-content-container').css({ 'min-height': 0 }); //let the parent height go back to normal
|
||||
}, 500);
|
||||
|
||||
LoadBreadCrumbs();
|
||||
}
|
||||
}])
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
.factory('StreamBreadCrumbs', ['$rootScope', '$location', function($rootScope, $location) {
|
||||
return function() {
|
||||
// Load the breadcrumbs array. We have to do things a bit different than Utilities.LoadBreadcrumbs.
|
||||
// Rather than botch that all up, we'll do our own thing here.
|
||||
$rootScope.breadcrumbs = [];
|
||||
var paths = $location.path().split('/');
|
||||
paths.splice(0,1);
|
||||
var path, title, i, j;
|
||||
for (i=0; i < paths.length; i++) {
|
||||
if (/^\d+/.test(paths[i])) {
|
||||
path='';
|
||||
title='';
|
||||
for (j=0; j <= i; j++) {
|
||||
path += '/' + paths[j];
|
||||
}
|
||||
for (j=0; j < $rootScope.crumbCache.length; j++) {
|
||||
if ($rootScope.crumbCache[j].path == path) {
|
||||
title = $rootScope.crumbCache[j].title;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!title) {
|
||||
title = paths[i - 1].substr(0,paths[i - 1].length - 1);
|
||||
title = title.charAt(0).toUpperCase() + title.slice(1);
|
||||
title = (title == 'Inventorie') ? 'Inventory' : title;
|
||||
}
|
||||
}
|
||||
else {
|
||||
path='';
|
||||
title='';
|
||||
if (i > 0) {
|
||||
for (j=0; j <= i; j++) {
|
||||
.factory('HideStream', ['LoadBreadCrumbs',
|
||||
function (LoadBreadCrumbs) {
|
||||
return function () {
|
||||
// Remove the stream widget
|
||||
|
||||
var stream = $('#stream-container');
|
||||
stream.hide('slide', {
|
||||
'direction': 'left'
|
||||
}, {
|
||||
'duration': 500,
|
||||
'queue': false
|
||||
});
|
||||
|
||||
// Completely destroy the container so we don't experience random flashes of it later.
|
||||
// There was some sort of weirdness with the tab 'show' causing the stream to slide in when
|
||||
// a tab was clicked, after the stream had been hidden. Seemed like timing- wait long enough
|
||||
// before clicking a tab, and it would not happen.
|
||||
setTimeout(function () {
|
||||
stream.detach();
|
||||
stream.empty();
|
||||
stream.unbind();
|
||||
$('#tab-content-container').css({
|
||||
'min-height': 0
|
||||
}); //let the parent height go back to normal
|
||||
}, 500);
|
||||
|
||||
LoadBreadCrumbs();
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
.factory('StreamBreadCrumbs', ['$rootScope', '$location',
|
||||
function ($rootScope, $location) {
|
||||
return function () {
|
||||
// Load the breadcrumbs array. We have to do things a bit different than Utilities.LoadBreadcrumbs.
|
||||
// Rather than botch that all up, we'll do our own thing here.
|
||||
$rootScope.breadcrumbs = [];
|
||||
var path, title, i, j, paths = $location.path().split('/');
|
||||
paths.splice(0, 1);
|
||||
for (i = 0; i < paths.length; i++) {
|
||||
if (/^\d+/.test(paths[i])) {
|
||||
path = '';
|
||||
title = '';
|
||||
for (j = 0; j <= i; j++) {
|
||||
path += '/' + paths[j];
|
||||
}
|
||||
for (j = 0; j < $rootScope.crumbCache.length; j++) {
|
||||
if ($rootScope.crumbCache[j].path === path) {
|
||||
title = $rootScope.crumbCache[j].title;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!title) {
|
||||
title = paths[i - 1].substr(0, paths[i - 1].length - 1);
|
||||
title = title.charAt(0).toUpperCase() + title.slice(1);
|
||||
title = (title === 'Inventorie') ? 'Inventory' : title;
|
||||
}
|
||||
} else {
|
||||
path = '';
|
||||
title = '';
|
||||
if (i > 0) {
|
||||
for (j = 0; j <= i; j++) {
|
||||
path += '/' + paths[j];
|
||||
}
|
||||
} else {
|
||||
path = '/' + paths[i];
|
||||
}
|
||||
title = paths[i];
|
||||
title = title.charAt(0).toUpperCase() + title.slice(1);
|
||||
}
|
||||
else {
|
||||
path = '/' + paths[i];
|
||||
}
|
||||
title = paths[i];
|
||||
title = title.charAt(0).toUpperCase() + title.slice(1);
|
||||
$rootScope.breadcrumbs.push({
|
||||
path: path,
|
||||
title: title
|
||||
});
|
||||
}
|
||||
$rootScope.breadcrumbs.push({ path: path, title: title, ngClick: "closeStream('" + path + "')" });
|
||||
}
|
||||
}
|
||||
}])
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
.factory('FixUrl', [ function() {
|
||||
return function(u) {
|
||||
return u.replace(/\/api\/v1\//,'/#/');
|
||||
}
|
||||
}])
|
||||
.factory('FixUrl', [
|
||||
function () {
|
||||
return function (u) {
|
||||
return u.replace(/\/api\/v1\//, '/#/');
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
.factory('BuildUrl', [ function() {
|
||||
return function(obj) {
|
||||
var url = '/#/';
|
||||
switch(obj.base) {
|
||||
case 'group':
|
||||
case 'host':
|
||||
url += 'home/' + obj.base + 's/?id=' + obj.id;
|
||||
break;
|
||||
case 'inventory':
|
||||
url += 'inventories/' + obj.id + '/';
|
||||
break;
|
||||
default:
|
||||
url += obj.base + 's/' + obj.id + '/';
|
||||
}
|
||||
return url;
|
||||
}
|
||||
}])
|
||||
|
||||
.factory('BuildDescription', ['FixUrl', 'BuildUrl', function(FixUrl, BuildUrl) {
|
||||
return function(activity) {
|
||||
|
||||
function stripDeleted(s) {
|
||||
return s.replace(/^_deleted_\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+\+\d+:\d+_/,'');
|
||||
.factory('BuildUrl', [
|
||||
function () {
|
||||
return function (obj) {
|
||||
var url = '/#/';
|
||||
switch (obj.base) {
|
||||
case 'group':
|
||||
case 'host':
|
||||
url += 'home/' + obj.base + 's/?id=' + obj.id;
|
||||
break;
|
||||
case 'inventory':
|
||||
url += 'inventories/' + obj.id + '/';
|
||||
break;
|
||||
default:
|
||||
url += obj.base + 's/' + obj.id + '/';
|
||||
}
|
||||
|
||||
var descr = '';
|
||||
var descr_nolink;
|
||||
descr += activity.operation;
|
||||
descr += (/e$/.test(activity.operation)) ? 'd ' : 'ed ';
|
||||
descr_nolink = descr;
|
||||
return url;
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
// labels
|
||||
var obj1 = activity.object1;
|
||||
var obj2 = activity.object2;
|
||||
|
||||
// objects
|
||||
var obj1_obj = (activity.summary_fields[obj1]) ? activity.summary_fields[obj1][0] : null;
|
||||
if (obj1 == obj2) {
|
||||
var obj2_obj = activity.summary_fields[obj1][1];
|
||||
}
|
||||
else if (activity.summary_fields[obj2]) {
|
||||
var obj2_obj = activity.summary_fields[obj2][0];
|
||||
}
|
||||
else {
|
||||
var obj2_obj = null;
|
||||
}
|
||||
|
||||
if (obj1 == 'user' || obj2 == 'user') {
|
||||
activity.summary_fields['user'][0].name = activity.summary_fields['user'][0].username;
|
||||
}
|
||||
|
||||
var name;
|
||||
if (obj2_obj && obj2_obj.name && !/^_delete/.test(obj2_obj.name)) {
|
||||
obj2_obj['base'] = obj2;
|
||||
descr += obj2 + ' <a href=\"' + BuildUrl(obj2_obj) + '\">'
|
||||
+ obj2_obj.name + '</a>' + ( (activity.operation == 'disassociate') ? ' from ' : ' to ' );
|
||||
descr_nolink += obj2 + ' ' + obj2_obj.name + ( (activity.operation == 'disassociate') ? ' from ' : ' to ' );
|
||||
}
|
||||
else if (obj2) {
|
||||
name = '';
|
||||
if (obj2_obj && obj2_obj.name) {
|
||||
name = ' ' + stripDeleted(obj2_obj.name);
|
||||
.factory('BuildDescription', ['FixUrl', 'BuildUrl',
|
||||
function (FixUrl, BuildUrl) {
|
||||
return function (activity) {
|
||||
|
||||
function stripDeleted(s) {
|
||||
return s.replace(/^_deleted_\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+\+\d+:\d+_/, '');
|
||||
}
|
||||
descr += obj2 + name + ( (activity.operation == 'disassociate') ? ' from ' : ' to ' );
|
||||
descr_nolink += obj2 + name + ( (activity.operation == 'disassociate') ? ' from ' : ' to ' );
|
||||
}
|
||||
if (obj1_obj && obj1_obj.name && !/^\_delete/.test(obj1_obj.name)) {
|
||||
obj1_obj['base'] = obj1;
|
||||
descr += obj1 + ' <a href=\"' + BuildUrl(obj1_obj) + '\">' + obj1_obj.name + '</a>';
|
||||
descr_nolink += obj1 + ' ' + obj1_obj.name;
|
||||
}
|
||||
else if (obj1) {
|
||||
name = '';
|
||||
var name_nolink = '';
|
||||
// find the name in changes, if needed
|
||||
if ( !(obj1_obj && obj1_obj.name) || obj1_obj && obj1_obj.name && /^_delete/.test(obj1_obj.name) ) {
|
||||
if (activity.changes && activity.changes.name) {
|
||||
if (typeof activity.changes.name == 'string') {
|
||||
name = ' ' + activity.changes.name;
|
||||
name_nolink = name;
|
||||
}
|
||||
else if (typeof activity.changes.name == 'object' && Array.isArray(activity.changes.name)) {
|
||||
name = ' ' + activity.changes.name[0];
|
||||
name_nolink = name;
|
||||
}
|
||||
}
|
||||
else if (obj1 == 'job' && obj1_obj && activity.changes && activity.changes.job_template) {
|
||||
// Hack for job activity where the template name is known
|
||||
if (activity.operation != 'delete') {
|
||||
obj1_obj['base'] = obj1;
|
||||
name = ' ' + '<a href=\"' + BuildUrl(obj1_obj) + '\">'+ obj1_obj.id + ' ' + activity.changes.job_template + '</a>';
|
||||
name_nolink = ' ' + obj1_obj.id + ' ' + activity.changes.job_template;
|
||||
}
|
||||
else {
|
||||
name = ' ' + obj1_obj.id + ' ' + activity.changes.job_template;
|
||||
name_nolink = name;
|
||||
}
|
||||
}
|
||||
else if (obj1 == 'job' && obj1_obj) {
|
||||
// Hack for job activity where template name not known
|
||||
if (activity.operation != 'delete') {
|
||||
obj1_obj['base'] = obj1;
|
||||
name = ' ' + '<a href=\"' + BuildUrl(obj1_obj) + '\">' + obj1_obj.id + '</a>';
|
||||
name_nolink = ' ' + obj1_obj.id;
|
||||
}
|
||||
else {
|
||||
name = ' ' + obj1_obj.id;
|
||||
name_nolink = name;
|
||||
}
|
||||
}
|
||||
|
||||
var descr, descr_nolink, obj1, obj2, obj1_obj, obj2_obj, name, name_nolink;
|
||||
|
||||
descr = activity.operation;
|
||||
descr += (/e$/.test(activity.operation)) ? 'd ' : 'ed ';
|
||||
descr_nolink = descr;
|
||||
|
||||
// labels
|
||||
obj1 = activity.object1;
|
||||
obj2 = activity.object2;
|
||||
|
||||
// objects
|
||||
obj1_obj = (activity.summary_fields[obj1]) ? activity.summary_fields[obj1][0] : null;
|
||||
if (obj1 === obj2) {
|
||||
obj2_obj = activity.summary_fields[obj1][1];
|
||||
} else if (activity.summary_fields[obj2]) {
|
||||
obj2_obj = activity.summary_fields[obj2][0];
|
||||
} else {
|
||||
obj2_obj = null;
|
||||
}
|
||||
else if (obj1_obj && obj1_obj.name) {
|
||||
name = ' ' + stripDeleted(obj1_obj.name);
|
||||
name_nolink = name;
|
||||
|
||||
if (obj1 === 'user' || obj2 === 'user') {
|
||||
activity.summary_fields.user[0].name = activity.summary_fields.user[0].username;
|
||||
}
|
||||
descr += obj1 + name;
|
||||
descr_nolink += obj1 + name_nolink;
|
||||
}
|
||||
activity['description'] = descr;
|
||||
activity['description_nolink'] = descr_nolink;
|
||||
}
|
||||
}])
|
||||
|
||||
.factory('ShowDetail', ['$rootScope', 'Rest', 'Alert', 'GenerateForm', 'ProcessErrors', 'GetBasePath', 'FormatDate',
|
||||
'ActivityDetailForm', 'Empty', 'Find',
|
||||
function($rootScope, Rest, Alert, GenerateForm, ProcessErrors, GetBasePath, FormatDate, ActivityDetailForm, Empty, Find) {
|
||||
return function(params) {
|
||||
|
||||
var activity_id = params.activity_id;
|
||||
var parent_scope = params.scope;
|
||||
|
||||
var generator = GenerateForm;
|
||||
var form = ActivityDetailForm;
|
||||
var activity = Find({list: parent_scope.activities, key: 'id', val: activity_id });
|
||||
|
||||
if (activity) {
|
||||
// Setup changes field
|
||||
activity['changes_stringified'] = JSON.stringify(activity['changes'], null, '\t');
|
||||
var n = activity['changes_stringified'].match(/\n/g);
|
||||
var rows = (n) ? n.length : 1;
|
||||
rows = (rows < 1) ? 3 : 10;
|
||||
form.fields['changes'].rows = 10;
|
||||
|
||||
// Load the form
|
||||
var scope = generator.inject(form, { mode: 'edit', modal: true, related: false });
|
||||
scope['changes'] = activity['changes_stringified'];
|
||||
scope['user'] = ( (activity.summary_fields.actor) ? activity.summary_fields.actor.username : 'system' ) +
|
||||
' on ' + FormatDate(new Date(activity['timestamp']));
|
||||
scope['operation'] = activity['description_nolink'];
|
||||
|
||||
scope.formModalAction = function() {
|
||||
$('#form-modal').modal("hide");
|
||||
if (obj2_obj && obj2_obj.name && !/^_delete/.test(obj2_obj.name)) {
|
||||
obj2_obj.base = obj2;
|
||||
descr += obj2 + ' <a href=\"' + BuildUrl(obj2_obj) + '\">' + obj2_obj.name + '</a>' + ((activity.operation === 'disassociate') ? ' from ' : ' to ');
|
||||
descr_nolink += obj2 + ' ' + obj2_obj.name + ((activity.operation === 'disassociate') ? ' from ' : ' to ');
|
||||
} else if (obj2) {
|
||||
name = '';
|
||||
if (obj2_obj && obj2_obj.name) {
|
||||
name = ' ' + stripDeleted(obj2_obj.name);
|
||||
}
|
||||
|
||||
$('#form-modal').on('show.bs.modal', function (e) {
|
||||
$('#form-modal-body').css({
|
||||
width:'auto', //probably not needed
|
||||
height:'auto', //probably not needed
|
||||
'max-height':'100%'
|
||||
descr += obj2 + name + ((activity.operation === 'disassociate') ? ' from ' : ' to ');
|
||||
descr_nolink += obj2 + name + ((activity.operation === 'disassociate') ? ' from ' : ' to ');
|
||||
}
|
||||
if (obj1_obj && obj1_obj.name && !/^\_delete/.test(obj1_obj.name)) {
|
||||
obj1_obj.base = obj1;
|
||||
descr += obj1 + ' <a href=\"' + BuildUrl(obj1_obj) + '\">' + obj1_obj.name + '</a>';
|
||||
descr_nolink += obj1 + ' ' + obj1_obj.name;
|
||||
} else if (obj1) {
|
||||
name = '';
|
||||
name_nolink = '';
|
||||
// find the name in changes, if needed
|
||||
if (!(obj1_obj && obj1_obj.name) || obj1_obj && obj1_obj.name && /^_delete/.test(obj1_obj.name)) {
|
||||
if (activity.changes && activity.changes.name) {
|
||||
if (typeof activity.changes.name === 'string') {
|
||||
name = ' ' + activity.changes.name;
|
||||
name_nolink = name;
|
||||
} else if (typeof activity.changes.name === 'object' && Array.isArray(activity.changes.name)) {
|
||||
name = ' ' + activity.changes.name[0];
|
||||
name_nolink = name;
|
||||
}
|
||||
} else if (obj1 === 'job' && obj1_obj && activity.changes && activity.changes.job_template) {
|
||||
// Hack for job activity where the template name is known
|
||||
if (activity.operation !== 'delete') {
|
||||
obj1_obj.base = obj1;
|
||||
name = ' ' + '<a href=\"' + BuildUrl(obj1_obj) + '\">' + obj1_obj.id + ' ' + activity.changes.job_template + '</a>';
|
||||
name_nolink = ' ' + obj1_obj.id + ' ' + activity.changes.job_template;
|
||||
} else {
|
||||
name = ' ' + obj1_obj.id + ' ' + activity.changes.job_template;
|
||||
name_nolink = name;
|
||||
}
|
||||
} else if (obj1 === 'job' && obj1_obj) {
|
||||
// Hack for job activity where template name not known
|
||||
if (activity.operation !== 'delete') {
|
||||
obj1_obj.base = obj1;
|
||||
name = ' ' + '<a href=\"' + BuildUrl(obj1_obj) + '\">' + obj1_obj.id + '</a>';
|
||||
name_nolink = ' ' + obj1_obj.id;
|
||||
} else {
|
||||
name = ' ' + obj1_obj.id;
|
||||
name_nolink = name;
|
||||
}
|
||||
}
|
||||
} else if (obj1_obj && obj1_obj.name) {
|
||||
name = ' ' + stripDeleted(obj1_obj.name);
|
||||
name_nolink = name;
|
||||
}
|
||||
descr += obj1 + name;
|
||||
descr_nolink += obj1 + name_nolink;
|
||||
}
|
||||
activity.description = descr;
|
||||
activity.description_nolink = descr_nolink;
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
.factory('ShowDetail', ['$rootScope', 'Rest', 'Alert', 'GenerateForm', 'ProcessErrors', 'GetBasePath', 'FormatDate',
|
||||
'ActivityDetailForm', 'Empty', 'Find',
|
||||
function ($rootScope, Rest, Alert, GenerateForm, ProcessErrors, GetBasePath, FormatDate, ActivityDetailForm, Empty, Find) {
|
||||
return function (params) {
|
||||
|
||||
var activity_id = params.activity_id,
|
||||
parent_scope = params.scope,
|
||||
generator = GenerateForm,
|
||||
form = ActivityDetailForm,
|
||||
activity = Find({ list: parent_scope.activities, key: 'id', val: activity_id }),
|
||||
n, rows, scope;
|
||||
|
||||
if (activity) {
|
||||
// Setup changes field
|
||||
activity.changes_stringified = JSON.stringify(activity.changes, null, '\t');
|
||||
n = activity.changes_stringified.match(/\n/g);
|
||||
rows = (n) ? n.length : 1;
|
||||
rows = (rows < 1) ? 3 : 10;
|
||||
form.fields.changes.rows = 10;
|
||||
|
||||
// Load the form
|
||||
scope = generator.inject(form, { mode: 'edit', modal: true, related: false });
|
||||
scope.changes = activity.changes_stringified;
|
||||
scope.user = ((activity.summary_fields.actor) ? activity.summary_fields.actor.username : 'system') +
|
||||
' on ' + FormatDate(new Date(activity.timestamps));
|
||||
scope.operation = activity.description_nolink;
|
||||
|
||||
scope.formModalAction = function () {
|
||||
$('#form-modal').modal("hide");
|
||||
};
|
||||
|
||||
$('#form-modal').on('show.bs.modal', function () {
|
||||
$('#form-modal-body').css({
|
||||
width: 'auto', //probably not needed
|
||||
height: 'auto', //probably not needed
|
||||
'max-height': '100%'
|
||||
});
|
||||
});
|
||||
|
||||
scope.formModalActionLabel = 'OK';
|
||||
scope.formModalCancelShow = false;
|
||||
scope.formModalInfo = false;
|
||||
scope.formModalHeader = "Event " + activity.id;
|
||||
|
||||
if (!scope.$$phase) {
|
||||
scope.$digest();
|
||||
scope.formModalActionLabel = 'OK';
|
||||
scope.formModalCancelShow = false;
|
||||
scope.formModalInfo = false;
|
||||
scope.formModalHeader = "Event " + activity.id;
|
||||
|
||||
if (!scope.$$phase) {
|
||||
scope.$digest();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
}
|
||||
}])
|
||||
|
||||
.factory('Stream', ['$rootScope', '$location', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait', 'StreamList', 'SearchInit',
|
||||
'PaginateInit', 'GenerateList', 'FormatDate', 'ShowStream', 'HideStream', 'BuildDescription', 'FixUrl', 'BuildUrl',
|
||||
'ShowDetail', 'StreamBreadCrumbs', 'setStreamHeight', 'Find', 'Store',
|
||||
function($rootScope, $location, Rest, GetBasePath, ProcessErrors, Wait, StreamList, SearchInit, PaginateInit, GenerateList,
|
||||
.factory('Stream', ['$rootScope', '$location', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait', 'StreamList', 'SearchInit',
|
||||
'PaginateInit', 'GenerateList', 'FormatDate', 'ShowStream', 'HideStream', 'BuildDescription', 'FixUrl', 'BuildUrl',
|
||||
'ShowDetail', 'StreamBreadCrumbs', 'setStreamHeight', 'Find', 'Store',
|
||||
function ($rootScope, $location, Rest, GetBasePath, ProcessErrors, Wait, StreamList, SearchInit, PaginateInit, GenerateList,
|
||||
FormatDate, ShowStream, HideStream, BuildDescription, FixUrl, BuildUrl, ShowDetail, StreamBreadCrumbs, setStreamHeight,
|
||||
Find, Store) {
|
||||
return function(params) {
|
||||
|
||||
var list = StreamList;
|
||||
var defaultUrl = GetBasePath('activity_stream');
|
||||
var view = GenerateList;
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
var parent_scope = params.scope;
|
||||
return function (params) {
|
||||
|
||||
// Hang onto current search params
|
||||
var PreviousSearchParams = Store('CurrentSearchParams');
|
||||
var list = StreamList,
|
||||
defaultUrl = GetBasePath('activity_stream'),
|
||||
view = GenerateList,
|
||||
base = $location.path().replace(/^\//, '').split('/')[0],
|
||||
parent_scope = params.scope,
|
||||
PreviousSearchParams = Store('CurrentSearchParams'),
|
||||
inventory_name = (params && params.inventory_name) ? params.inventory_name : null,
|
||||
url = (params && params.url) ? params.url : null,
|
||||
type, paths, itm, scope;
|
||||
|
||||
// pass in an inventory name to fix breadcrumb display
|
||||
var inventory_name = (params && params.inventory_name) ? params.inventory_name : null;
|
||||
$rootScope.flashMessage = null;
|
||||
|
||||
// url will override the attempt to compute an activity_stream query
|
||||
var url = (params && params.url) ? params.url : null;
|
||||
|
||||
$rootScope.flashMessage = null;
|
||||
|
||||
if (url) {
|
||||
defaultUrl = url;
|
||||
}
|
||||
else {
|
||||
if ($location.path() !== '/home') {
|
||||
// Restrict what we're looking at based on the path
|
||||
var type = (base == 'inventories') ? 'inventory' : base.replace(/s$/,'');
|
||||
var paths = $location.path().split('/');
|
||||
paths.splice(0,1);
|
||||
if (paths.length > 1 && /^\d+/.test(paths[paths.length - 1])) {
|
||||
type = paths[paths.length - 2];
|
||||
type = (type == 'inventories') ? 'inventory' : type.replace(/s$/,'');
|
||||
//defaultUrl += '?object1=' + type + '&object1__id=' +
|
||||
defaultUrl += '?' + type + '__id=' + paths[paths.length - 1];
|
||||
}
|
||||
else if (paths.length > 1) {
|
||||
type = paths[paths.length - 1];
|
||||
type = (type == 'inventories') ? 'inventory' : type.replace(/s$/,'');
|
||||
defaultUrl += '?or__object1=' + type + '&or__object2=' + type;
|
||||
}
|
||||
else {
|
||||
defaultUrl += '?or__object1=' + type + '&or__object2=' + type;
|
||||
if (url) {
|
||||
defaultUrl = url;
|
||||
} else {
|
||||
if ($location.path() !== '/home') {
|
||||
// Restrict what we're looking at based on the path
|
||||
type = (base === 'inventories') ? 'inventory' : base.replace(/s$/, '');
|
||||
paths = $location.path().split('/');
|
||||
paths.splice(0, 1);
|
||||
if (paths.length > 1 && /^\d+/.test(paths[paths.length - 1])) {
|
||||
type = paths[paths.length - 2];
|
||||
type = (type === 'inventories') ? 'inventory' : type.replace(/s$/, '');
|
||||
//defaultUrl += '?object1=' + type + '&object1__id=' +
|
||||
defaultUrl += '?' + type + '__id=' + paths[paths.length - 1];
|
||||
} else if (paths.length > 1) {
|
||||
type = paths[paths.length - 1];
|
||||
type = (type === 'inventories') ? 'inventory' : type.replace(/s$/, '');
|
||||
defaultUrl += '?or__object1=' + type + '&or__object2=' + type;
|
||||
} else {
|
||||
defaultUrl += '?or__object1=' + type + '&or__object2=' + type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add a container for the stream widget
|
||||
$('#tab-content-container').append("<div id=\"stream-container\"><div id=\"stream-content\"></div></div><!-- Stream widget -->");
|
||||
|
||||
StreamBreadCrumbs();
|
||||
// Add a container for the stream widget
|
||||
$('#tab-content-container').append("<div id=\"stream-container\"><div id=\"stream-content\"></div></div><!-- Stream widget -->");
|
||||
|
||||
// Fix inventory name. The way we're doing breadcrumbs doesn't support bind variables.
|
||||
if (inventory_name) {
|
||||
var itm = Find({ list: $rootScope.breadcrumbs, key: 'title', val: '{{ inventory_name }}' });
|
||||
if (itm) {
|
||||
itm.title = inventory_name;
|
||||
StreamBreadCrumbs();
|
||||
|
||||
// Fix inventory name. The way we're doing breadcrumbs doesn't support bind variables.
|
||||
if (inventory_name) {
|
||||
itm = Find({ list: $rootScope.breadcrumbs, key: 'title', val: '{{ inventory_name }}' });
|
||||
if (itm) {
|
||||
itm.title = inventory_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShowStream();
|
||||
|
||||
// Generate the list
|
||||
var scope = view.inject(list, {
|
||||
mode: 'edit',
|
||||
id: 'stream-content',
|
||||
searchSize: 'col-lg-3',
|
||||
secondWidget: true,
|
||||
activityStream: true
|
||||
ShowStream();
|
||||
|
||||
// Generate the list
|
||||
scope = view.inject(list, { mode: 'edit', id: 'stream-content', searchSize: 'col-lg-3', secondWidget: true, activityStream: true });
|
||||
|
||||
// descriptive title describing what AS is showing
|
||||
scope.streamTitle = (params && params.title) ? params.title : null;
|
||||
|
||||
scope.closeStream = function (inUrl) {
|
||||
HideStream();
|
||||
if (scope.searchCleanup) {
|
||||
scope.searchCleanup();
|
||||
}
|
||||
// Restore prior search state
|
||||
if (PreviousSearchParams) {
|
||||
SearchInit({
|
||||
scope: parent_scope,
|
||||
set: PreviousSearchParams.set,
|
||||
list: PreviousSearchParams.list,
|
||||
url: PreviousSearchParams.defaultUrl,
|
||||
iterator: PreviousSearchParams.iterator,
|
||||
sort_order: PreviousSearchParams.sort_order,
|
||||
setWidgets: false
|
||||
});
|
||||
}
|
||||
if (inUrl) {
|
||||
$location.path(inUrl);
|
||||
}
|
||||
};
|
||||
|
||||
scope.refreshStream = function () {
|
||||
scope.search(list.iterator);
|
||||
};
|
||||
|
||||
scope.showDetail = function (id) {
|
||||
ShowDetail({
|
||||
scope: scope,
|
||||
activity_id: id
|
||||
});
|
||||
};
|
||||
|
||||
if (scope.removeStreamPostRefresh) {
|
||||
scope.removeStreamPostRefresh();
|
||||
}
|
||||
scope.removeStreamPostRefresh = scope.$on('PostRefresh', function () {
|
||||
var i, cDate, href, deleted, obj1, obj2;
|
||||
for (i = 0; i < scope.activities.length; i++) {
|
||||
// Convert event_time date to local time zone
|
||||
cDate = new Date(scope.activities[i].timestamp);
|
||||
scope.activities[i].timestamp = FormatDate(cDate);
|
||||
|
||||
if (scope.activities[i].summary_fields.actor) {
|
||||
scope.activities[i].user = "<a href=\"/#/users/" + scope.activities[i].summary_fields.actor.id + "\">" +
|
||||
scope.activities[i].summary_fields.actor.username + "</a>";
|
||||
} else {
|
||||
scope.activities[i].user = 'system';
|
||||
}
|
||||
|
||||
// Objects
|
||||
deleted = /^\_delete/;
|
||||
obj1 = scope.activities[i].object1;
|
||||
obj2 = scope.activities[i].object2;
|
||||
if (obj1 && scope.activities[i].summary_fields[obj1] && scope.activities[i].summary_fields[obj1].name) {
|
||||
if (!deleted.test(scope.activities[i].summary_fields[obj1].name)) {
|
||||
href = BuildUrl(scope.activities[i].summary_fields.object1);
|
||||
scope.activities[i].objects = "<a href=\"" + href + "\">" + scope.activities[i].summary_fields[obj1].name + "</a>";
|
||||
} else {
|
||||
scope.activities[i].objects = scope.activities[i].summary_fields[obj1].name;
|
||||
}
|
||||
} else if (scope.activities[i].object1) {
|
||||
scope.activities[i].objects = scope.activities[i].object1;
|
||||
}
|
||||
if (obj2 && scope.activities[i].summary_fields[obj2] && scope.activities[i].summary_fields[obj2].name) {
|
||||
if (!deleted.test(scope.activities[i].summary_fields.object2.name)) {
|
||||
href = BuildUrl(scope.activities[i].summary_fields.object2);
|
||||
scope.activities[i].objects += ", <a href=\"" + href + "\">" + scope.activities[i].summary_fields[obj2].name + "</a>";
|
||||
} else {
|
||||
scope.activities[i].objects += "," + scope.activities[i].summary_fields[obj2].name;
|
||||
}
|
||||
} else if (scope.activities[i].object2) {
|
||||
scope.activities[i].objects += ", " + scope.activities[i].object2;
|
||||
}
|
||||
|
||||
BuildDescription(scope.activities[i]);
|
||||
|
||||
}
|
||||
// Give ng-repeate a chance to show the data before adjusting the page size.
|
||||
setTimeout(function () {
|
||||
setStreamHeight();
|
||||
}, 500);
|
||||
});
|
||||
|
||||
// descriptive title describing what AS is showing
|
||||
scope.streamTitle = (params && params.title) ? params.title : null;
|
||||
|
||||
scope.closeStream = function(inUrl) {
|
||||
HideStream();
|
||||
if (scope.searchCleanup) {
|
||||
scope.searchCleanup();
|
||||
}
|
||||
// Restore prior search state
|
||||
if (PreviousSearchParams) {
|
||||
SearchInit({
|
||||
scope: parent_scope,
|
||||
set: PreviousSearchParams.set,
|
||||
list: PreviousSearchParams.list,
|
||||
url: PreviousSearchParams.defaultUrl,
|
||||
iterator: PreviousSearchParams.iterator,
|
||||
sort_order: PreviousSearchParams.sort_order,
|
||||
setWidgets: false });
|
||||
}
|
||||
if (inUrl) {
|
||||
$location.path(inUrl);
|
||||
}
|
||||
}
|
||||
|
||||
scope.refreshStream = function() {
|
||||
// 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);
|
||||
}
|
||||
|
||||
scope.showDetail = function(id) {
|
||||
ShowDetail({ scope: scope, activity_id: id });
|
||||
}
|
||||
|
||||
if (scope.removeStreamPostRefresh) {
|
||||
scope.removeStreamPostRefresh();
|
||||
}
|
||||
scope.removeStreamPostRefresh = scope.$on('PostRefresh', function() {
|
||||
var cDate, href, deleted, obj1, obj2;
|
||||
for (var i=0; i < scope['activities'].length; i++) {
|
||||
// Convert event_time date to local time zone
|
||||
cDate = new Date(scope['activities'][i].timestamp);
|
||||
scope['activities'][i].timestamp = FormatDate(cDate);
|
||||
|
||||
if (scope['activities'][i]['summary_fields']['actor']) {
|
||||
scope['activities'][i]['user'] = "<a href=\"/#/users/" + scope['activities'][i]['summary_fields']['actor']['id'] + "\">" +
|
||||
scope['activities'][i]['summary_fields']['actor']['username'] + "</a>";
|
||||
}
|
||||
else {
|
||||
scope['activities'][i]['user'] = 'system';
|
||||
}
|
||||
|
||||
// Objects
|
||||
deleted = /^\_delete/;
|
||||
obj1 = scope['activities'][i].object1;
|
||||
obj2 = scope['activities'][i].object2;
|
||||
if ( obj1 && scope['activities'][i].summary_fields[obj1] && scope['activities'][i].summary_fields[obj1].name) {
|
||||
if ( !deleted.test(scope['activities'][i].summary_fields[obj1].name) ) {
|
||||
href = BuildUrl(scope['activities'][i].summary_fields.object1);
|
||||
scope['activities'][i].objects = "<a href=\"" + href + "\">" + scope['activities'][i].summary_fields[obj1].name + "</a>";
|
||||
}
|
||||
else {
|
||||
scope['activities'][i].objects = scope['activities'][i].summary_fields[obj1].name;
|
||||
}
|
||||
}
|
||||
else if (scope['activities'][i].object1) {
|
||||
scope['activities'][i].objects = scope['activities'][i].object1;
|
||||
}
|
||||
if (obj2 && scope['activities'][i].summary_fields[obj2] && scope['activities'][i].summary_fields[obj2].name) {
|
||||
if ( !deleted.test(scope['activities'][i].summary_fields.object2.name) ) {
|
||||
href = BuildUrl(scope['activities'][i].summary_fields.object2);
|
||||
scope['activities'][i].objects += ", <a href=\"" + href + "\">" + scope['activities'][i].summary_fields[obj2].name + "</a>";
|
||||
}
|
||||
else {
|
||||
scope['activities'][i].objects += "," + scope['activities'][i].summary_fields[obj2].name;
|
||||
}
|
||||
}
|
||||
else if (scope['activities'][i].object2) {
|
||||
scope['activities'][i].objects += ", " + scope['activities'][i].object2;
|
||||
}
|
||||
|
||||
BuildDescription(scope['activities'][i]);
|
||||
|
||||
}
|
||||
// Give ng-repeate a chance to show the data before adjusting the page size.
|
||||
setTimeout(function() { setStreamHeight(); }, 500);
|
||||
});
|
||||
|
||||
// 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);
|
||||
|
||||
}
|
||||
}]);
|
||||
|
||||
};
|
||||
}
|
||||
]);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user