mirror of
https://github.com/ansible/awx.git
synced 2026-04-05 10:09:20 -02:30
Major rename of package from lib to ansibleworks.
This commit is contained in:
227
ansibleworks/ui/static/js/app.js
Normal file
227
ansibleworks/ui/static/js/app.js
Normal file
@@ -0,0 +1,227 @@
|
||||
/************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Our main application mdoule. Declare application routes and perform initialization chores.
|
||||
*
|
||||
*/
|
||||
|
||||
var urlPrefix = '/static/';
|
||||
|
||||
angular.module('ansible', [
|
||||
'RestServices',
|
||||
'AuthService',
|
||||
'Utilities',
|
||||
'OrganizationFormDefinition',
|
||||
'UserFormDefinition',
|
||||
'FormGenerator',
|
||||
'OrganizationListDefinition',
|
||||
'UserListDefinition',
|
||||
'ListGenerator',
|
||||
'AWToolTip',
|
||||
'PromptDialog',
|
||||
'ApiLoader',
|
||||
'RelatedSearchHelper',
|
||||
'RelatedPaginateHelper',
|
||||
'SearchHelper',
|
||||
'PaginateHelper',
|
||||
'RefreshHelper',
|
||||
'AdminListDefinition',
|
||||
'AWDirectives',
|
||||
'InventoriesListDefinition',
|
||||
'InventoryFormDefinition',
|
||||
'InventoryHelper',
|
||||
'AWFilters',
|
||||
'HostFormDefinition',
|
||||
'HostListDefinition',
|
||||
'GroupFormDefinition',
|
||||
'GroupListDefinition',
|
||||
'TeamsListDefinition',
|
||||
'TeamFormDefinition',
|
||||
'TeamHelper',
|
||||
'CredentialsListDefinition',
|
||||
'CredentialFormDefinition',
|
||||
'LookUpHelper',
|
||||
'JobTemplatesListDefinition',
|
||||
'JobTemplateFormDefinition',
|
||||
'JobTemplateHelper',
|
||||
'ProjectsListDefinition',
|
||||
'JobsListDefinition',
|
||||
'JobFormDefinition',
|
||||
'JobEventFormDefinition'
|
||||
])
|
||||
.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/job_events',
|
||||
{ templateUrl: urlPrefix + 'partials/jobs.html', controller: JobEvents }).
|
||||
|
||||
when('/job_templates',
|
||||
{ templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesList }).
|
||||
|
||||
when('/job_templates/add',
|
||||
{ templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesAdd }).
|
||||
|
||||
when('/job_templates/:id',
|
||||
{ templateUrl: urlPrefix + 'partials/job_templates.html', controller: JobTemplatesEdit }).
|
||||
|
||||
when('/projects',
|
||||
{ templateUrl: urlPrefix + 'partials/projects.html', controller: ProjectsList }).
|
||||
|
||||
when('/inventories',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: InventoriesList }).
|
||||
|
||||
when('/inventories/add',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: InventoriesAdd }).
|
||||
|
||||
when('/inventories/:id',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: InventoriesEdit }).
|
||||
|
||||
when('/inventories/:inventory_id/hosts',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: HostsList }).
|
||||
|
||||
when('/inventories/:inventory_id/hosts/add',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: HostsAdd }).
|
||||
|
||||
when('/inventories/:inventory_id/hosts/:host_id',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: HostsEdit }).
|
||||
|
||||
when('/inventories/:inventory_id/groups',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: GroupsList }).
|
||||
|
||||
when('/inventories/:inventory_id/groups/add',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: GroupsAdd }).
|
||||
|
||||
when('/inventories/:inventory_id/groups/:group_id',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: GroupsEdit }).
|
||||
|
||||
when('/inventories/:inventory_id/groups/:group_id/children',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: GroupsList }).
|
||||
|
||||
when('/inventories/:inventory_id/groups/:group_id/children/add',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: GroupsAdd }).
|
||||
|
||||
when('/inventories/:inventory_id/groups/:group_id/children/:child_id',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: GroupsEdit }).
|
||||
|
||||
when('/inventories/:inventory_id/groups/:group_id/hosts',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: HostsList }).
|
||||
|
||||
when('/inventories/:inventory_id/groups/:group_id/hosts/add',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: HostsAdd }).
|
||||
|
||||
when('/inventories/:inventory_id/groups/:group_id/hosts/:host_id',
|
||||
{ templateUrl: urlPrefix + 'partials/inventories.html', controller: HostsEdit }).
|
||||
|
||||
when('/organizations', { templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: OrganizationsList }).
|
||||
|
||||
when('/organizations/add', { templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: OrganizationsAdd }).
|
||||
|
||||
when('/organizations/:id', { templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: OrganizationsEdit }).
|
||||
|
||||
when('/organizations/:id/admins', { templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: AdminsList }).
|
||||
|
||||
when('/organizations/:id/users', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersList }).
|
||||
|
||||
when('/organizations/:id/users/add', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersAdd }).
|
||||
|
||||
when('/organizations/:organization_id/users/:id', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersEdit }).
|
||||
|
||||
when('/teams', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: TeamsList }).
|
||||
|
||||
when('/teams/add', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: TeamsAdd }).
|
||||
|
||||
when('/teams/:id', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: TeamsEdit }).
|
||||
|
||||
when('/teams/:id/users', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: UsersList }).
|
||||
|
||||
when('/teams/:organization_id/users/:id', { templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: UsersEdit }).
|
||||
|
||||
when('/credentials', { templateUrl: urlPrefix + 'partials/credentials.html',
|
||||
controller: CredentialsList }).
|
||||
|
||||
when('/credentials/add', { templateUrl: urlPrefix + 'partials/credentials.html',
|
||||
controller: CredentialsAdd }).
|
||||
|
||||
when('/credentials/:id', { templateUrl: urlPrefix + 'partials/credentials.html',
|
||||
controller: CredentialsEdit }).
|
||||
|
||||
when('/users', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersList }).
|
||||
|
||||
when('/users/add', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersAdd }).
|
||||
|
||||
when('/users/:id', { templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersEdit }).
|
||||
|
||||
when('/login', { templateUrl: urlPrefix + 'partials/login-dialog.html', controller: Authenticate }).
|
||||
|
||||
when('/logout', { templateUrl: urlPrefix + 'partials/login-dialog.html', controller: Authenticate }).
|
||||
|
||||
otherwise({redirectTo: '/'});
|
||||
}])
|
||||
.run(['$rootScope', '$location', 'Authorization','LoadBasePaths',
|
||||
function($rootScope, $location, Authorization, LoadBasePaths) {
|
||||
|
||||
LoadBasePaths();
|
||||
|
||||
$rootScope.breadcrumbs = new Array();
|
||||
$rootScope.crumbCache = new Array();
|
||||
|
||||
$rootScope.$on("$routeChangeStart", function(event, next, current) {
|
||||
// Evaluate the token on each navigation request. Redirect to login page when not valid
|
||||
if (Authorization.isTokenValid() == false) {
|
||||
if ( next.templateUrl != (urlPrefix + 'partials/login.html') ) {
|
||||
$location.path('/login');
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($rootScope.current_user == undefined || $rootScope.current_user == null) {
|
||||
Authorization.restoreUserInfo(); //user must have hit browser refresh
|
||||
}
|
||||
}
|
||||
// Make the correct tab active
|
||||
var base = ($location.path().replace(/^\//,'').split('/')[0]);
|
||||
if (base == '') {
|
||||
$('.nav-tabs a[href="#' + 'organizations' + '"]').tab('show');
|
||||
}
|
||||
else {
|
||||
base.replace(/\_/g,' ');
|
||||
$('.nav-tabs a[href="#' + base + '"]').tab('show');
|
||||
}
|
||||
});
|
||||
|
||||
if (! Authorization.isTokenValid() ) {
|
||||
// When the app first loads, redirect to login page
|
||||
$location.path('/login');
|
||||
}
|
||||
|
||||
// If browser refresh, activate the correct tab
|
||||
var base = ($location.path().replace(/^\//,'').split('/')[0]);
|
||||
if (base == '') {
|
||||
base = 'organizations';
|
||||
$location.path('/organizations');
|
||||
$('.nav-tabs a[href="#' + base + '"]').tab('show');
|
||||
}
|
||||
else {
|
||||
base.replace(/\_/g,' ');
|
||||
$('.nav-tabs a[href="#' + base + '"]').tab('show');
|
||||
}
|
||||
}]);
|
||||
19
ansibleworks/ui/static/js/config.js
Normal file
19
ansibleworks/ui/static/js/config.js
Normal file
@@ -0,0 +1,19 @@
|
||||
/************************************
|
||||
*
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* config.js
|
||||
*
|
||||
* Gobal configuration variables for controlling application behavior.
|
||||
*
|
||||
*/
|
||||
|
||||
var $AnsibleConfig =
|
||||
{
|
||||
session_timeout: 3600, // cookie expiration in seconds. session will expire after this many
|
||||
// seconds of inactivity.
|
||||
|
||||
tooltip_delay: 2000, // Default number of milliseconds to delay displaying/hiding tooltips
|
||||
|
||||
debug_mode: true // Enable console logging messages
|
||||
}
|
||||
114
ansibleworks/ui/static/js/controllers/Admins.js
Normal file
114
ansibleworks/ui/static/js/controllers/Admins.js
Normal file
@@ -0,0 +1,114 @@
|
||||
/************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
var list = AdminList;
|
||||
var defaultUrl = '/api/v1' + '/organizations/' + $routeParams.id + '/users/' ;
|
||||
var view = GenerateList;
|
||||
//var paths = $location.path().replace(/^\//,'').split('/');
|
||||
var mode = 'select';
|
||||
var scope = view.inject(AdminList, { mode: mode }); // Inject our view
|
||||
scope.selected = [];
|
||||
|
||||
SearchInit({ scope: scope, set: 'admins', list: list, url: defaultUrl });
|
||||
PaginateInit({ scope: scope, list: list, url: defaultUrl });
|
||||
scope.search(list.iterator);
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
scope.finishSelection = function() {
|
||||
Rest.setUrl('/api/v1' + $location.path() + '/'); // We're assuming the path matches the api path.
|
||||
// Will this always be true??
|
||||
scope.queue = [];
|
||||
|
||||
scope.$on('callFinished', function() {
|
||||
// We call the API for each selected user. We need to hang out until all the api
|
||||
// calls are finished.
|
||||
if (scope.queue.length == scope.selected.length) {
|
||||
// All the api calls finished
|
||||
$('input[type="checkbox"]').prop("checked",false);
|
||||
scope.selected = [];
|
||||
var errors = 0;
|
||||
for (var i=0; i < scope.queue.length; i++) {
|
||||
if (scope.queue[i].result == 'error') {
|
||||
errors++;
|
||||
// there is no way to know which user raised the error. no data comes
|
||||
// back from the api call.
|
||||
// $('td.username-column').each(function(index) {
|
||||
// if ($(this).text() == scope.queue[i].username) {
|
||||
// $(this).addClass("error");
|
||||
// }
|
||||
// });
|
||||
}
|
||||
}
|
||||
if (errors > 0) {
|
||||
Alert('Error', 'There was an error while adding one or more of the selected users.');
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.selected.length > 0 ) {
|
||||
var user;
|
||||
for (var i=0; i < scope.selected.length; i++) {
|
||||
user = null;
|
||||
for (var j=0; j < scope.admins.length; j++) {
|
||||
if (scope.admins[j].id == scope.selected[i]) {
|
||||
user = scope.admins[j];
|
||||
}
|
||||
}
|
||||
if (user !== null) {
|
||||
Rest.post(user)
|
||||
.success( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'success', data: data, status: status });
|
||||
scope.$emit('callFinished');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
|
||||
scope.$emit('callFinished');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
returnToCaller();
|
||||
}
|
||||
}
|
||||
|
||||
scope.toggle_admin = function(id) {
|
||||
if (scope.selected.indexOf(id) > -1) {
|
||||
scope.selected.splice(scope.selected.indexOf(id),1);
|
||||
}
|
||||
else {
|
||||
scope.selected.push(id);
|
||||
}
|
||||
if (scope[list.iterator + "_" + id + "_class"] == "success") {
|
||||
scope[list.iterator + "_" + id + "_class"] = "";
|
||||
//$('input[name="check_' + id + '"]').checked = false;
|
||||
document.getElementById('check_' + id).checked = false;
|
||||
}
|
||||
else {
|
||||
scope[list.iterator + "_" + id + "_class"] = "success";
|
||||
//$('input[name="check_' + id + '"]').checked = true;
|
||||
document.getElementById('check_' + id).checked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AdminsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'AdminList', 'GenerateList',
|
||||
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller' ];
|
||||
|
||||
74
ansibleworks/ui/static/js/controllers/Authentication.js
Normal file
74
ansibleworks/ui/static/js/controllers/Authentication.js
Normal file
@@ -0,0 +1,74 @@
|
||||
/************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
*
|
||||
* Authentication.js
|
||||
*
|
||||
* Controller functions for user authentication.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function Authenticate($scope, $rootScope, $location, Authorization, ToggleClass, Alert)
|
||||
{
|
||||
// Authorization is injected from AuthService found in services.js
|
||||
|
||||
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, your logged out.
|
||||
//gets set back to true by Authorization.setToken().
|
||||
|
||||
$scope.sessionExpired = Authorization.didSessionExpire(); //Display session timeout message
|
||||
$scope.sessionTimeout = ($AnsibleConfig.session_timeout / 60).toFixed(2)
|
||||
|
||||
// Display the login dialog
|
||||
$('#login-modal').modal({ show: true, keyboard: false, backdrop: false });
|
||||
|
||||
$scope.reset = function() {
|
||||
$('#login-form input').each( function(index) { $(this).val(''); });
|
||||
};
|
||||
|
||||
// Call the API to get an auth token
|
||||
$scope.systemLogin = function(username, password) {
|
||||
$('.api-error').empty();
|
||||
Authorization.retrieveToken(username, password)
|
||||
.success( function(data, status, headers, config) {
|
||||
Authorization.setToken(data.token);
|
||||
$scope.reset();
|
||||
// Get all the profile/access info regarding the logged in user
|
||||
Authorization.getUser()
|
||||
.success(function(data, status, headers, config) {
|
||||
$('#login-modal').modal('hide');
|
||||
Authorization.setUserInfo(data);
|
||||
$location.path('/organizations');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
Alert('Error', 'Failed to get user data from /api/v1/me. GET status: ' + status);
|
||||
});
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
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];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( data.non_field_errors && data.non_field_errors.length > 0 ) {
|
||||
$rootScope.alertHeader = 'Error!';
|
||||
$rootScope.alertBody = data.non_field_errors[0];
|
||||
}
|
||||
else {
|
||||
$rootScope.alertHeader = 'Error!';
|
||||
$rootScope.alertBody = 'The login attempt failed with a status of: ' + status;
|
||||
}
|
||||
$scope.reset();
|
||||
$('#alert-modal').modal({ show: true, keyboard: true, backdrop: 'static' });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
421
ansibleworks/ui/static/js/controllers/Credentials.js
Normal file
421
ansibleworks/ui/static/js/controllers/Credentials.js
Normal file
@@ -0,0 +1,421 @@
|
||||
/************************************
|
||||
* Copyright (c) 2013 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)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
var list = CredentialList;
|
||||
var defaultUrl = GetBasePath('credentials');
|
||||
var view = GenerateList;
|
||||
var paths = $location.path().replace(/^\//,'').split('/');
|
||||
var mode = (paths[0] == 'credentials') ? 'edit' : 'select'; // if base path 'credentials', we're here to add/edit
|
||||
var scope = view.inject(CredentialList, { mode: mode }); // Inject our view
|
||||
scope.selected = [];
|
||||
|
||||
SearchInit({ scope: scope, set: 'credentials', list: list, url: defaultUrl });
|
||||
PaginateInit({ scope: scope, list: list, url: defaultUrl });
|
||||
scope.search(list.iterator);
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
scope.addCredential = function() {
|
||||
$location.path($location.path() + '/add');
|
||||
}
|
||||
|
||||
scope.editCredential = function(id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
}
|
||||
|
||||
scope.deleteCredential = function(id, name) {
|
||||
|
||||
var action = function() {
|
||||
var url = defaultUrl + id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.delete()
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(list.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 });
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete ' + name + '?',
|
||||
action: action
|
||||
});
|
||||
}
|
||||
|
||||
scope.finishSelection = function() {
|
||||
Rest.setUrl(GetBasePath('base') + $location.path() + '/'); // We're assuming the path matches the api path.
|
||||
// Will this always be true??
|
||||
scope.queue = [];
|
||||
|
||||
scope.$on('callFinished', function() {
|
||||
// We call the API for each selected user. We need to hang out until all the api
|
||||
// calls are finished.
|
||||
if (scope.queue.length == scope.selected.length) {
|
||||
// All the api calls finished
|
||||
$('input[type="checkbox"]').prop("checked",false);
|
||||
scope.selected = [];
|
||||
var errors = 0;
|
||||
for (var i=0; i < scope.queue.length; i++) {
|
||||
if (scope.queue[i].result == 'error') {
|
||||
errors++;
|
||||
// there is no way to know which user raised the error. no data comes
|
||||
// back from the api call.
|
||||
// $('td.username-column').each(function(index) {
|
||||
// if ($(this).text() == scope.queue[i].username) {
|
||||
// $(this).addClass("error");
|
||||
// }
|
||||
// });
|
||||
}
|
||||
}
|
||||
if (errors > 0) {
|
||||
Alert('Error', 'There was an error while adding one or more of the selected Credentials.');
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.selected.length > 0 ) {
|
||||
var credential = null;
|
||||
for (var i=0; i < scope.selected.length; i++) {
|
||||
for (var j=0; j < scope.credentials.length; j++) {
|
||||
if (scope.credentials[j].id == scope.selected[i]) {
|
||||
credential = scope.credentials[j];
|
||||
}
|
||||
}
|
||||
if (credential !== null) {
|
||||
Rest.post(credential)
|
||||
.success( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'success', data: data, status: status });
|
||||
scope.$emit('callFinished');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
|
||||
scope.$emit('callFinished');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ReturnToCaller();
|
||||
}
|
||||
}
|
||||
|
||||
scope.toggle_credential = function(id) {
|
||||
if (scope.selected.indexOf(id) > -1) {
|
||||
scope.selected.splice(scope.selected.indexOf(id),1);
|
||||
}
|
||||
else {
|
||||
scope.selected.push(id);
|
||||
}
|
||||
if (scope[list.iterator + "_" + id + "_class"] == "success") {
|
||||
scope[list.iterator + "_" + id + "_class"] = "";
|
||||
//$('input[name="check_' + id + '"]').checked = false;
|
||||
document.getElementById('check_' + id).checked = false;
|
||||
}
|
||||
else {
|
||||
scope[list.iterator + "_" + id + "_class"] = "success";
|
||||
//$('input[name="check_' + id + '"]').checked = true;
|
||||
document.getElementById('check_' + id).checked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CredentialsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'CredentialList', 'GenerateList',
|
||||
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
|
||||
'GetBasePath'];
|
||||
|
||||
|
||||
function CredentialsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
|
||||
GenerateList, SearchInit, PaginateInit, LookUpInit, UserList, TeamList, GetBasePath)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
// Inject dynamic view
|
||||
var defaultUrl = GetBasePath('credentials');
|
||||
var form = CredentialForm;
|
||||
var generator = GenerateForm;
|
||||
var scope = generator.inject(form, {mode: 'add', related: false});
|
||||
generator.reset();
|
||||
LoadBreadCrumbs();
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: ($routeParams.user_id) ? $routeParams.user_id : null,
|
||||
list: UserList,
|
||||
field: 'user'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: ($routeParams.team_id) ? $routeParams.team_id : null,
|
||||
list: TeamList,
|
||||
field: 'team'
|
||||
});
|
||||
|
||||
// Save
|
||||
scope.formSave = function() {
|
||||
Rest.setUrl(defaultUrl);
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
Rest.post(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
ReturnToCaller();
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to add new Credential. Post returned status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
// Reset
|
||||
scope.formReset = function() {
|
||||
// Defaults
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CredentialsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'CredentialForm', 'GenerateForm',
|
||||
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList',
|
||||
'SearchInit', 'PaginateInit', 'LookUpInit', 'UserList', 'TeamList', 'GetBasePath' ];
|
||||
|
||||
|
||||
function CredentialsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, CredentialForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
|
||||
RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInit,
|
||||
UserList, TeamList, Prompt, GetBasePath)
|
||||
{
|
||||
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 master = {};
|
||||
var id = $routeParams.id;
|
||||
var relatedSets = {};
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: ($routeParams.user_id) ? $routeParams.user_id : null,
|
||||
list: UserList,
|
||||
field: 'user'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: ($routeParams.team_id) ? $routeParams.team_id : null,
|
||||
list: TeamList,
|
||||
field: 'team'
|
||||
});
|
||||
|
||||
function setAskCheckboxes() {
|
||||
for (var fld in form.fields) {
|
||||
if (form.fields[fld].type == 'password' && form.fields[fld].ask && 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");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// After Credential is loaded, retrieve each related set and any lookups
|
||||
scope.$on('credentialLoaded', function() {
|
||||
for (var set in relatedSets) {
|
||||
scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
});
|
||||
|
||||
// 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]) {
|
||||
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];
|
||||
}
|
||||
setAskCheckboxes();
|
||||
}
|
||||
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('credentialLoaded');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve Credential: ' + $routeParams.id + '. GET status: ' + status });
|
||||
});
|
||||
|
||||
// Save changes to the parent
|
||||
scope.formSave = function() {
|
||||
Rest.setUrl(defaultUrl + $routeParams.id + '/');
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
Rest.put(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
(base == 'credentials') ? ReturnToCaller() : ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to update Credential: ' + $routeParams.id + '. PUT status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
scope[fld] = master[fld];
|
||||
}
|
||||
setAskCheckboxes();
|
||||
};
|
||||
|
||||
// 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
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CredentialsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'CredentialForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
|
||||
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'LookUpInit', 'UserList', 'TeamList',
|
||||
'Prompt', 'GetBasePath' ];
|
||||
|
||||
349
ansibleworks/ui/static/js/controllers/Groups.js
Normal file
349
ansibleworks/ui/static/js/controllers/Groups.js
Normal file
@@ -0,0 +1,349 @@
|
||||
/************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
*
|
||||
* Groups.js
|
||||
*
|
||||
* Controller functions for Group model.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function GroupsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
|
||||
Alert, GroupList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit,
|
||||
PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
var list = GroupList;
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
var defaultUrl = GetBasePath('groups');
|
||||
var view = GenerateList;
|
||||
|
||||
var scope = view.inject(GroupList, { mode: 'select' }); // Inject our view
|
||||
scope.selected = [];
|
||||
|
||||
SearchInit({ scope: scope, set: 'groups', list: list, url: defaultUrl });
|
||||
PaginateInit({ scope: scope, list: list, url: defaultUrl });
|
||||
scope.search(list.iterator);
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
scope.addGroup = function() {
|
||||
$location.path($location.path() + '/add');
|
||||
}
|
||||
|
||||
scope.editGroup = function(id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
}
|
||||
|
||||
scope.deleteGroup = function(id, name) {
|
||||
|
||||
var action = function() {
|
||||
var url = defaultUrl;
|
||||
Rest.setUrl(url);
|
||||
Rest.post({ id: id, disassociate: 1 })
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(list.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 });
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete group' + name + '?',
|
||||
action: action
|
||||
});
|
||||
}
|
||||
|
||||
scope.finishSelection = function() {
|
||||
var url = ($routeParams.group_id) ? GetBasePath('groups') + $routeParams.group_id + '/children/' :
|
||||
GetBasePath('inventory') + $routeParams.inventory_id + '/groups/';
|
||||
Rest.setUrl(url);
|
||||
scope.queue = [];
|
||||
|
||||
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 (scope.queue.length == scope.selected.length) {
|
||||
// All the api calls finished
|
||||
$('input[type="checkbox"]').prop("checked",false);
|
||||
scope.selected = [];
|
||||
var errors = 0;
|
||||
for (var i=0; i < scope.queue.length; i++) {
|
||||
if (scope.queue[i].result == 'error') {
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
if (errors > 0) {
|
||||
Alert('Error', 'There was an error while adding one or more of the selected groups.');
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.selected.length > 0 ) {
|
||||
var group;
|
||||
for (var i=0; i < scope.selected.length; i++) {
|
||||
group = null;
|
||||
for (var j=0; j < scope.groups.length; j++) {
|
||||
if (scope.groups[j].id == scope.selected[i]) {
|
||||
group = scope.groups[j];
|
||||
}
|
||||
}
|
||||
if (group !== null) {
|
||||
Rest.post(group)
|
||||
.success( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'success', data: data, status: status });
|
||||
scope.$emit('callFinished');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
|
||||
scope.$emit('callFinished');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
}
|
||||
|
||||
scope.toggle_group = function(id) {
|
||||
if (scope.selected.indexOf(id) > -1) {
|
||||
scope.selected.splice(scope.selected.indexOf(id),1);
|
||||
}
|
||||
else {
|
||||
scope.selected.push(id);
|
||||
}
|
||||
if (scope[list.iterator + "_" + id + "_class"] == "success") {
|
||||
scope[list.iterator + "_" + id + "_class"] = "";
|
||||
//$('input[name="check_' + id + '"]').checked = false;
|
||||
document.getElementById('check_' + id).checked = false;
|
||||
}
|
||||
else {
|
||||
scope[list.iterator + "_" + id + "_class"] = "success";
|
||||
//$('input[name="check_' + id + '"]').checked = true;
|
||||
document.getElementById('check_' + id).checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GroupsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupList', 'GenerateList',
|
||||
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
|
||||
'GetBasePath' ];
|
||||
|
||||
|
||||
function GroupsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, GroupForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller,
|
||||
ClearScope, GetBasePath)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
// Inject dynamic view
|
||||
var defaultUrl = ($routeParams.group_id) ? GetBasePath('groups') + $routeParams.group_id + '/children/' :
|
||||
GetBasePath('inventory') + $routeParams.inventory_id + '/groups/';
|
||||
var form = GroupForm;
|
||||
var generator = GenerateForm;
|
||||
var scope = generator.inject(form, {mode: 'add', related: false});
|
||||
generator.reset();
|
||||
var master={};
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
// Save
|
||||
scope.formSave = function() {
|
||||
try {
|
||||
// Make sure we have valid JSON
|
||||
var myjson = JSON.parse(scope.variables);
|
||||
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
if (fld != 'variables') {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
}
|
||||
|
||||
if ($routeParams.inventory_id) {
|
||||
data['inventory'] = $routeParams.inventory_id;
|
||||
}
|
||||
|
||||
Rest.setUrl(defaultUrl);
|
||||
Rest.post(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
if (scope.variables) {
|
||||
Rest.setUrl(data.related.variable_data);
|
||||
Rest.put({data: scope.variables})
|
||||
.success( function(data, status, headers, config) {
|
||||
ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to add group varaibles. PUT returned status: ' + status });
|
||||
});
|
||||
}
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to add new group. Post returned status: ' + status });
|
||||
});
|
||||
}
|
||||
catch(err) {
|
||||
Alert("Error", "Error parsing group variables. Expecting valid JSON. Parser returned " + err);
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
// Defaults
|
||||
generator.reset();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
GroupsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'GroupForm', 'GenerateForm',
|
||||
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GetBasePath' ];
|
||||
|
||||
|
||||
function GroupsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, GroupForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
|
||||
RelatedPaginateInit, ReturnToCaller, ClearScope, GetBasePath)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
var generator = GenerateForm;
|
||||
var form = GroupForm;
|
||||
var defaultUrl = GetBasePath('groups') + $routeParams.group_id + '/';
|
||||
var scope = generator.inject(form, {mode: 'edit', related: true});
|
||||
generator.reset();
|
||||
var master = {};
|
||||
var id = $routeParams.group_id;
|
||||
var relatedSets = {};
|
||||
|
||||
// After the Organization is loaded, retrieve each related set
|
||||
if (scope.groupLoadedRemove) {
|
||||
scope.groupLoadedRemove();
|
||||
}
|
||||
scope.groupLoadedRemove = scope.$on('groupLoaded', function() {
|
||||
for (var set in relatedSets) {
|
||||
scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
if (scope.variable_url) {
|
||||
Rest.setUrl(scope.variable_url);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
if ($.isEmptyObject(data.data)) {
|
||||
scope.variables = "\{\}";
|
||||
}
|
||||
else {
|
||||
scope.variables = data.data;
|
||||
}
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
scope.variables = null;
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve host variables. GET returned status: ' + status });
|
||||
});
|
||||
}
|
||||
else {
|
||||
scope.variables = "\{\}";
|
||||
}
|
||||
});
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Rest.setUrl(defaultUrl);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
LoadBreadCrumbs();
|
||||
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 };
|
||||
}
|
||||
}
|
||||
|
||||
scope.variable_url = data.related.variable_data;
|
||||
|
||||
// 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('groupLoaded');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve group: ' + id + '. GET status: ' + status });
|
||||
});
|
||||
|
||||
// Save changes to the parent
|
||||
scope.formSave = function() {
|
||||
try {
|
||||
// Make sure we have valid JSON
|
||||
var myjson = JSON.parse(scope.variables);
|
||||
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
|
||||
Rest.setUrl(defaultUrl);
|
||||
Rest.put(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
if (scope.variables) {
|
||||
Rest.setUrl(GetBasePath('groups') + data.id + '/variable_data/');
|
||||
Rest.put({data: scope.variables})
|
||||
.success( function(data, status, headers, config) {
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
(base == 'groups') ? ReturnToCaller() : ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to update group varaibles. PUT returned status: ' + status });
|
||||
});
|
||||
}
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
(base == 'groups') ? ReturnToCaller() : ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to update group: ' + id + '. PUT status: ' + status });
|
||||
});
|
||||
}
|
||||
catch(err) {
|
||||
Alert("Error", "Error parsing group variables. Expecting valid JSON. Parser returned " + err);
|
||||
}
|
||||
};
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
scope[fld] = master[fld];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
GroupsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'HostForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
|
||||
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'GetBasePath' ];
|
||||
|
||||
345
ansibleworks/ui/static/js/controllers/Hosts.js
Normal file
345
ansibleworks/ui/static/js/controllers/Hosts.js
Normal file
@@ -0,0 +1,345 @@
|
||||
/************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
*
|
||||
* Hosts.js
|
||||
*
|
||||
* Controller functions for Host model.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function HostsList ($scope, $rootScope, $location, $log, $routeParams, Rest,
|
||||
Alert, HostList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit,
|
||||
ReturnToCaller, ClearScope, ProcessErrors, GetBasePath)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
var list = HostList
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
var defaultUrl = GetBasePath('hosts');
|
||||
var view = GenerateList;
|
||||
var mode = (base == 'hosts') ? 'edit' : 'select';
|
||||
var scope = view.inject(list, { mode: mode }); // Inject our view
|
||||
scope.selected = [];
|
||||
|
||||
SearchInit({ scope: scope, set: 'hosts', list: list, url: defaultUrl });
|
||||
PaginateInit({ scope: scope, list: list, url: defaultUrl });
|
||||
scope.search(list.iterator);
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
scope.addHost = function() {
|
||||
$location.path($location.path() + '/add');
|
||||
}
|
||||
|
||||
scope.editHost = function(id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
}
|
||||
|
||||
scope.deleteHost = function(id, name) {
|
||||
|
||||
var action = function() {
|
||||
var url = defaultUrl;
|
||||
Rest.setUrl(url);
|
||||
Rest.post({ id: id, disassociate: 1 })
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(list.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 });
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete host ' + name + '?',
|
||||
action: action
|
||||
});
|
||||
}
|
||||
|
||||
scope.finishSelection = function() {
|
||||
var url = ($routeParams.group_id) ? GetBasePath('groups') + $routeParams.group_id + '/hosts/' :
|
||||
GetBasePath('inventory') + $routeParams.inventory_id + '/hosts/';
|
||||
|
||||
Rest.setUrl(url); // We're assuming the path matches the api path.
|
||||
// Will this always be true??
|
||||
scope.queue = [];
|
||||
|
||||
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 (scope.queue.length == scope.selected.length) {
|
||||
// All the api calls finished
|
||||
$('input[type="checkbox"]').prop("checked",false);
|
||||
scope.selected = [];
|
||||
var errors = 0;
|
||||
for (var i=0; i < scope.queue.length; i++) {
|
||||
if (scope.queue[i].result == 'error') {
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
if (errors > 0) {
|
||||
Alert('Error', 'There was an error while adding one or more of the selected hosts.');
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.selected.length > 0 ) {
|
||||
var host;
|
||||
for (var i=0; i < scope.selected.length; i++) {
|
||||
host = null;
|
||||
for (var j=0; j < scope.hosts.length; j++) {
|
||||
if (scope.hosts[j].id == scope.selected[i]) {
|
||||
host = scope.hosts[j];
|
||||
}
|
||||
}
|
||||
if (host !== null) {
|
||||
Rest.post(host)
|
||||
.success( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'success', data: data, status: status });
|
||||
scope.$emit('callFinished');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
|
||||
scope.$emit('callFinished');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
}
|
||||
|
||||
scope.toggle_host = function(id) {
|
||||
if (scope.selected.indexOf(id) > -1) {
|
||||
scope.selected.splice(scope.selected.indexOf(id),1);
|
||||
}
|
||||
else {
|
||||
scope.selected.push(id);
|
||||
}
|
||||
if (scope[list.iterator + "_" + id + "_class"] == "success") {
|
||||
scope[list.iterator + "_" + id + "_class"] = "";
|
||||
//$('input[name="check_' + id + '"]').checked = false;
|
||||
document.getElementById('check_' + id).checked = false;
|
||||
}
|
||||
else {
|
||||
scope[list.iterator + "_" + id + "_class"] = "success";
|
||||
//$('input[name="check_' + id + '"]').checked = true;
|
||||
document.getElementById('check_' + id).checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HostsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostList', 'GenerateList',
|
||||
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
|
||||
'GetBasePath' ];
|
||||
|
||||
|
||||
function HostsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, HostForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller,
|
||||
ClearScope, GetBasePath )
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
// Inject dynamic view
|
||||
var defaultUrl = ($routeParams.group_id) ? GetBasePath('groups') + $routeParams.group_id + '/hosts/' :
|
||||
GetBasePath('inventory') + $routeParams.inventory_id + '/hosts/';
|
||||
var form = HostForm;
|
||||
var generator = GenerateForm;
|
||||
var scope = generator.inject(form, {mode: 'add', related: false});
|
||||
generator.reset();
|
||||
var master = {};
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
// Save
|
||||
scope.formSave = function() {
|
||||
Rest.setUrl(defaultUrl);
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
if (fld != 'varaibles') {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
}
|
||||
if ($routeParams.inventory_id) {
|
||||
data['inventory'] = $routeParams.inventory_id;
|
||||
}
|
||||
try {
|
||||
// Make sure we have valid JSON
|
||||
var myjson = JSON.parse(scope.variables);
|
||||
Rest.post(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
if (scope.variables) {
|
||||
Rest.setUrl(data.related.variable_data);
|
||||
Rest.put({data: scope.variables})
|
||||
.success( function(data, status, headers, config) {
|
||||
ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to add host varaibles. POST returned status: ' + status });
|
||||
});
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to add new host. POST returned status: ' + status });
|
||||
});
|
||||
}
|
||||
catch(err) {
|
||||
Alert("Error", "Error parsing host variables. Expecting valid JSON. Parser returned " + err);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
// Defaults
|
||||
generator.reset();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
HostsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'HostForm', 'GenerateForm',
|
||||
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GetBasePath' ];
|
||||
|
||||
|
||||
function HostsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, HostForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
|
||||
RelatedPaginateInit, ReturnToCaller, ClearScope, GetBasePath)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
var defaultUrl = GetBasePath('hosts');
|
||||
var generator = GenerateForm;
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
var form = HostForm;
|
||||
var scope = generator.inject(form, {mode: 'edit', related: true});
|
||||
generator.reset();
|
||||
var master = {};
|
||||
var id = $routeParams.host_id;
|
||||
var relatedSets = {};
|
||||
|
||||
// After form data loads, load related sets and lookups
|
||||
scope.$on('hostLoaded', function() {
|
||||
for (var set in relatedSets) {
|
||||
scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
if (scope.variable_url) {
|
||||
Rest.setUrl(scope.variable_url);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
if ($.isEmptyObject(data.data)) {
|
||||
scope.variables = "\{\}";
|
||||
}
|
||||
else {
|
||||
scope.variables = data.data;
|
||||
}
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
scope.variables = null;
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve host variables. GET returned status: ' + status });
|
||||
});
|
||||
}
|
||||
else {
|
||||
scope.variables = "\{\}";
|
||||
}
|
||||
});
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Rest.setUrl(defaultUrl + ':id/');
|
||||
Rest.get({ params: {id: id} })
|
||||
.success( function(data, status, headers, config) {
|
||||
LoadBreadCrumbs();
|
||||
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 };
|
||||
}
|
||||
}
|
||||
scope.variable_url = data.related.variable_data;
|
||||
// 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('hostLoaded');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve host: ' + id + '. GET status: ' + status });
|
||||
});
|
||||
|
||||
// Save changes to the parent
|
||||
scope.formSave = function() {
|
||||
Rest.setUrl(defaultUrl + id + '/');
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
|
||||
try {
|
||||
// Make sure we have valid JSON
|
||||
var myjson = JSON.parse(scope.variables);
|
||||
Rest.put(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
if (scope.variables) {
|
||||
Rest.setUrl(GetBasePath('hosts') + data.id + '/variable_data/');
|
||||
Rest.put({data: scope.variables})
|
||||
.success( function(data, status, headers, config) {
|
||||
(base == 'hosts') ? ReturnToCaller() : ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to update host varaibles. PUT returned status: ' + status });
|
||||
});
|
||||
}
|
||||
else {
|
||||
(base == 'hosts') ? ReturnToCaller() : ReturnToCaller(1);
|
||||
}
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to update host: ' + id + '. PUT status: ' + status });
|
||||
});
|
||||
}
|
||||
catch(err) {
|
||||
Alert("Error", "Error parsing host variables. Expecting valid JSON. Parser returned " + err);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
scope[fld] = master[fld];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
HostsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'HostForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
|
||||
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'GetBasePath' ];
|
||||
|
||||
458
ansibleworks/ui/static/js/controllers/Inventories.js
Normal file
458
ansibleworks/ui/static/js/controllers/Inventories.js
Normal file
@@ -0,0 +1,458 @@
|
||||
/************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
*
|
||||
* Inventories.js
|
||||
*
|
||||
* Controller functions for the Inventory model.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function InventoriesList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, InventoryList,
|
||||
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
|
||||
ClearScope, ProcessErrors)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
var list = InventoryList;
|
||||
var defaultUrl = '/api/v1/inventories/';
|
||||
var view = GenerateList;
|
||||
var paths = $location.path().replace(/^\//,'').split('/');
|
||||
var mode = (paths[0] == 'inventories') ? 'edit' : 'select'; // if base path 'users', we're here to add/edit users
|
||||
var scope = view.inject(InventoryList, { mode: mode }); // Inject our view
|
||||
scope.selected = [];
|
||||
|
||||
SearchInit({ scope: scope, set: 'inventories', list: list, url: defaultUrl });
|
||||
PaginateInit({ scope: scope, list: list, url: defaultUrl });
|
||||
scope.search(list.iterator);
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
scope.addInventory = function() {
|
||||
$location.path($location.path() + '/add');
|
||||
}
|
||||
|
||||
scope.editInventory = function(id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
}
|
||||
|
||||
scope.deleteInventory = function(id, name) {
|
||||
|
||||
var action = function() {
|
||||
var url = defaultUrl + id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.delete()
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(list.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 });
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete ' + name + '?',
|
||||
action: action
|
||||
});
|
||||
}
|
||||
|
||||
scope.lookupOrganization = function(organization_id) {
|
||||
Rest.setUrl('/api/v1/organization/' + organization_id + '/');
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
return data.name;
|
||||
});
|
||||
}
|
||||
|
||||
scope.finishSelection = function() {
|
||||
Rest.setUrl('/api/v1' + $location.path() + '/'); // We're assuming the path matches the api path.
|
||||
// Will this always be true??
|
||||
scope.queue = [];
|
||||
|
||||
scope.$on('callFinished', function() {
|
||||
// We call the API for each selected user. We need to hang out until all the api
|
||||
// calls are finished.
|
||||
if (scope.queue.length == scope.selected.length) {
|
||||
// All the api calls finished
|
||||
$('input[type="checkbox"]').prop("checked",false);
|
||||
scope.selected = [];
|
||||
var errors = 0;
|
||||
for (var i=0; i < scope.queue.length; i++) {
|
||||
if (scope.queue[i].result == 'error') {
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
if (errors > 0) {
|
||||
Alert('Error', 'There was an error while adding one or more of the selected inventories.');
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.selected.length > 0 ) {
|
||||
var inventory = null;
|
||||
for (var i=0; i < scope.selected.length; i++) {
|
||||
for (var j=0; j < scope.inventories.length; j++) {
|
||||
if (scope.inventories[j].id == scope.selected[i]) {
|
||||
inventory = scope.inventories[j];
|
||||
}
|
||||
}
|
||||
if (inventory !== null) {
|
||||
Rest.post(inventory)
|
||||
.success( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'success', data: data, status: status });
|
||||
scope.$emit('callFinished');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
|
||||
scope.$emit('callFinished');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ReturnToCaller();
|
||||
}
|
||||
}
|
||||
|
||||
scope.toggle_inventory = function(id) {
|
||||
if (scope.selected.indexOf(id) > -1) {
|
||||
scope.selected.splice(scope.selected.indexOf(id),1);
|
||||
}
|
||||
else {
|
||||
scope.selected.push(id);
|
||||
}
|
||||
if (scope[list.iterator + "_" + id + "_class"] == "success") {
|
||||
scope[list.iterator + "_" + id + "_class"] = "";
|
||||
//$('input[name="check_' + id + '"]').checked = false;
|
||||
document.getElementById('check_' + id).checked = false;
|
||||
}
|
||||
else {
|
||||
scope[list.iterator + "_" + id + "_class"] = "success";
|
||||
//$('input[name="check_' + id + '"]').checked = true;
|
||||
document.getElementById('check_' + id).checked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InventoriesList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'InventoryList', 'GenerateList',
|
||||
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors' ];
|
||||
|
||||
|
||||
function InventoriesAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
|
||||
GenerateList, OrganizationList, SearchInit, PaginateInit, LookUpInit)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
// Inject dynamic view
|
||||
var defaultUrl = '/api/v1/inventories/';
|
||||
var form = InventoryForm;
|
||||
var generator = GenerateForm;
|
||||
var scope = generator.inject(form, {mode: 'add', related: false});
|
||||
generator.reset();
|
||||
LoadBreadCrumbs();
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: ($routeParams.organization_id) ? $routeParams.organization_id : null,
|
||||
list: OrganizationList,
|
||||
field: 'organization'
|
||||
});
|
||||
|
||||
// Save
|
||||
scope.formSave = function() {
|
||||
Rest.setUrl(defaultUrl);
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
if ($routeParams.inventory_id) {
|
||||
data.inventory = $routeParams.inventory_id;
|
||||
}
|
||||
Rest.post(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
ReturnToCaller();
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to add new inventory. Post returned status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
// Reset
|
||||
scope.formReset = function() {
|
||||
// Defaults
|
||||
generator.reset();
|
||||
};
|
||||
}
|
||||
|
||||
InventoriesAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm', 'GenerateForm',
|
||||
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'GenerateList',
|
||||
'OrganizationList', 'SearchInit', 'PaginateInit', 'LookUpInit' ];
|
||||
|
||||
|
||||
function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
|
||||
RelatedPaginateInit, ReturnToCaller, ClearScope, LookUpInit, Prompt,
|
||||
OrganizationList, TreeInit, GetBasePath)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
var generator = GenerateForm;
|
||||
var form = InventoryForm;
|
||||
var defaultUrl=GetBasePath('inventory');
|
||||
var scope = generator.inject(form, {mode: 'edit', related: true});
|
||||
generator.reset();
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
var master = {};
|
||||
var id = $routeParams.id;
|
||||
var relatedSets = {};
|
||||
|
||||
// After inventory is loaded, retrieve each related set and any lookups
|
||||
scope.$on('inventoryLoaded', function() {
|
||||
for (var set in relatedSets) {
|
||||
scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
});
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Rest.setUrl(defaultUrl + ':id/');
|
||||
Rest.get({ params: {id: id} })
|
||||
.success( function(data, status, headers, config) {
|
||||
LoadBreadCrumbs({ path: '/inventories/' + id, title: data.name });
|
||||
for (var fld in form.fields) {
|
||||
if (data[fld]) {
|
||||
scope[fld] = data[fld];
|
||||
master[fld] = scope[fld];
|
||||
}
|
||||
if (form.fields[fld].type == 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) {
|
||||
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: data.organization,
|
||||
list: OrganizationList,
|
||||
field: 'organization'
|
||||
});
|
||||
|
||||
var related = data.related;
|
||||
for (var set in form.related) {
|
||||
if (related[set]) {
|
||||
relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
|
||||
}
|
||||
}
|
||||
|
||||
// Load the tree view
|
||||
TreeInit({ scope: scope, inventory: data });
|
||||
|
||||
// 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('inventoryLoaded');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve inventory: ' + $routeParams.id + '. GET status: ' + status });
|
||||
});
|
||||
|
||||
// Save changes to the parent
|
||||
scope.formSave = function() {
|
||||
Rest.setUrl(defaultUrl + $routeParams.id + '/');
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
Rest.put(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
(base == 'inventories') ? ReturnToCaller() : ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to update inventory: ' + $routeParams.id + '. PUT status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
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.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
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
function changePath(path) {
|
||||
// For reasons unknown, calling $location.path(<new path>) from inside
|
||||
// treeController fails to work. This is the work-around.
|
||||
window.location = '/#' + path;
|
||||
};
|
||||
|
||||
scope.treeController = function($node) {
|
||||
var nodeType = $($node).attr('type');
|
||||
if (nodeType == 'host') {
|
||||
return {
|
||||
edit: {
|
||||
label: 'Edit Host',
|
||||
action: function(obj) { changePath($location.path() + '/hosts/' + $(obj).attr('id')); }
|
||||
},
|
||||
delete: {
|
||||
label: 'Delete Host',
|
||||
action: function(obj) {
|
||||
var action_to_take = function() {
|
||||
var url = defaultUrl + $routeParams.id + '/hosts/';
|
||||
Rest.setUrl(url);
|
||||
Rest.post({ id: $(obj).attr('id'), disassociate: 1 })
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
$('#tree-view').jstree("delete_node",obj);
|
||||
})
|
||||
.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 });
|
||||
});
|
||||
};
|
||||
//Force binds to work. Not working usual way.
|
||||
$('#prompt-header').text('Delete');
|
||||
$('#prompt-body').text('Are you sure you want to delete host ' + $(obj).attr('name') + '?');
|
||||
$('#prompt-action-btn').addClass('btn-danger');
|
||||
scope.promptAction = action_to_take; // for some reason this binds?
|
||||
$('#prompt-modal').modal({
|
||||
backdrop: 'static',
|
||||
keyboard: true,
|
||||
show: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nodeType == 'inventory') {
|
||||
return {
|
||||
addGroup: {
|
||||
label: 'Add Group',
|
||||
action: function() { changePath($location.path() + '/groups'); }
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return {
|
||||
addGroup: {
|
||||
label: 'Add Subgroup',
|
||||
action: function(obj) {
|
||||
LoadBreadCrumbs({ path: '/groups/' + $(obj).attr('id'), title: $(obj).attr('name') });
|
||||
changePath($location.path() + '/groups/' + $(obj).attr('id') + '/children');
|
||||
},
|
||||
"_disabled": (nodeType == 'all-hosts-group') ? true : false
|
||||
},
|
||||
addHost: {
|
||||
label: 'Add Host',
|
||||
action: function(obj) {
|
||||
LoadBreadCrumbs({ path: '/groups/' + $(obj).attr('id'), title: $(obj).attr('name') });
|
||||
changePath($location.path() + '/groups/' + $(obj).attr('id') + '/hosts');
|
||||
},
|
||||
"_disabled": (nodeType == 'all-hosts-group') ? true : false
|
||||
},
|
||||
edit: {
|
||||
label: 'Edit Group',
|
||||
action: function(obj) { changePath($location.path() + '/groups/' + $(obj).attr('id')); },
|
||||
separator_before: true,
|
||||
"_disabled": (nodeType == 'all-hosts-group') ? true : false
|
||||
},
|
||||
delete: {
|
||||
label: 'Delete Group',
|
||||
action: function(obj) {
|
||||
var action_to_take = function() {
|
||||
var url = defaultUrl + $routeParams.id + '/groups/';
|
||||
Rest.setUrl(url);
|
||||
Rest.post({ id: $(obj).attr('id'), disassociate: 1 })
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
$('#tree-view').jstree("delete_node",obj);
|
||||
})
|
||||
.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 });
|
||||
});
|
||||
};
|
||||
//Force binds to work. Not working usual way.
|
||||
var parent = $.jstree._reference('#tree-view')._get_parent(obj);
|
||||
$('#prompt-header').text('Delete Group');
|
||||
$('#prompt-body').text('Are you sure you want to remove group ' + $(obj).attr('name') +
|
||||
' from ' + $(parent).attr('name') + '?');
|
||||
$('#prompt-action-btn').addClass('btn-danger');
|
||||
scope.promptAction = action_to_take; // for some reason this binds?
|
||||
$('#prompt-modal').modal({
|
||||
backdrop: 'static',
|
||||
keyboard: true,
|
||||
show: true
|
||||
});
|
||||
},
|
||||
"_disabled": (nodeType == 'all-hosts-group') ? true : false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
InventoriesEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
|
||||
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'LookUpInit', 'Prompt',
|
||||
'OrganizationList', 'TreeInit', 'GetBasePath'];
|
||||
|
||||
551
ansibleworks/ui/static/js/controllers/JobTemplates.js
Normal file
551
ansibleworks/ui/static/js/controllers/JobTemplates.js
Normal file
@@ -0,0 +1,551 @@
|
||||
/************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
*
|
||||
* JobTemplates.js
|
||||
*
|
||||
* Controller functions for the Job Template model.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function JobTemplatesList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobTemplateList,
|
||||
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
|
||||
ClearScope, ProcessErrors, GetBasePath, PromptPasswords, JobTemplateForm, CredentialList,
|
||||
LookUpInit)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
var list = JobTemplateList;
|
||||
var defaultUrl = GetBasePath('job_templates');
|
||||
var view = GenerateList;
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
var mode = (base == 'job_templates') ? 'edit' : 'select';
|
||||
var scope = view.inject(list, { mode: mode });
|
||||
scope.selected = [];
|
||||
|
||||
SearchInit({ scope: scope, set: 'job_templates', list: list, url: defaultUrl });
|
||||
PaginateInit({ scope: scope, list: list, url: defaultUrl });
|
||||
scope.search(list.iterator);
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
scope.addJobTemplate = function() {
|
||||
$location.path($location.path() + '/add');
|
||||
}
|
||||
|
||||
scope.editJobTemplate = function(id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
}
|
||||
|
||||
scope.deleteJobTemplate = function(id, name) {
|
||||
var action = function() {
|
||||
var url = defaultUrl + id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.delete()
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(list.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 });
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete ' + name + '?',
|
||||
action: action
|
||||
});
|
||||
}
|
||||
|
||||
scope.finishSelection = function() {
|
||||
Rest.setUrl(defaultUrl);
|
||||
scope.queue = [];
|
||||
|
||||
if (scope.callFinishedRemove) {
|
||||
scope.callFinishedRemove();
|
||||
}
|
||||
scope.callFinishedRemove = scope.$on('callFinished', function() {
|
||||
// We call the API for each selected user. We need to hang out until all the api
|
||||
// calls are finished.
|
||||
if (scope.queue.length == scope.selected.length) {
|
||||
// All the api calls finished
|
||||
$('input[type="checkbox"]').prop("checked",false);
|
||||
scope.selected = [];
|
||||
var errors = 0;
|
||||
for (var i=0; i < scope.queue.length; i++) {
|
||||
if (scope.queue[i].result == 'error') {
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
if (errors > 0) {
|
||||
Alert('Error', 'There was an error while adding one or more of the selected templates.');
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.selected.length > 0 ) {
|
||||
var template = null;
|
||||
for (var i=0; i < scope.selected.length; i++) {
|
||||
for (var j=0; j < scope.job_templates.length; j++) {
|
||||
if (scope.job_templates[j].id == scope.selected[i]) {
|
||||
template = scope.job_templates[j];
|
||||
}
|
||||
}
|
||||
if (template !== null) {
|
||||
Rest.post(template)
|
||||
.success( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'success', data: data, status: status });
|
||||
scope.$emit('callFinished');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
|
||||
scope.$emit('callFinished');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
}
|
||||
|
||||
scope.toggle_job_template = function(id) {
|
||||
if (scope.selected.indexOf(id) > -1) {
|
||||
scope.selected.splice(scope.selected.indexOf(id),1);
|
||||
}
|
||||
else {
|
||||
scope.selected.push(id);
|
||||
}
|
||||
if (scope[list.iterator + "_" + id + "_class"] == "success") {
|
||||
scope[list.iterator + "_" + id + "_class"] = "";
|
||||
//$('input[name="check_' + id + '"]').checked = false;
|
||||
document.getElementById('check_' + id).checked = false;
|
||||
}
|
||||
else {
|
||||
scope[list.iterator + "_" + id + "_class"] = "success";
|
||||
//$('input[name="check_' + id + '"]').checked = true;
|
||||
document.getElementById('check_' + id).checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
function postJob(data) {
|
||||
// Create the job record
|
||||
(scope.credentialWatchRemove) ? scope.credentialWatchRemove() : null;
|
||||
var dt = new Date().toISOString();
|
||||
Rest.setUrl(data.related.jobs);
|
||||
Rest.post({
|
||||
name: data.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) {
|
||||
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
|
||||
});
|
||||
}
|
||||
else {
|
||||
// No passwords needed, start the job!
|
||||
Rest.setUrl(data.related.start);
|
||||
Rest.post()
|
||||
.success( function(data, status, headers, config) {
|
||||
$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) {
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Failed to create job. POST returned status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
scope.submitJob = function(id) {
|
||||
// Get the job details
|
||||
Rest.setUrl(defaultUrl + id + '/');
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
// Create a job record
|
||||
if (data.credential == '' || data.credential == null) {
|
||||
// Template does not have credential, prompt for one
|
||||
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 });
|
||||
});
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
JobTemplatesList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobTemplateList',
|
||||
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
|
||||
'ProcessErrors','GetBasePath', 'PromptPasswords', 'JobTemplateForm', 'CredentialList', 'LookUpInit'
|
||||
];
|
||||
|
||||
function JobTemplatesAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
|
||||
GetBasePath, InventoryList, CredentialList, ProjectList, LookUpInit)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
// Inject dynamic view
|
||||
var defaultUrl = GetBasePath('job_templates');
|
||||
var form = JobTemplateForm;
|
||||
var generator = GenerateForm;
|
||||
var scope = generator.inject(form, {mode: 'add', related: false});
|
||||
generator.reset();
|
||||
LoadBreadCrumbs();
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: null,
|
||||
list: InventoryList,
|
||||
field: 'inventory'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: null,
|
||||
list: CredentialList,
|
||||
field: 'credential'
|
||||
});
|
||||
|
||||
// Update playbook select whenever project value changes
|
||||
var selectPlaybook = function(oldValue, newValue) {
|
||||
if (oldValue != newValue) {
|
||||
if (scope.project) {
|
||||
var url = GetBasePath('projects') + scope.project + '/playbooks/';
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
var opts = [];
|
||||
for (var i=0; i < data.length; i++) {
|
||||
opts.push(data[i]);
|
||||
}
|
||||
scope.playbook_options = opts;
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to get playbook list for ' + url +'. GET returned status: ' + status });
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Register a watcher on project_name
|
||||
if (scope.selectPlaybookUnregister) {
|
||||
scope.selectPlaybookUnregister();
|
||||
}
|
||||
scope.selectPlaybookUnregister = scope.$watch('project_name', selectPlaybook);
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: null,
|
||||
list: ProjectList,
|
||||
field: 'project'
|
||||
});
|
||||
|
||||
scope.job_type_options = [{ value: 'run', label: 'Run' }, { value: 'check', label: 'Check' }];
|
||||
scope.playbook_options = [];
|
||||
|
||||
// Save
|
||||
scope.formSave = function() {
|
||||
Rest.setUrl(defaultUrl);
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
if (form.fields[fld].type == 'select' && fld != 'playbook') {
|
||||
data[fld] = scope[fld].value;
|
||||
}
|
||||
else {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
}
|
||||
Rest.post(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
(base == 'job_templates') ? ReturnToCaller() : ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to add new project. POST returned status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
// Reset
|
||||
scope.formReset = function() {
|
||||
// Defaults
|
||||
generator.reset();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
JobTemplatesAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobTemplateForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope',
|
||||
'GetBasePath', 'InventoryList', 'CredentialList', 'ProjectList', 'LookUpInit' ];
|
||||
|
||||
|
||||
function JobTemplatesEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
|
||||
RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList, CredentialList,
|
||||
ProjectList, LookUpInit, PromptPasswords, GetBasePath)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
var defaultUrl= GetBasePath('job_templates');
|
||||
var generator = GenerateForm;
|
||||
var form = JobTemplateForm;
|
||||
var scope = generator.inject(form, {mode: 'edit', related: true});
|
||||
generator.reset();
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
var master = {};
|
||||
var id = $routeParams.id;
|
||||
var relatedSets = {};
|
||||
|
||||
|
||||
function getPlaybooks(project) {
|
||||
if (project !== null && project !== '' && project !== undefined) {
|
||||
var url = GetBasePath('projects') + project + '/playbooks/';
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
scope.playbook_options = [];
|
||||
for (var i=0; i < data.length; i++) {
|
||||
scope.playbook_options.push(data[i]);
|
||||
}
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to get playbook list for ' + url +'. GET returned status: ' + status });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Register a watcher on project_name. Refresh the playbook list on change.
|
||||
if (scope.selectPlaybookUnregister) {
|
||||
scope.selectPlaybookUnregister();
|
||||
}
|
||||
scope.selectPlaybookUnregister = scope.$watch('project_name', function(oldValue, newValue) {
|
||||
if (oldValue !== newValue && newValue !== '' && newValue !== null && newValue !== undefined) {
|
||||
scope.playbook = null;
|
||||
getPlaybooks(scope.project);
|
||||
}
|
||||
});
|
||||
|
||||
// Retrieve each related set and populate the playbook list
|
||||
if (scope.jobTemplateLoadedRemove) {
|
||||
scope.jobTemplateLoadedRemove();
|
||||
}
|
||||
scope.jobTemplateLoadedRemove = scope.$on('jobTemplateLoaded', function() {
|
||||
for (var set in relatedSets) {
|
||||
scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
getPlaybooks(scope.project);
|
||||
});
|
||||
|
||||
// Our job type options
|
||||
scope.job_type_options = [{ value: 'run', label: 'Run' }, { value: 'check', label: 'Check' }];
|
||||
scope.playbook_options = null;
|
||||
scope.playbook = null;
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Rest.setUrl(defaultUrl + ':id/');
|
||||
Rest.get({ params: {id: id} })
|
||||
.success( function(data, status, headers, config) {
|
||||
LoadBreadCrumbs({ path: '/job_templates/' + id, title: data.name });
|
||||
for (var fld in form.fields) {
|
||||
if (data[fld] !== null && data[fld] !== undefined) {
|
||||
if (form.fields[fld].type == 'select') {
|
||||
if (scope[fld + '_options'] && scope[fld + '_options'].length > 0) {
|
||||
for (var 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];
|
||||
}
|
||||
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.url = data.url;
|
||||
var related = data.related;
|
||||
for (var set in form.related) {
|
||||
if (related[set]) {
|
||||
relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
|
||||
}
|
||||
}
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: data.inventory,
|
||||
list: InventoryList,
|
||||
field: 'inventory'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: data.credential,
|
||||
list: CredentialList,
|
||||
field: 'credential'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: data.project,
|
||||
list: ProjectList,
|
||||
field: 'project'
|
||||
});
|
||||
|
||||
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
|
||||
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
|
||||
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
|
||||
scope.$emit('jobTemplateLoaded');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve job template: ' + $routeParams.id + '. GET status: ' + status });
|
||||
});
|
||||
|
||||
// Save changes to the parent
|
||||
scope.formSave = function() {
|
||||
Rest.setUrl(defaultUrl + $routeParams.id + '/');
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
if (form.fields[fld].type == 'select' && fld != 'playbook') {
|
||||
data[fld] = scope[fld].value;
|
||||
}
|
||||
else {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
}
|
||||
Rest.put(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
(base == 'job_templates') ? ReturnToCaller() : ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to update team: ' + $routeParams.id + '. PUT status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
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.id + '/' + set);
|
||||
};
|
||||
|
||||
// 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
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
JobTemplatesEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobTemplateForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
|
||||
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList',
|
||||
'ProjectList', 'LookUpInit', 'PromptPasswords', 'GetBasePath'
|
||||
];
|
||||
415
ansibleworks/ui/static/js/controllers/Jobs.js
Normal file
415
ansibleworks/ui/static/js/controllers/Jobs.js
Normal file
@@ -0,0 +1,415 @@
|
||||
/************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
*
|
||||
* Jobs.js
|
||||
*
|
||||
* Controller functions for the Job model.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobList,
|
||||
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
|
||||
ClearScope, ProcessErrors, GetBasePath, LookUpInit)
|
||||
{
|
||||
ClearScope('htmlTemplate');
|
||||
var list = JobList;
|
||||
var defaultUrl = GetBasePath('jobs');
|
||||
var view = GenerateList;
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
var scope = view.inject(list, { mode: 'edit' });
|
||||
scope.selected = [];
|
||||
|
||||
SearchInit({ scope: scope, set: 'jobs', list: list, url: defaultUrl });
|
||||
PaginateInit({ scope: scope, list: list, url: defaultUrl });
|
||||
scope.search(list.iterator);
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
scope.refreshJob = function() {
|
||||
scope.search(list.iterator);
|
||||
}
|
||||
|
||||
scope.editJob = function(id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
}
|
||||
|
||||
scope.viewEvents = function(id) {
|
||||
$location.path($location.path() + '/' + id + '/job_events');
|
||||
}
|
||||
|
||||
scope.deleteJob = function(id, name) {
|
||||
Rest.setUrl(defaultUrl + id + '/');
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
|
||||
var url, action_label, restcall, hdr;
|
||||
|
||||
if (data.status == 'pending') {
|
||||
url = data.related.cancel;
|
||||
action_label = 'cancel';
|
||||
hdr = 'Cancel Job';
|
||||
}
|
||||
else {
|
||||
url = defaultUrl + id + '/';
|
||||
action_label = 'delete';
|
||||
hdr = 'Delete Job';
|
||||
}
|
||||
|
||||
var action = function() {
|
||||
Rest.setUrl(url);
|
||||
if (action_label == 'cancel') {
|
||||
Rest.post()
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(list.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 });
|
||||
});
|
||||
}
|
||||
else {
|
||||
Rest.delete()
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(list.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 });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Prompt({ hdr: hdr,
|
||||
body: 'Are you sure you want to ' + action_label + ' job ' + id + '?',
|
||||
action: action
|
||||
});
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Failed to get job details. GET returned status: ' + status });
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
JobsListCtrl.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobList',
|
||||
'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
|
||||
'ProcessErrors','GetBasePath', 'LookUpInit'
|
||||
];
|
||||
|
||||
|
||||
function JobsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, JobForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
|
||||
RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList, CredentialList,
|
||||
ProjectList, LookUpInit, PromptPasswords, GetBasePath)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
var defaultUrl= GetBasePath('jobs');
|
||||
var generator = GenerateForm;
|
||||
var form = JobForm;
|
||||
|
||||
var scope = generator.inject(form, {mode: 'edit', related: true});
|
||||
generator.reset();
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
var master = {};
|
||||
var id = $routeParams.id;
|
||||
var relatedSets = {};
|
||||
|
||||
|
||||
function getPlaybooks(project) {
|
||||
if (project !== null && project !== '' && project !== undefined) {
|
||||
var url = GetBasePath('projects') + project + '/playbooks/';
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
scope.playbook_options = [];
|
||||
for (var i=0; i < data.length; i++) {
|
||||
scope.playbook_options.push(data[i]);
|
||||
}
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to get playbook list for ' + url +'. GET returned status: ' + status });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Register a watcher on project_name. Refresh the playbook list on change.
|
||||
if (scope.selectPlaybookUnregister) {
|
||||
scope.selectPlaybookUnregister();
|
||||
}
|
||||
scope.selectPlaybookUnregister = scope.$watch('project_name', function(oldValue, newValue) {
|
||||
if (oldValue !== newValue && newValue !== '' && newValue !== null && newValue !== undefined) {
|
||||
scope.playbook = null;
|
||||
getPlaybooks(scope.project);
|
||||
}
|
||||
});
|
||||
|
||||
// Retrieve each related set and populate the playbook list
|
||||
if (scope.jobLoadedRemove) {
|
||||
scope.jobLoadedRemove();
|
||||
}
|
||||
scope.jobLoadedRemove = scope.$on('jobLoaded', function() {
|
||||
|
||||
scope[form.name + 'ReadOnly'] = (scope.status == 'new') ? false : true;
|
||||
|
||||
// Load related sets
|
||||
for (var set in relatedSets) {
|
||||
scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
// Set the playbook lookup
|
||||
getPlaybooks(scope.project);
|
||||
});
|
||||
|
||||
// Our job type options
|
||||
scope.job_type_options = [{ value: 'run', label: 'Run' }, { value: 'check', label: 'Check' }];
|
||||
scope.playbook_options = null;
|
||||
scope.playbook = null;
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Rest.setUrl(defaultUrl + ':id/');
|
||||
Rest.get({ params: {id: id} })
|
||||
.success( function(data, status, headers, config) {
|
||||
LoadBreadCrumbs({ path: '/job_templates/' + id, title: data.name });
|
||||
for (var fld in form.fields) {
|
||||
if (data[fld] !== null && data[fld] !== undefined) {
|
||||
if (form.fields[fld].type == 'select') {
|
||||
if (scope[fld + '_options'] && scope[fld + '_options'].length > 0) {
|
||||
for (var 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];
|
||||
}
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
for (var fld in form.statusFields) {
|
||||
if (data[fld] !== null && data[fld] !== undefined) {
|
||||
scope[fld] = data[fld];
|
||||
}
|
||||
}
|
||||
|
||||
scope.url = data.url;
|
||||
var related = data.related;
|
||||
for (var set in form.related) {
|
||||
if (related[set]) {
|
||||
relatedSets[set] = { url: related[set], iterator: form.related[set].iterator };
|
||||
}
|
||||
}
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: data.inventory,
|
||||
list: InventoryList,
|
||||
field: 'inventory'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: data.credential,
|
||||
list: CredentialList,
|
||||
field: 'credential'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: scope,
|
||||
form: form,
|
||||
current_item: data.project,
|
||||
list: ProjectList,
|
||||
field: 'project'
|
||||
});
|
||||
|
||||
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
|
||||
RelatedSearchInit({ scope: scope, form: form, relatedSets: relatedSets });
|
||||
RelatedPaginateInit({ scope: scope, relatedSets: relatedSets });
|
||||
scope.$emit('jobLoaded');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve job template: ' + $routeParams.id + '. GET status: ' + status });
|
||||
});
|
||||
|
||||
// Save changes to the parent
|
||||
scope.formSave = function() {
|
||||
Rest.setUrl(defaultUrl + $routeParams.id);
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
if (form.fields[fld].type == 'select' && fld != 'playbook') {
|
||||
data[fld] = scope[fld].value;
|
||||
}
|
||||
else {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
}
|
||||
Rest.put(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
(base == 'job_templates') ? ReturnToCaller() : ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to update team: ' + $routeParams.id + '. PUT status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
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.id + '/' + set);
|
||||
};
|
||||
|
||||
// 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
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
JobsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
|
||||
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList',
|
||||
'ProjectList', 'LookUpInit', 'PromptPasswords', 'GetBasePath'
|
||||
];
|
||||
|
||||
|
||||
function JobEvents ($scope, $rootScope, $compile, $location, $log, $routeParams, JobEventForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope, SearchInit,
|
||||
PaginateInit, GetBasePath)
|
||||
{
|
||||
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('jobs') + $routeParams.id + '/job_events/';
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
var master = {};
|
||||
var id = $routeParams.id;
|
||||
var relatedSets = {};
|
||||
|
||||
if (scope.PostRefreshRemove){
|
||||
scope.PostRefreshRemove();
|
||||
}
|
||||
scope.PostRefreshRemove = scope.$on('PostRefresh', function() {
|
||||
|
||||
// Disable Next/Prev buttons when we reach the end/beginning of array
|
||||
scope[form.items.event.iterator + 'NextUrlDisable'] = (scope[form.items.event.iterator + 'NextUrl'] !== null) ? "" : "disabled";
|
||||
scope[form.items.event.iterator + 'PrevUrlDisable'] = (scope[form.items.event.iterator + 'PrevUrl'] !== null) ? "" : "disabled";
|
||||
|
||||
// Set the scope input field values
|
||||
if (scope[form.items.event.set] && scope[form.items.event.set].length > 0) {
|
||||
var results = scope[form.items.event.set][0];
|
||||
for (var fld in form.items.event.fields) {
|
||||
if (fld == 'event_data') {
|
||||
scope.event_data = JSON.stringify(results[fld]);
|
||||
}
|
||||
else {
|
||||
if (results[fld]) {
|
||||
scope[fld] = results[fld];
|
||||
}
|
||||
}
|
||||
}
|
||||
scope['event_status'] = (results.failed) ? 'failed' : 'success';
|
||||
}
|
||||
});
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Rest.setUrl(defaultUrl);
|
||||
Rest.get({ params: {page_size: 1} })
|
||||
.success( function(data, status, headers, config) {
|
||||
var results = data.results[0];
|
||||
scope[form.items.event.iterator + 'NextUrl'] = data.next;
|
||||
scope[form.items.event.iterator + 'PrevUrl'] = data.previous;
|
||||
scope[form.items.event.iterator + 'Count'] = data.count;
|
||||
LoadBreadCrumbs({ path: '/jobs/' + id, title: results["summary_fields"].job.name });
|
||||
for (var fld in form.fields) {
|
||||
if (results[fld]) {
|
||||
scope[fld] = results[fld];
|
||||
}
|
||||
if (form.fields[fld].sourceModel && results.summary_fields[form.fields[fld].sourceModel]) {
|
||||
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
||||
results.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
|
||||
}
|
||||
}
|
||||
scope[form.items.event.set] = data.results;
|
||||
SearchInit({ scope: scope, set: form.items.event.set, list: form.items.event, iterator: form.items.event.iterator, url: defaultUrl });
|
||||
PaginateInit({ scope: scope, list: form.items.event, iterator: form.items.event.iterator, url: defaultUrl , pageSize: 1 });
|
||||
scope.$emit('PostRefresh');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve job event data: ' + $routeParams.id + '. GET status: ' + status });
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
JobEvents.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobEventForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope', 'SearchInit',
|
||||
'PaginateInit', 'GetBasePath' ];
|
||||
|
||||
234
ansibleworks/ui/static/js/controllers/Organizations.js
Normal file
234
ansibleworks/ui/static/js/controllers/Organizations.js
Normal file
@@ -0,0 +1,234 @@
|
||||
/************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
*
|
||||
* Organizations.js
|
||||
*
|
||||
* Controller functions for Organization model.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function OrganizationsList ($scope, $rootScope, $location, $log, Rest, Alert, LoadBreadCrumbs, Prompt,
|
||||
GenerateList, OrganizationList, SearchInit, PaginateInit, ClearScope, ProcessErrors)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
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 = '/api/v1/organizations/';
|
||||
var iterator = list.iterator;
|
||||
$rootScope.flashMessage = null;
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
// 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);
|
||||
|
||||
//getData();
|
||||
|
||||
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() {
|
||||
var url = defaultUrl + id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.delete()
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(list.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 });
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete ' + name + '?',
|
||||
action: action
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
OrganizationsList.$inject=[ '$scope', '$rootScope', '$location', '$log', 'Rest', 'Alert', 'LoadBreadCrumbs', 'Prompt',
|
||||
'GenerateList', 'OrganizationList', 'SearchInit', 'PaginateInit', 'ClearScope', 'ProcessErrors'];
|
||||
|
||||
|
||||
function OrganizationsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ClearScope)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
// Inject dynamic view
|
||||
var form = GenerateForm;
|
||||
var scope = form.inject(OrganizationForm, {mode: 'add', related: false});
|
||||
form.reset();
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
// Save
|
||||
scope.formSave = function() {
|
||||
Rest.setUrl('/api/v1/organizations/');
|
||||
Rest.post({ name: $scope.name,
|
||||
description: $scope.description })
|
||||
.success( function(data, status, headers, config) {
|
||||
$rootScope.flashMessage = "Your changes were successfully saved!";
|
||||
$location.path('/organizations/' + data.id + '/');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, OrganizationForm,
|
||||
{ hdr: 'Error!', msg: 'Failed to add new location. Post returned status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
$rootScope.flashMessage = null;
|
||||
form.reset();
|
||||
};
|
||||
}
|
||||
|
||||
OrganizationsAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'OrganizationForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ClearScope' ];
|
||||
|
||||
|
||||
function OrganizationsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, OrganizationForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
|
||||
RelatedPaginateInit, Prompt, ClearScope)
|
||||
{
|
||||
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 = '/api/v1/organizations/';
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
var master = {};
|
||||
var id = $routeParams.id;
|
||||
var relatedSets = {};
|
||||
|
||||
// After the Organization is loaded, retrieve each related set
|
||||
scope.$on('organizationLoaded', function() {
|
||||
for (var set in relatedSets) {
|
||||
scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
});
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Rest.setUrl(defaultUrl + ':id/');
|
||||
Rest.get({ params: {id: id} })
|
||||
.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() {
|
||||
var params = {};
|
||||
for (var fld in form.fields) {
|
||||
params[fld] = scope[fld];
|
||||
}
|
||||
Rest.setUrl('/api/v1/organizations/' + $routeParams.id + '/');
|
||||
Rest.put(params)
|
||||
.success( function(data, status, headers, config) {
|
||||
master = params;
|
||||
$rootScope.flashMessage = "Your changes were successfully saved!";
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, OrganizationForm,
|
||||
{ hdr: 'Error!', msg: 'Failed to update organization: ' + id + '. PUT status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
// Reset the form
|
||||
scope.formReset = function() {
|
||||
$rootScope.flashMessage = null;
|
||||
form.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.id + '/' + set);
|
||||
};
|
||||
|
||||
// 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
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
OrganizationsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'OrganizationForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
|
||||
'RelatedPaginateInit', 'Prompt', 'ClearScope'];
|
||||
141
ansibleworks/ui/static/js/controllers/Projects.js
Normal file
141
ansibleworks/ui/static/js/controllers/Projects.js
Normal file
@@ -0,0 +1,141 @@
|
||||
/************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
*
|
||||
* Projects.js
|
||||
*
|
||||
* Controller functions for the Projects model.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function ProjectsList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, ProjectList,
|
||||
GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller,
|
||||
ClearScope, ProcessErrors, GetBasePath)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
var list = ProjectList;
|
||||
var defaultUrl = GetBasePath('projects');
|
||||
var view = GenerateList;
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
var mode = (base == 'projects') ? 'edit' : 'select'; // if base path 'credentials', we're here to add/edit
|
||||
var scope = view.inject(list, { mode: mode }); // Inject our view
|
||||
scope.selected = [];
|
||||
|
||||
SearchInit({ scope: scope, set: 'projects', list: list, url: defaultUrl });
|
||||
PaginateInit({ scope: scope, list: list, url: defaultUrl });
|
||||
scope.search(list.iterator);
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
scope.addCredential = function() {
|
||||
$location.path($location.path() + '/add');
|
||||
}
|
||||
|
||||
scope.editCredential = function(id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
}
|
||||
|
||||
scope.deleteCredential = function(id, name) {
|
||||
|
||||
var action = function() {
|
||||
var url = defaultUrl + id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.delete()
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(list.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 });
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete ' + name + '?',
|
||||
action: action
|
||||
});
|
||||
}
|
||||
|
||||
scope.finishSelection = function() {
|
||||
Rest.setUrl(GetBasePath('projects'));
|
||||
scope.queue = [];
|
||||
|
||||
if (scope.callFinishedRemove) {
|
||||
scope.callFinishedRemove();
|
||||
}
|
||||
scope.callFinishedRemoved = scope.$on('callFinished', function() {
|
||||
// We call the API for each selected user. We need to hang out until all the api
|
||||
// calls are finished.
|
||||
if (scope.queue.length == scope.selected.length) {
|
||||
// All the api calls finished
|
||||
$('input[type="checkbox"]').prop("checked",false);
|
||||
scope.selected = [];
|
||||
var errors = 0;
|
||||
for (var i=0; i < scope.queue.length; i++) {
|
||||
if (scope.queue[i].result == 'error') {
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
if (errors > 0) {
|
||||
Alert('Error', 'There was an error while adding one or more of the selected Pojects.');
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.selected.length > 0 ) {
|
||||
var project = null;
|
||||
for (var i=0; i < scope.selected.length; i++) {
|
||||
for (var j=0; j < scope.projects.length; j++) {
|
||||
if (scope.projects[j].id == scope.selected[i]) {
|
||||
project = scope.credentials[j];
|
||||
}
|
||||
}
|
||||
if (project !== null) {
|
||||
Rest.post(project)
|
||||
.success( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'success', data: data, status: status });
|
||||
scope.$emit('callFinished');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
|
||||
scope.$emit('callFinished');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
}
|
||||
|
||||
scope.toggle_project = function(id) {
|
||||
if (scope.selected.indexOf(id) > -1) {
|
||||
scope.selected.splice(scope.selected.indexOf(id),1);
|
||||
}
|
||||
else {
|
||||
scope.selected.push(id);
|
||||
}
|
||||
if (scope[list.iterator + "_" + id + "_class"] == "success") {
|
||||
scope[list.iterator + "_" + id + "_class"] = "";
|
||||
//$('input[name="check_' + id + '"]').checked = false;
|
||||
document.getElementById('check_' + id).checked = false;
|
||||
}
|
||||
else {
|
||||
scope[list.iterator + "_" + id + "_class"] = "success";
|
||||
//$('input[name="check_' + id + '"]').checked = true;
|
||||
document.getElementById('check_' + id).checked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProjectsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'ProjectList', 'GenerateList',
|
||||
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
|
||||
'GetBasePath' ];
|
||||
338
ansibleworks/ui/static/js/controllers/Teams.js
Normal file
338
ansibleworks/ui/static/js/controllers/Teams.js
Normal file
@@ -0,0 +1,338 @@
|
||||
/************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
var list = TeamList;
|
||||
var defaultUrl = '/api/v1/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 = [];
|
||||
|
||||
//SetTeamListeners({ scope: scope, set: 'teams', iterator: list.iterator });
|
||||
SearchInit({ scope: scope, set: 'teams', list: list, url: defaultUrl });
|
||||
PaginateInit({ scope: scope, list: list, url: defaultUrl });
|
||||
scope.search(list.iterator);
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
scope.addTeam = function() {
|
||||
$location.path($location.path() + '/add');
|
||||
}
|
||||
|
||||
scope.editTeam = function(id) {
|
||||
$location.path($location.path() + '/' + id);
|
||||
}
|
||||
|
||||
scope.deleteTeam = function(id, name) {
|
||||
|
||||
var action = function() {
|
||||
var url = defaultUrl + id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.delete()
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(list.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 });
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete ' + name + '?',
|
||||
action: action
|
||||
});
|
||||
}
|
||||
|
||||
scope.lookupOrganization = function(organization_id) {
|
||||
Rest.setUrl('/api/v1/organization/' + organization_id + '/');
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
return data.name;
|
||||
});
|
||||
}
|
||||
|
||||
scope.finishSelection = function() {
|
||||
Rest.setUrl('/api/v1' + $location.path() + '/'); // We're assuming the path matches the api path.
|
||||
// Will this always be true??
|
||||
scope.queue = [];
|
||||
|
||||
scope.$on('callFinished', function() {
|
||||
// We call the API for each selected user. We need to hang out until all the api
|
||||
// calls are finished.
|
||||
if (scope.queue.length == scope.selected.length) {
|
||||
// All the api calls finished
|
||||
$('input[type="checkbox"]').prop("checked",false);
|
||||
scope.selected = [];
|
||||
var errors = 0;
|
||||
for (var i=0; i < scope.queue.length; i++) {
|
||||
if (scope.queue[i].result == 'error') {
|
||||
errors++;
|
||||
// there is no way to know which user raised the error. no data comes
|
||||
// back from the api call.
|
||||
// $('td.username-column').each(function(index) {
|
||||
// if ($(this).text() == scope.queue[i].username) {
|
||||
// $(this).addClass("error");
|
||||
// }
|
||||
// });
|
||||
}
|
||||
}
|
||||
if (errors > 0) {
|
||||
Alert('Error', 'There was an error while adding one or more of the selected teams.');
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.selected.length > 0 ) {
|
||||
var team = null;
|
||||
for (var i=0; i < scope.selected.length; i++) {
|
||||
for (var j=0; j < scope.teams.length; j++) {
|
||||
if (scope.teams[j].id == scope.selected[i]) {
|
||||
team = scope.teams[j];
|
||||
}
|
||||
}
|
||||
if (team !== null) {
|
||||
Rest.post(team)
|
||||
.success( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'success', data: data, status: status });
|
||||
scope.$emit('callFinished');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
|
||||
scope.$emit('callFinished');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ReturnToCaller();
|
||||
}
|
||||
}
|
||||
|
||||
scope.toggle_team = function(id) {
|
||||
if (scope.selected.indexOf(id) > -1) {
|
||||
scope.selected.splice(scope.selected.indexOf(id),1);
|
||||
}
|
||||
else {
|
||||
scope.selected.push(id);
|
||||
}
|
||||
if (scope[list.iterator + "_" + id + "_class"] == "success") {
|
||||
scope[list.iterator + "_" + id + "_class"] = "";
|
||||
//$('input[name="check_' + id + '"]').checked = false;
|
||||
document.getElementById('check_' + id).checked = false;
|
||||
}
|
||||
else {
|
||||
scope[list.iterator + "_" + id + "_class"] = "success";
|
||||
//$('input[name="check_' + id + '"]').checked = true;
|
||||
document.getElementById('check_' + id).checked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TeamsList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'TeamList', 'GenerateList',
|
||||
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
|
||||
'SetTeamListeners' ];
|
||||
|
||||
|
||||
function TeamsAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope,
|
||||
GenerateList, OrganizationList, SearchInit, PaginateInit, TeamLookUpOrganizationInit)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
// Inject dynamic view
|
||||
var defaultUrl = '/api/v1/teams/';
|
||||
var form = TeamForm;
|
||||
var generator = GenerateForm;
|
||||
var scope = generator.inject(form, {mode: 'add', related: false});
|
||||
generator.reset();
|
||||
LoadBreadCrumbs();
|
||||
TeamLookUpOrganizationInit({ scope: scope });
|
||||
|
||||
// Save
|
||||
scope.formSave = function() {
|
||||
Rest.setUrl(defaultUrl);
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
Rest.post(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
ReturnToCaller();
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to add new inventory. 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', 'TeamLookUpOrganizationInit' ];
|
||||
|
||||
|
||||
function TeamsEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, TeamForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
|
||||
RelatedPaginateInit, ReturnToCaller, ClearScope, TeamLookUpOrganizationInit, Prompt)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
var defaultUrl='/api/v1/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.id;
|
||||
var relatedSets = {};
|
||||
|
||||
TeamLookUpOrganizationInit({ scope: scope });
|
||||
|
||||
// Retrieve each related set and any lookups
|
||||
scope.$on('teamLoaded', function() {
|
||||
Rest.setUrl(scope['organization_url']);
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
scope['organization_name'] = data.name;
|
||||
master['organization_name'] = data.name;
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, null,
|
||||
{ hdr: 'Error!', msg: 'Failed to retrieve: ' + scope.orgnization_url + '. GET status: ' + status });
|
||||
});
|
||||
for (var set in relatedSets) {
|
||||
scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
});
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Rest.setUrl(defaultUrl + ':id/');
|
||||
Rest.get({ params: {id: id} })
|
||||
.success( function(data, status, headers, config) {
|
||||
LoadBreadCrumbs({ path: '/teams/' + id, title: data.name });
|
||||
console.log(data);
|
||||
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['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.id + '. GET status: ' + status });
|
||||
});
|
||||
|
||||
// Save changes to the parent
|
||||
scope.formSave = function() {
|
||||
Rest.setUrl(defaultUrl + $routeParams.id);
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
Rest.put(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
(base == 'teams') ? ReturnToCaller() : ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to update team: ' + $routeParams.id + '. PUT status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
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.id + '/' + set);
|
||||
};
|
||||
|
||||
// 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
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TeamsEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'TeamForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
|
||||
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope', 'TeamLookUpOrganizationInit', 'Prompt'
|
||||
];
|
||||
|
||||
287
ansibleworks/ui/static/js/controllers/Users.js
Normal file
287
ansibleworks/ui/static/js/controllers/Users.js
Normal file
@@ -0,0 +1,287 @@
|
||||
/************************************
|
||||
* Copyright (c) 2013 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)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
var list = UserList;
|
||||
var defaultUrl = '/api/v1/users/';
|
||||
var view = GenerateList;
|
||||
var paths = $location.path().replace(/^\//,'').split('/');
|
||||
var mode = (paths[0] == '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 = [];
|
||||
|
||||
SearchInit({ scope: scope, set: 'users', list: list, url: defaultUrl });
|
||||
PaginateInit({ scope: scope, list: list, url: defaultUrl });
|
||||
scope.search(list.iterator);
|
||||
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
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() {
|
||||
var url = defaultUrl + id + '/';
|
||||
Rest.setUrl(url);
|
||||
Rest.delete()
|
||||
.success( function(data, status, headers, config) {
|
||||
$('#prompt-modal').modal('hide');
|
||||
scope.search(list.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 });
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({ hdr: 'Delete',
|
||||
body: 'Are you sure you want to delete ' + name + '?',
|
||||
action: action
|
||||
});
|
||||
}
|
||||
|
||||
scope.finishSelection = function() {
|
||||
Rest.setUrl('/api/v1' + $location.path() + '/'); // We're assuming the path matches the api path.
|
||||
// Will this always be true??
|
||||
scope.queue = [];
|
||||
|
||||
scope.$on('callFinished', function() {
|
||||
// We call the API for each selected user. We need to hang out until all the api
|
||||
// calls are finished.
|
||||
if (scope.queue.length == scope.selected.length) {
|
||||
// All the api calls finished
|
||||
$('input[type="checkbox"]').prop("checked",false);
|
||||
scope.selected = [];
|
||||
var errors = 0;
|
||||
for (var i=0; i < scope.queue.length; i++) {
|
||||
if (scope.queue[i].result == 'error') {
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
if (errors > 0) {
|
||||
Alert('Error', 'There was an error while adding one or more of the selected users.');
|
||||
}
|
||||
else {
|
||||
ReturnToCaller(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.selected.length > 0 ) {
|
||||
var user;
|
||||
for (var i=0; i < scope.selected.length; i++) {
|
||||
user = null;
|
||||
for (var j=0; j < scope.users.length; j++) {
|
||||
if (scope.users[j].id == scope.selected[i]) {
|
||||
user = scope.users[j];
|
||||
}
|
||||
}
|
||||
if (user !== null) {
|
||||
Rest.post(user)
|
||||
.success( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'success', data: data, status: status });
|
||||
scope.$emit('callFinished');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
scope.queue.push({ result: 'error', data: data, status: status, headers: headers });
|
||||
scope.$emit('callFinished');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ReturnToCaller();
|
||||
}
|
||||
}
|
||||
|
||||
scope.toggle_user = function(id) {
|
||||
if (scope.selected.indexOf(id) > -1) {
|
||||
scope.selected.splice(scope.selected.indexOf(id),1);
|
||||
}
|
||||
else {
|
||||
scope.selected.push(id);
|
||||
}
|
||||
if (scope[list.iterator + "_" + id + "_class"] == "success") {
|
||||
scope[list.iterator + "_" + id + "_class"] = "";
|
||||
//$('input[name="check_' + id + '"]').checked = false;
|
||||
document.getElementById('check_' + id).checked = false;
|
||||
}
|
||||
else {
|
||||
scope[list.iterator + "_" + id + "_class"] = "success";
|
||||
//$('input[name="check_' + id + '"]').checked = true;
|
||||
document.getElementById('check_' + id).checked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UsersList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'UserList', 'GenerateList',
|
||||
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors' ];
|
||||
|
||||
|
||||
function UsersAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
// Inject dynamic view
|
||||
var defaultUrl = '/api/v1/organizations/';
|
||||
var form = UserForm;
|
||||
var generator = GenerateForm;
|
||||
var scope = generator.inject(form, {mode: 'add', related: false});
|
||||
generator.reset();
|
||||
|
||||
LoadBreadCrumbs();
|
||||
|
||||
// Save
|
||||
scope.formSave = function() {
|
||||
Rest.setUrl(defaultUrl + $routeParams.id + '/users/');
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
Rest.post(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to add new user. Post returned status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
// Defaults
|
||||
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][fld].$setValidity('awpassmatch', false);
|
||||
}
|
||||
}
|
||||
|
||||
UsersAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'UserForm', 'GenerateForm',
|
||||
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope'];
|
||||
|
||||
|
||||
function UsersEdit ($scope, $rootScope, $compile, $location, $log, $routeParams, UserForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit,
|
||||
RelatedPaginateInit, ReturnToCaller, ClearScope)
|
||||
{
|
||||
ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior
|
||||
//scope.
|
||||
|
||||
var defaultUrl='/api/v1/users/';
|
||||
var generator = GenerateForm;
|
||||
var form = UserForm;
|
||||
var scope = generator.inject(form, {mode: 'edit', related: true});
|
||||
generator.reset();
|
||||
var master = {};
|
||||
var id = $routeParams.id;
|
||||
var relatedSets = {};
|
||||
|
||||
// After the Organization is loaded, retrieve each related set
|
||||
scope.$on('userLoaded', function() {
|
||||
for (var set in relatedSets) {
|
||||
scope.search(relatedSets[set].iterator);
|
||||
}
|
||||
});
|
||||
|
||||
// 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 };
|
||||
}
|
||||
}
|
||||
// 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() {
|
||||
Rest.setUrl(defaultUrl + $routeParams.id + '/');
|
||||
var data = {}
|
||||
for (var fld in form.fields) {
|
||||
data[fld] = scope[fld];
|
||||
}
|
||||
Rest.put(data)
|
||||
.success( function(data, status, headers, config) {
|
||||
var base = $location.path().replace(/^\//,'').split('/')[0];
|
||||
(base == 'users') ? ReturnToCaller() : ReturnToCaller(1);
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
ProcessErrors(scope, data, status, form,
|
||||
{ hdr: 'Error!', msg: 'Failed to update users: ' + $routeParams.id + '. PUT status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
// Cancel
|
||||
scope.formReset = function() {
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
scope[fld] = master[fld];
|
||||
}
|
||||
};
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
UsersEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'UserForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit',
|
||||
'RelatedPaginateInit', 'ReturnToCaller', 'ClearScope'];
|
||||
|
||||
145
ansibleworks/ui/static/js/forms/Credentials.js
Normal file
145
ansibleworks/ui/static/js/forms/Credentials.js
Normal file
@@ -0,0 +1,145 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Credentials.js
|
||||
* Form definition for Credential model
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('CredentialFormDefinition', [])
|
||||
.value(
|
||||
'CredentialForm', {
|
||||
|
||||
addTitle: 'Create Credential', //Legend in add mode
|
||||
editTitle: '{{ name }}', //Legend in edit mode
|
||||
name: 'credential',
|
||||
well: true,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
label: 'Name',
|
||||
type: 'text',
|
||||
addRequired: true,
|
||||
editRequired: true
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
"ssh_username": {
|
||||
label: 'SSH Username',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
"ssh_password": {
|
||||
label: 'SSH Password',
|
||||
type: 'password',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
ngChange: "clearPWConfirm('ssh_password_confirm')",
|
||||
ask: true,
|
||||
clear: true,
|
||||
associated: 'ssh_password_confirm'
|
||||
},
|
||||
"ssh_password_confirm": {
|
||||
label: 'Confirm SSH Password',
|
||||
type: 'password',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPassMatch: true,
|
||||
associated: 'ssh_password'
|
||||
},
|
||||
"ssh_key_data": {
|
||||
label: 'SSH Key',
|
||||
type: 'textarea',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
rows: 10
|
||||
},
|
||||
"ssh_key_unlock": {
|
||||
label: 'Key Password',
|
||||
type: 'password',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
ngChange: "clearPWConfirm('ssh_key_unlock_confirm')",
|
||||
associated: 'ssh_key_unlock_confirm',
|
||||
ask: true,
|
||||
clear: true
|
||||
},
|
||||
"ssh_key_unlock_confirm": {
|
||||
label: 'Confirm Key Password',
|
||||
type: 'password',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPassMatch: true,
|
||||
associated: 'ssh_key_unlock'
|
||||
},
|
||||
"sudo_username": {
|
||||
label: 'Sudo Username',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
"sudo_password": {
|
||||
label: 'Sudo Password',
|
||||
type: 'password',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
ngChange: "clearPWConfirm('sudo_password_confirm')",
|
||||
ask: true,
|
||||
clear: true,
|
||||
associated: 'sudo_password_confirm'
|
||||
},
|
||||
"sudo_password_confirm": {
|
||||
label: 'Confirm Sudo Password',
|
||||
type: 'password',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPassMatch: true,
|
||||
associated: 'sudo_password'
|
||||
},
|
||||
user: {
|
||||
label: 'User',
|
||||
type: 'lookup',
|
||||
sourceModel: 'user',
|
||||
sourceField: 'username',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
ngClick: 'lookUpUser()'
|
||||
},
|
||||
team: {
|
||||
label: 'Team',
|
||||
type: 'lookup',
|
||||
sourceModel: 'team',
|
||||
sourceField: 'name',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
ngClick: 'lookUpTeam()'
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
label: 'Save',
|
||||
icon: 'icon-ok',
|
||||
class: 'btn-success',
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
label: 'Reset',
|
||||
icon: 'icon-remove',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
}
|
||||
|
||||
}); //InventoryForm
|
||||
|
||||
63
ansibleworks/ui/static/js/forms/Groups.js
Normal file
63
ansibleworks/ui/static/js/forms/Groups.js
Normal file
@@ -0,0 +1,63 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Groups.js
|
||||
* Form definition for Group model
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('GroupFormDefinition', [])
|
||||
.value(
|
||||
'GroupForm', {
|
||||
|
||||
addTitle: 'Create Group', //Legend in add mode
|
||||
editTitle: '{{ name }}', //Legend in edit mode
|
||||
name: 'group', //Form name attribute
|
||||
well: true, //Wrap the form with TB well
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
label: 'Name',
|
||||
type: 'text',
|
||||
addRequired: true,
|
||||
editRequired: true
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
variables: {
|
||||
label: 'Variables',
|
||||
type: 'textarea',
|
||||
addRequired: false,
|
||||
editRequird: false,
|
||||
rows: 10,
|
||||
class: 'span12',
|
||||
default: "\{\}"
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
label: 'Save',
|
||||
icon: 'icon-ok',
|
||||
class: 'btn btn-success',
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
label: 'Reset',
|
||||
icon: 'icon-remove',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
}
|
||||
|
||||
}); //UserForm
|
||||
|
||||
68
ansibleworks/ui/static/js/forms/Hosts.js
Normal file
68
ansibleworks/ui/static/js/forms/Hosts.js
Normal file
@@ -0,0 +1,68 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* 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: true, //Wrap the form with TB well
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
label: 'Name',
|
||||
type: 'text',
|
||||
addRequired: true,
|
||||
editRequired: true
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
inventory: {
|
||||
type: 'hidden',
|
||||
includeOnEdit: true,
|
||||
includeOnAdd: true
|
||||
},
|
||||
variables: {
|
||||
label: 'Variables',
|
||||
type: 'textarea',
|
||||
addRequired: false,
|
||||
editRequird: false,
|
||||
rows: 10,
|
||||
class: 'span12',
|
||||
default: "\{\}"
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
label: 'Save',
|
||||
icon: 'icon-ok',
|
||||
class: 'btn-success',
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
label: 'Reset',
|
||||
icon: 'icon-remove',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
}
|
||||
|
||||
}); //UserForm
|
||||
|
||||
110
ansibleworks/ui/static/js/forms/Inventories.js
Normal file
110
ansibleworks/ui/static/js/forms/Inventories.js
Normal file
@@ -0,0 +1,110 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Inventories.js
|
||||
* Form definition for User model
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('InventoryFormDefinition', [])
|
||||
.value(
|
||||
'InventoryForm', {
|
||||
|
||||
addTitle: 'Create Inventory', //Legend in add mode
|
||||
editTitle: '{{ name }}', //Legend in edit mode
|
||||
name: 'inventory',
|
||||
well: true,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
label: 'Name',
|
||||
type: 'text',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
capitalize: true
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
organization: {
|
||||
label: 'Organization',
|
||||
type: 'lookup',
|
||||
sourceModel: 'organization',
|
||||
sourceField: 'name',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
ngClick: 'lookUpOrganization()'
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
label: 'Save',
|
||||
icon: 'icon-ok',
|
||||
class: 'btn-success',
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
label: 'Reset',
|
||||
icon: 'icon-remove',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
// hosts: {
|
||||
// type: 'collection',
|
||||
// title: 'Hosts',
|
||||
// iterator: 'host',
|
||||
// open: false,
|
||||
|
||||
// actions: {
|
||||
// add: {
|
||||
// ngClick: "add('hosts')",
|
||||
// icon: 'icon-plus',
|
||||
// awToolTip: 'Create a new host'
|
||||
// },
|
||||
// },
|
||||
|
||||
// fields: {
|
||||
// name: {
|
||||
// key: true,
|
||||
// label: 'Name'
|
||||
// },
|
||||
// description: {
|
||||
// label: 'Description'
|
||||
// }
|
||||
// },
|
||||
|
||||
// fieldActions: {
|
||||
// edit: {
|
||||
// ngClick: "edit('hosts', \{\{ host.id \}\}, '\{\{ host.name \}\}')",
|
||||
// icon: 'icon-edit',
|
||||
// awToolTip: 'Edit host'
|
||||
// },
|
||||
// delete: {
|
||||
// ngClick: "delete('hosts', \{\{ host.id \}\}, '\{\{ host.name \}\}', 'hosts')",
|
||||
// icon: 'icon-remove',
|
||||
// class: 'btn-danger',
|
||||
// awToolTip: 'Create a new host'
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
groups: {
|
||||
type: 'tree',
|
||||
title: "{{ name }} Children",
|
||||
instructions: "Right click on a host or subgroup to make changes or add additional children.",
|
||||
open: true,
|
||||
actions: { }
|
||||
}
|
||||
}
|
||||
|
||||
}); //InventoryForm
|
||||
|
||||
100
ansibleworks/ui/static/js/forms/JobEvents.js
Normal file
100
ansibleworks/ui/static/js/forms/JobEvents.js
Normal file
@@ -0,0 +1,100 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* JobEvents.js
|
||||
* Form definition for Job Events model
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('JobEventFormDefinition', [])
|
||||
.value(
|
||||
'JobEventForm', {
|
||||
|
||||
editTitle: '{{ name }} Events', //Legend in edit mode
|
||||
name: 'job_events',
|
||||
well: true,
|
||||
fieldsAsHeader: true,
|
||||
|
||||
fields: {
|
||||
job: {
|
||||
label: 'Job',
|
||||
type: 'text',
|
||||
class: 'span1',
|
||||
readonly: true
|
||||
},
|
||||
job_name: {
|
||||
type: 'text',
|
||||
sourceModel: 'job',
|
||||
sourceField: 'name',
|
||||
class: 'span5',
|
||||
readonly: true
|
||||
},
|
||||
job_description: {
|
||||
type: 'text',
|
||||
sourceModel: 'job',
|
||||
sourceField: 'description',
|
||||
class: 'span5',
|
||||
readonly: true
|
||||
}
|
||||
},
|
||||
|
||||
buttons: {
|
||||
|
||||
},
|
||||
|
||||
items: {
|
||||
event: {
|
||||
set: 'job_events',
|
||||
iterator: 'job_event',
|
||||
label: 'Event',
|
||||
fields: {
|
||||
id: {
|
||||
label: 'Event ID',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
class: 'span2',
|
||||
key: true,
|
||||
searchType: 'int'
|
||||
},
|
||||
created: {
|
||||
label: 'Event Timestamp',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
class: 'span4'
|
||||
},
|
||||
event: {
|
||||
label: 'Event',
|
||||
type: 'text',
|
||||
readonly: true
|
||||
},
|
||||
host: {
|
||||
label: 'Host',
|
||||
type: 'text',
|
||||
readonly: true
|
||||
},
|
||||
event_status: {
|
||||
label: 'Event Status',
|
||||
type: 'text',
|
||||
class: 'job-\{\{ event_status \}\}',
|
||||
readonly: true,
|
||||
searchField: 'failed',
|
||||
searchType: 'boolean',
|
||||
searchOptions: [{ name: "success", value: 0 }, { name: "failed", value: 1 }],
|
||||
},
|
||||
event_data: {
|
||||
label: 'Event Data',
|
||||
type: 'textarea',
|
||||
class: 'span12',
|
||||
rows: 10,
|
||||
readonly: true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
}
|
||||
|
||||
}); //Form
|
||||
|
||||
157
ansibleworks/ui/static/js/forms/JobTemplates.js
Normal file
157
ansibleworks/ui/static/js/forms/JobTemplates.js
Normal file
@@ -0,0 +1,157 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* JobTemplates.js
|
||||
* Form definition for Job Template model
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('JobTemplateFormDefinition', [])
|
||||
.value(
|
||||
'JobTemplateForm', {
|
||||
|
||||
addTitle: 'Create Job Templates', //Legend in add mode
|
||||
editTitle: '{{ name }}', //Legend in edit mode
|
||||
name: 'job_templates',
|
||||
well: true,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
label: 'Name',
|
||||
type: 'text',
|
||||
addRequired: true,
|
||||
editRequired: true
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
job_type: {
|
||||
label: 'Job Type',
|
||||
type: 'select',
|
||||
ngOptions: 'type.label for type in job_type_options',
|
||||
default: 'run',
|
||||
addRequired: true,
|
||||
editRequired: true
|
||||
},
|
||||
inventory: {
|
||||
label: 'Inventory',
|
||||
type: 'lookup',
|
||||
sourceModel: 'inventory',
|
||||
sourceField: 'name',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
ngClick: 'lookUpInventory()'
|
||||
},
|
||||
project: {
|
||||
label: 'Project',
|
||||
type: 'lookup',
|
||||
sourceModel: 'project',
|
||||
sourceField: 'name',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
ngClick: 'lookUpProject()',
|
||||
},
|
||||
playbook: {
|
||||
label: 'Playbook',
|
||||
type:'select',
|
||||
ngOptions: 'book for book in playbook_options',
|
||||
id: 'playbook-select',
|
||||
addRequired: true,
|
||||
editRequired: true
|
||||
},
|
||||
credential: {
|
||||
label: 'Credential',
|
||||
type: 'lookup',
|
||||
sourceModel: 'credential',
|
||||
sourceField: 'name',
|
||||
ngClick: 'lookUpCredential()',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
forks: {
|
||||
label: 'Forks',
|
||||
type: 'number',
|
||||
integer: true,
|
||||
min: 0,
|
||||
max: 100,
|
||||
default: 0,
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
limit: {
|
||||
label: 'Limit',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
verbosity: {
|
||||
label: 'Verbosity',
|
||||
type: 'number',
|
||||
integer: true,
|
||||
default: 0,
|
||||
min: 0,
|
||||
max: 3,
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
extra_vars: {
|
||||
label: 'Extra Variables',
|
||||
type: 'textarea',
|
||||
rows: 6,
|
||||
class: 'span4',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
label: 'Save',
|
||||
icon: 'icon-ok',
|
||||
class: 'btn-success',
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
label: 'Reset',
|
||||
icon: 'icon-remove',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
jobs: {
|
||||
type: 'collection',
|
||||
title: 'Jobs',
|
||||
iterator: 'job',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "edit('jobs', \{\{ job.id \}\}, '\{\{ job.name \}\}')",
|
||||
icon: 'icon-edit'
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
}); //InventoryForm
|
||||
|
||||
167
ansibleworks/ui/static/js/forms/Jobs.js
Normal file
167
ansibleworks/ui/static/js/forms/Jobs.js
Normal file
@@ -0,0 +1,167 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Jobs.js
|
||||
* Form definition for Jobs model
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('JobFormDefinition', [])
|
||||
.value(
|
||||
'JobForm', {
|
||||
|
||||
addTitle: 'Create Job', //Legend in add mode
|
||||
editTitle: '{{ name }}', //Legend in edit mode
|
||||
name: 'jobs',
|
||||
well: true,
|
||||
twoColumns: true,
|
||||
allowReadonly: true,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
label: 'Name',
|
||||
type: 'text',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
column: 1
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
column: 1
|
||||
},
|
||||
job_type: {
|
||||
label: 'Job Type',
|
||||
type: 'select',
|
||||
ngOptions: 'type.label for type in job_type_options',
|
||||
default: 'run',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
column: 1
|
||||
},
|
||||
inventory: {
|
||||
label: 'Inventory',
|
||||
type: 'lookup',
|
||||
sourceModel: 'inventory',
|
||||
sourceField: 'name',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
ngClick: 'lookUpInventory()',
|
||||
column: 1
|
||||
},
|
||||
project: {
|
||||
label: 'Project',
|
||||
type: 'lookup',
|
||||
sourceModel: 'project',
|
||||
sourceField: 'name',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
ngClick: 'lookUpProject()',
|
||||
column: 1
|
||||
},
|
||||
playbook: {
|
||||
label: 'Playbook',
|
||||
type:'select',
|
||||
ngOptions: 'book for book in playbook_options',
|
||||
id: 'playbook-select',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
column: 1
|
||||
},
|
||||
credential: {
|
||||
label: 'Credential',
|
||||
type: 'lookup',
|
||||
sourceModel: 'credential',
|
||||
sourceField: 'name',
|
||||
ngClick: 'lookUpCredential()',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
column: 2
|
||||
},
|
||||
forks: {
|
||||
label: 'Forks',
|
||||
type: 'number',
|
||||
integer: true,
|
||||
min: 0,
|
||||
max: 100,
|
||||
default: 0,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
column: 2
|
||||
},
|
||||
limit: {
|
||||
label: 'Limit',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
column: 2
|
||||
},
|
||||
verbosity: {
|
||||
label: 'Verbosity',
|
||||
type: 'number',
|
||||
integer: true,
|
||||
default: 0,
|
||||
min: 0,
|
||||
max: 3,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
column: 2
|
||||
},
|
||||
extra_vars: {
|
||||
label: 'Extra Variables',
|
||||
type: 'textarea',
|
||||
rows: 6,
|
||||
class: 'span5',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
column: 2
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
label: 'Save',
|
||||
icon: 'icon-ok',
|
||||
class: 'btn-success',
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
label: 'Reset',
|
||||
icon: 'icon-remove',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
statusFields: {
|
||||
status: {
|
||||
label: 'Job Status <span class="job-detail-status job-\{\{ status \}\}"><i class="icon-circle"></i> \{\{ status \}\}</span>',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
control: false
|
||||
},
|
||||
result_stdout: {
|
||||
label: 'Standard Out',
|
||||
type: 'textarea',
|
||||
readonly: true,
|
||||
rows: 10,
|
||||
class: 'span12'
|
||||
},
|
||||
result_traceback: {
|
||||
label: 'Traceback',
|
||||
type: 'textarea',
|
||||
readonly: true,
|
||||
rows: 10,
|
||||
class: 'span12'
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
}
|
||||
|
||||
}); //Form
|
||||
|
||||
127
ansibleworks/ui/static/js/forms/Organizations.js
Normal file
127
ansibleworks/ui/static/js/forms/Organizations.js
Normal file
@@ -0,0 +1,127 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* 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/
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
label: 'Name',
|
||||
type: 'text',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
capitalize: true
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
label: 'Save',
|
||||
icon: 'icon-ok',
|
||||
class: 'btn-success',
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
label: 'Reset',
|
||||
icon: 'icon-remove',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
users: {
|
||||
type: 'collection',
|
||||
title: 'Users',
|
||||
iterator: 'user',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
ngClick: "add('users')",
|
||||
icon: 'icon-plus'
|
||||
},
|
||||
},
|
||||
|
||||
fields: {
|
||||
username: {
|
||||
key: true,
|
||||
label: 'Username'
|
||||
},
|
||||
first_name: {
|
||||
label: 'First Name'
|
||||
},
|
||||
last_name: {
|
||||
label: 'Last Name'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "edit('users', \{\{ user.id \}\}, '\{\{ user.username \}\}')",
|
||||
icon: 'icon-edit'
|
||||
},
|
||||
delete: {
|
||||
ngClick: "delete('users', \{\{ user.id \}\}, '\{\{ user.username \}\}', 'users')",
|
||||
icon: 'icon-remove',
|
||||
class: 'btn-danger'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
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?
|
||||
actions: { // Actions displayed top right of list
|
||||
add: {
|
||||
ngClick: "add('admins')",
|
||||
icon: 'icon-plus'
|
||||
}
|
||||
},
|
||||
fields: {
|
||||
username: {
|
||||
key: true,
|
||||
label: 'Username'
|
||||
},
|
||||
first_name: {
|
||||
label: 'First Name'
|
||||
},
|
||||
last_name: {
|
||||
label: 'Last Name'
|
||||
}
|
||||
},
|
||||
fieldActions: { // Actions available on each row
|
||||
delete: {
|
||||
ngClick: "delete('admins', \{\{ admin.id \}\}, '\{\{ admin.username \}\}', 'administrators')",
|
||||
icon: 'icon-remove',
|
||||
class: 'btn-danger'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}); //OrganizationForm
|
||||
|
||||
|
||||
175
ansibleworks/ui/static/js/forms/Teams.js
Normal file
175
ansibleworks/ui/static/js/forms/Teams.js
Normal file
@@ -0,0 +1,175 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 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
|
||||
name: 'team',
|
||||
well: true,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
label: 'Name',
|
||||
type: 'text',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
capitalize: true
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false
|
||||
},
|
||||
organization: {
|
||||
label: 'Organization',
|
||||
type: 'lookup',
|
||||
sourceModel: 'organization',
|
||||
sourceField: 'name',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
ngClick: 'lookUpOrganization()'
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
label: 'Save',
|
||||
icon: 'icon-ok',
|
||||
class: 'btn-success',
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
label: 'Reset',
|
||||
icon: 'icon-remove',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
|
||||
users: {
|
||||
type: 'collection',
|
||||
title: 'Users',
|
||||
iterator: 'user',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
ngClick: "add('users')",
|
||||
icon: 'icon-plus'
|
||||
},
|
||||
},
|
||||
|
||||
fields: {
|
||||
username: {
|
||||
key: true,
|
||||
label: 'Username'
|
||||
},
|
||||
first_name: {
|
||||
label: 'First Name'
|
||||
},
|
||||
last_name: {
|
||||
label: 'Last Name'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "edit('users', \{\{ user.id \}\}, '\{\{ user.username \}\}')",
|
||||
icon: 'icon-edit'
|
||||
},
|
||||
delete: {
|
||||
ngClick: "delete('users', \{\{ user.id \}\}, '\{\{ user.username \}\}', 'users')",
|
||||
icon: 'icon-remove',
|
||||
class: 'btn-danger'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
credentials: {
|
||||
type: 'collection',
|
||||
title: 'Credentials',
|
||||
iterator: 'credential',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
ngClick: "add('credentials')",
|
||||
icon: 'icon-plus'
|
||||
},
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "edit('credentials', \{\{ credential.id \}\}, '\{\{ credential.name \}\}')",
|
||||
icon: 'icon-edit'
|
||||
},
|
||||
delete: {
|
||||
ngClick: "delete('credentials', \{\{ credential.id \}\}, '\{\{ credential.name \}\}', 'credentials')",
|
||||
icon: 'icon-remove',
|
||||
class: 'btn-danger'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
projects: {
|
||||
type: 'collection',
|
||||
title: 'Projects',
|
||||
iterator: 'project',
|
||||
open: false,
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
ngClick: "add('projects')",
|
||||
icon: 'icon-plus'
|
||||
},
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "edit('projects', \{\{ project.id \}\}, '\{\{ project.name \}\}')",
|
||||
icon: 'icon-edit'
|
||||
},
|
||||
delete: {
|
||||
ngClick: "delete('projects', \{\{ project.id \}\}, '\{\{ project.name \}\}', 'projects')",
|
||||
icon: 'icon-remove',
|
||||
class: 'btn-danger'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}); //InventoryForm
|
||||
|
||||
175
ansibleworks/ui/static/js/forms/Users.js
Normal file
175
ansibleworks/ui/static/js/forms/Users.js
Normal file
@@ -0,0 +1,175 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* 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
|
||||
|
||||
fields: {
|
||||
username: {
|
||||
label: 'Username',
|
||||
type: 'text',
|
||||
addRequired: true,
|
||||
editRequired: true
|
||||
},
|
||||
first_name: {
|
||||
label: 'First Name',
|
||||
type: 'text',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
capitalize: true
|
||||
},
|
||||
last_name: {
|
||||
label: 'Last Name',
|
||||
type: 'text',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
capitalize: true
|
||||
},
|
||||
email: {
|
||||
label: 'Email',
|
||||
type: 'email',
|
||||
addRequired: true,
|
||||
editRequired: true
|
||||
},
|
||||
password: {
|
||||
label: 'Password',
|
||||
type: 'password',
|
||||
addRequired: true,
|
||||
editRequired: false,
|
||||
ngChange: "clearPWConfirm('password_confirm')"
|
||||
},
|
||||
password_confirm: {
|
||||
label: 'Confirm Password',
|
||||
type: 'password',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPassMatch: true,
|
||||
associated: 'password'
|
||||
},
|
||||
is_superuser: {
|
||||
label: 'Superuser?',
|
||||
type: 'checkbox',
|
||||
trueValue: 'true',
|
||||
falseValue: 'false',
|
||||
default: 'false',
|
||||
ngShow: "current_user['is_superuser'] == true"
|
||||
}
|
||||
},
|
||||
|
||||
buttons: { //for now always generates <button> tags
|
||||
save: {
|
||||
label: 'Save',
|
||||
icon: 'icon-ok',
|
||||
class: 'btn-success',
|
||||
ngClick: 'formSave()', //$scope.function to call on click, optional
|
||||
ngDisabled: true //Disable when $pristine or $invalid, optional
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
label: 'Reset',
|
||||
icon: 'icon-remove',
|
||||
ngDisabled: true //Disabled when $pristine
|
||||
}
|
||||
},
|
||||
|
||||
related: { //related colletions (and maybe items?)
|
||||
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?
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
organizations: {
|
||||
type: 'collection',
|
||||
title: 'Organizations',
|
||||
iterator: 'organization',
|
||||
open: false,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
teams: {
|
||||
type: 'collection',
|
||||
title: 'Teams',
|
||||
iterator: 'team',
|
||||
open: false,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
projects: {
|
||||
type: 'collection',
|
||||
title: 'Projects',
|
||||
iterator: 'project',
|
||||
open: false,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
credentials: {
|
||||
type: 'collection',
|
||||
title: 'Credentials',
|
||||
iterator: 'credential',
|
||||
open: false,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
}); //UserForm
|
||||
|
||||
114
ansibleworks/ui/static/js/helpers/JobTemplate.js
Normal file
114
ansibleworks/ui/static/js/helpers/JobTemplate.js
Normal file
@@ -0,0 +1,114 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* JobTemplateHelper
|
||||
*
|
||||
*/
|
||||
angular.module('JobTemplateHelper', [ 'RestServices', 'Utilities', 'CredentialFormDefinition' ])
|
||||
.factory('PromptPasswords',['CredentialForm', '$compile', 'Rest', '$location', function(JobTemplateForm, $compile, Rest, $location) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var passwords = params.passwords;
|
||||
var start_url = params.start_url;
|
||||
var form = JobTemplateForm;
|
||||
var html = '';
|
||||
var field, element, dialogScope, fld;
|
||||
|
||||
scope.startJob = function() {
|
||||
$('#password-modal').modal('hide');
|
||||
var pswd = {};
|
||||
$('.password-field').each(function(index) {
|
||||
pswd[$(this).attr('name')] = $(this).val();
|
||||
});
|
||||
Rest.setUrl(start_url);
|
||||
Rest.post(pswd)
|
||||
.success( function(data, status, headers, config) {
|
||||
$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 });
|
||||
});
|
||||
}
|
||||
|
||||
html += html += "<form class=\"form-horizontal\" name=\"password_form\" novalidate>\n";
|
||||
for (var i=0; i < passwords.length; i++) {
|
||||
// Add the password field
|
||||
field = form.fields[passwords[i]];
|
||||
fld = passwords[i];
|
||||
scope[fld] = '';
|
||||
html += "<div class=\"control-group\">\n";
|
||||
html += "<label class=\"control-label\" for=\"" + fld + '">' + field.label + '</label>' + "\n";
|
||||
html += "<div class=\"controls\">\n";
|
||||
html += "<input type=\"password\" ";
|
||||
html += "ng-model=\"" + fld + '" ';
|
||||
html += 'name="' + fld + '" ';
|
||||
html += "class=\"password-field\" ";
|
||||
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 = form.fields[field.associated];
|
||||
scope[fld] = '';
|
||||
html += "<div class=\"control-group\">\n";
|
||||
html += "<label class=\"control-label\" for=\"" + fld + '">' + field.label + '</label>' + "\n";
|
||||
html += "<div class=\"controls\">\n";
|
||||
html += "<input type=\"password\" ";
|
||||
html += "ng-model=\"" + fld + '" ';
|
||||
html += 'name="' + fld + '" ';
|
||||
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();
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
97
ansibleworks/ui/static/js/helpers/Lookup.js
Normal file
97
ansibleworks/ui/static/js/helpers/Lookup.js
Normal file
@@ -0,0 +1,97 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* LookupHelper
|
||||
* Build a lookup dialog
|
||||
*
|
||||
* LookUpInit( {
|
||||
* scope: <form scope>,
|
||||
* form: <form object>,
|
||||
* current_item: <id of item to select on open>,
|
||||
* list: <list object>,
|
||||
* field: <name of the form field with which the lookup is associated>,
|
||||
* hdr: <optional. modal dialog header>
|
||||
* })
|
||||
*/
|
||||
|
||||
angular.module('LookUpHelper', [ 'RestServices', 'Utilities', 'SearchHelper', 'PaginateHelper', 'ListGenerator', 'ApiLoader' ])
|
||||
|
||||
.factory('LookUpInit', ['Alert', 'Rest', 'GenerateList', 'SearchInit', 'PaginateInit', 'GetBasePath',
|
||||
function(Alert, Rest, GenerateList, SearchInit, PaginateInit, GetBasePath) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope; // form scope
|
||||
var form = params.form; // form object
|
||||
var current_item = params.current_item; //id of the item that should be selected on open
|
||||
var list = params.list; // list object
|
||||
var field = params.field; // form field
|
||||
var postAction = params.postAction //action to perform post user selection
|
||||
|
||||
|
||||
// Show pop-up
|
||||
var name = list.iterator.charAt(0).toUpperCase() + list.iterator.substring(1);
|
||||
var defaultUrl = (list.name == 'inventories') ? GetBasePath('inventory') : GetBasePath(list.name);
|
||||
var hdr = (params.hdr) ? params.hdr : 'Select ' + name;
|
||||
|
||||
$('input[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').attr('data-url',defaultUrl +
|
||||
'?' + form.fields[field].sourceField + '__' + 'iexact=:value');
|
||||
$('input[name="' + form.fields[field].sourceModel + '_' + form.fields[field].sourceField + '"]').attr('data-source',field);
|
||||
|
||||
scope['lookUp' + name] = function() {
|
||||
var listGenerator = GenerateList;
|
||||
var listScope = listGenerator.inject(list, { mode: 'lookup', hdr: hdr });
|
||||
listScope.selectAction = function() {
|
||||
var found = false;
|
||||
var name;
|
||||
for (var i=0; i < listScope[list.name].length; i++) {
|
||||
if (listScope[list.iterator + "_" + listScope[list.name][i].id + "_class"] == "success") {
|
||||
found = true;
|
||||
scope[field] = listScope[list.name][i].id;
|
||||
if (scope[form.name + '_form'] && form.fields[field] && form.fields[field].sourceModel) {
|
||||
scope[form.fields[field].sourceModel + '_' + form.fields[field].sourceField] =
|
||||
listScope[list.name][i][form.fields[field].sourceField];
|
||||
if (scope[form.name + '_form'][form.fields[field].sourceModel + '_' + form.fields[field].sourceField]) {
|
||||
scope[form.name + '_form'][form.fields[field].sourceModel + '_' + form.fields[field].sourceField]
|
||||
.$setValidity('awlookup',true);
|
||||
}
|
||||
}
|
||||
if (scope[form.name + '_form']) {
|
||||
scope[form.name + '_form'].$setDirty();
|
||||
}
|
||||
listGenerator.hide();
|
||||
}
|
||||
}
|
||||
if (found == false) {
|
||||
Alert('Missing Selection', 'Oops, you failed to make a selection. Click on a row to make your selection, ' +
|
||||
'and then click the Select button.');
|
||||
}
|
||||
else {
|
||||
console.log('found!');
|
||||
if (postAction) {
|
||||
postAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listScope['toggle_' + list.iterator] = 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' });
|
||||
listScope.search(list.iterator);
|
||||
if (current_item) {
|
||||
listScope['toggle_' + list.iterator](current_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
89
ansibleworks/ui/static/js/helpers/api-defaults.js
Normal file
89
ansibleworks/ui/static/js/helpers/api-defaults.js
Normal file
@@ -0,0 +1,89 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* 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;
|
||||
|
||||
function lookup(key) {
|
||||
var result = {};
|
||||
for (id in $rootScope.apiDefaults) {
|
||||
if (id == key || id.iterator == key) {
|
||||
result[id] = defaults[id];
|
||||
break;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}]);
|
||||
214
ansibleworks/ui/static/js/helpers/inventory.js
Normal file
214
ansibleworks/ui/static/js/helpers/inventory.js
Normal file
@@ -0,0 +1,214 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* InventoryHelper
|
||||
* 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',
|
||||
'SearchHelper', 'PaginateHelper', 'ListGenerator', 'AuthService'
|
||||
])
|
||||
|
||||
.factory('TreeInit', ['Alert', 'Rest', 'Authorization', '$http',
|
||||
function(Alert, Rest, Authorization, $http) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var inventory = params.inventory;
|
||||
var groups = inventory.related.root_groups;
|
||||
var hosts = inventory.related.hosts;
|
||||
var inventory_name = inventory.name;
|
||||
var inventory_url = inventory.url;
|
||||
var inventory_id = inventory.id;
|
||||
var tree_id = '#tree-view';
|
||||
|
||||
var treeData = [];
|
||||
|
||||
|
||||
// On group expand, fetch and add hosts
|
||||
if (scope.loadHostsRemove) {
|
||||
scope.loadHostsRemove();
|
||||
}
|
||||
scope.loadHostsRemove = scope.$on('loadHosts', function(){
|
||||
var node = scope.selected_node;
|
||||
var url = $(node).attr('hosts');
|
||||
var children = [];
|
||||
// Rest and $http refuse to work. Seems we've hit a nesting limit at this point?
|
||||
$.ajax({
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
headers: { 'Authorization': 'Token ' + Authorization.getToken() }
|
||||
}).done( function(data) {
|
||||
for (var i=0; i < data.results.length; i++) {
|
||||
// Add each host to the group node
|
||||
$(tree_id).jstree("create_node", node, "inside", {
|
||||
data: {
|
||||
title: data.results[i].name,
|
||||
icon: '/'
|
||||
},
|
||||
attr: {
|
||||
id: data.results[i].id,
|
||||
type: 'host',
|
||||
name: data.results[i].name,
|
||||
description: data.results[i].description,
|
||||
url: data.results[i].url,
|
||||
variable_data: data.results[i].varaible_data,
|
||||
inventory: data.results[i].related.inventory,
|
||||
job_events: data.results[i].related.job_events
|
||||
}
|
||||
});
|
||||
}
|
||||
// Open the group node
|
||||
$(tree_id).jstree("open_node", node);
|
||||
});
|
||||
});
|
||||
|
||||
// After loading the Inventory top-level data, initialize the tree
|
||||
if (scope.buildTreeRemove) {
|
||||
scope.buildTreeRemove();
|
||||
}
|
||||
scope.buildTreeRemove = scope.$on('buildTree', function() {
|
||||
$(tree_id).jstree({
|
||||
"core": { "initially_open":['inventory-node'] },
|
||||
"plugins": ['themes', 'json_data', 'ui', 'contextmenu'],
|
||||
"json_data": {
|
||||
data: treeData,
|
||||
ajax: {
|
||||
url: function(node){
|
||||
scope.selected_node = node;
|
||||
return $(node).attr('children');
|
||||
},
|
||||
headers: { 'Authorization': 'Token ' + Authorization.getToken() },
|
||||
success: function(data) {
|
||||
var response = [];
|
||||
for (var i=0; i < data.results.length; i++) {
|
||||
response.push({
|
||||
data: {
|
||||
title: data.results[i].name
|
||||
},
|
||||
attr: {
|
||||
id: data.results[i].id,
|
||||
type: 'group',
|
||||
name: data.results[i].name,
|
||||
description: data.results[i].description,
|
||||
inventory: data.results[i].inventory,
|
||||
all: data.results[i].related.all_hosts,
|
||||
children: data.results[i].related.children,
|
||||
hosts: data.results[i].related.hosts,
|
||||
variable: data.results[i].related.variable_data
|
||||
},
|
||||
state: 'closed'
|
||||
});
|
||||
}
|
||||
scope.$emit('loadHosts');
|
||||
return response;
|
||||
}
|
||||
}
|
||||
},
|
||||
"contextmenu": {
|
||||
items: scope.treeController
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Ater inventory top-level hosts, load top-level groups
|
||||
if (scope.HostLoadedRemove) {
|
||||
scope.HostLoadedRemove();
|
||||
}
|
||||
scope.HostLoadedRemove = scope.$on('hostsLoaded', function() {
|
||||
Rest.setUrl(groups + '?order_by=name');
|
||||
Rest.get()
|
||||
.success( function(data, status, headers, config) {
|
||||
for (var i=0; i < data.results.length; i++) {
|
||||
treeData[0].children.push({
|
||||
data: {
|
||||
title: data.results[i].name
|
||||
},
|
||||
attr: {
|
||||
id: data.results[i].id,
|
||||
type: 'group',
|
||||
name: data.results[i].name,
|
||||
description: data.results[i].description,
|
||||
inventory: data.results[i].inventory,
|
||||
all: data.results[i].related.all_hosts,
|
||||
children: data.results[i].related.children,
|
||||
hosts: data.results[i].related.hosts,
|
||||
variable: data.results[i].related.variable_data
|
||||
},
|
||||
state: 'closed'
|
||||
});
|
||||
}
|
||||
scope.$emit('buildTree');
|
||||
})
|
||||
.error( function(data, status, headers, config) {
|
||||
Alert('Error', 'Failed to laod tree data. Url: ' + groups + ' GET status: ' + status);
|
||||
});
|
||||
});
|
||||
|
||||
// Load inventory all hosts
|
||||
Rest.setUrl(hosts + '?order_by=name');
|
||||
Rest.get()
|
||||
.success ( function(data, status, headers, config) {
|
||||
treeData = [];
|
||||
treeData.push({
|
||||
data: {
|
||||
title: inventory_name
|
||||
},
|
||||
attr: {
|
||||
type: 'inventory',
|
||||
id: 'inventory-node',
|
||||
url: inventory_url,
|
||||
'inventory_id': inventory_id,
|
||||
name: inventory_name
|
||||
},
|
||||
state: 'open',
|
||||
children:[]
|
||||
});
|
||||
//treeData[0].children.push({
|
||||
var all_hosts_node = {
|
||||
data: {
|
||||
title: 'All Hosts'
|
||||
},
|
||||
attr: {
|
||||
type: 'all-hosts-group',
|
||||
id: 'all-hosts-group',
|
||||
url: hosts + '?order_by=name',
|
||||
name: 'All Hosts'
|
||||
},
|
||||
state: 'closed',
|
||||
children: []
|
||||
};
|
||||
for (var i=0; i < data.results.length; i++ ) {
|
||||
all_hosts_node.children.push({
|
||||
data: {
|
||||
title: data.results[i].name,
|
||||
icon: '/'
|
||||
},
|
||||
attr: {
|
||||
id: data.results[i].id,
|
||||
type: 'host',
|
||||
name: data.results[i].name,
|
||||
description: data.results[i].description,
|
||||
url: data.results[i].url,
|
||||
variable_data: data.results[i].varaible_data,
|
||||
inventory: data.results[i].related.inventory,
|
||||
job_events: data.results[i].related.job_events
|
||||
},
|
||||
});
|
||||
}
|
||||
treeData[0].children.push(all_hosts_node);
|
||||
scope.$emit('hostsLoaded');
|
||||
})
|
||||
.error ( function(data, status, headers, config) {
|
||||
Alert('Error', 'Failed to laod tree data. Url: ' + hosts + ' GET status: ' + status);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
64
ansibleworks/ui/static/js/helpers/paginate.js
Normal file
64
ansibleworks/ui/static/js/helpers/paginate.js
Normal file
@@ -0,0 +1,64 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* PaginateHelper
|
||||
*
|
||||
* All the parts for controlling the search widget on
|
||||
* related collections.
|
||||
*
|
||||
* PaginateInit({
|
||||
* scope: <scope>,
|
||||
* list: <form object used by FormGenerator>
|
||||
* url: <
|
||||
* });
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('PaginateHelper', ['RefreshHelper'])
|
||||
.factory('PaginateInit', [ 'Refresh', function(Refresh) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var list = params.list;
|
||||
var iterator = (params.iterator) ? params.iterator : list.iterator;
|
||||
var url = params.url;
|
||||
var mode = (params.mode) ? params.mode : null;
|
||||
|
||||
scope[iterator + 'Page'] = 0;
|
||||
|
||||
if (params.pageSize) {
|
||||
scope[iterator + 'PageSize'] = params.pageSize;
|
||||
}
|
||||
else if (mode == 'lookup') {
|
||||
scope[iterator + 'PageSize'] = 5;
|
||||
}
|
||||
else {
|
||||
scope[iterator + 'PageSize'] = 20;
|
||||
}
|
||||
|
||||
scope.nextSet = function(set, iterator) {
|
||||
if (scope[iterator + 'NextUrl']) {
|
||||
scope[iterator + 'Page']++;
|
||||
Refresh({ scope: scope, set: set, iterator: iterator, url: scope[iterator + 'NextUrl'] });
|
||||
}
|
||||
};
|
||||
|
||||
scope.prevSet = function(set, iterator) {
|
||||
if (scope[iterator + 'PrevUrl']) {
|
||||
scope[iterator + 'Page']--;
|
||||
Refresh({ scope: scope, set: set, iterator: iterator, url: scope[iterator + 'PrevUrl'] });
|
||||
}
|
||||
};
|
||||
|
||||
scope.changePageSize = function(set, iterator) {
|
||||
// Called when a new page size is selected
|
||||
scope[iterator + 'Page'] = 0;
|
||||
console.log(url);
|
||||
url = url.replace(/\/\?.*$/,'/');
|
||||
console.log(url);
|
||||
url += (scope[iterator + 'SearchParams']) ? scope[iterator + 'SearchParams'] + '&page_size=' + scope[iterator + 'PageSize' ] :
|
||||
'?page_size=' + scope[iterator + 'PageSize' ];
|
||||
Refresh({ scope: scope, set: set, iterator: iterator, url: url });
|
||||
}
|
||||
}
|
||||
}]);
|
||||
43
ansibleworks/ui/static/js/helpers/refresh-related.js
Normal file
43
ansibleworks/ui/static/js/helpers/refresh-related.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* RefreshRelatedHelper
|
||||
*
|
||||
* Used to refresh a related set whenever pagination or filter options change.
|
||||
*
|
||||
* RefreshRelated({
|
||||
* scope: <current scope>,
|
||||
* set: <model>,
|
||||
* iterator: <model name in singular form (i.e. organization),
|
||||
* url: <the api url to call>
|
||||
* });
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('RefreshRelatedHelper', ['RestServices', 'Utilities'])
|
||||
.factory('RefreshRelated', ['Alert', 'Rest', function(Alert, Rest) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var set = params.set;
|
||||
var iterator = params.iterator;
|
||||
var url = params.url;
|
||||
|
||||
url.replace(/page_size\=\d+/,''); //stop repeatedly appending page_size
|
||||
|
||||
Rest.setUrl(url);
|
||||
Rest.get({ params: { page_size: scope[iterator + 'PageSize'] }})
|
||||
.success( function(data, status, headers, config) {
|
||||
scope[set] = data['results'];
|
||||
scope[iterator + 'NextUrl'] = data.next;
|
||||
scope[iterator + 'PrevUrl'] = data.previous;
|
||||
scope[iterator + 'Count'] = data.count;
|
||||
scope[iterator + 'PageCount'] = Math.ceil((data.count / scope[iterator + 'PageSize']));
|
||||
scope[iterator + 'SearchSpin'] = false;
|
||||
})
|
||||
.error ( function(data, status, headers, config) {
|
||||
scope[iterator + 'SearchSpin'] = true;
|
||||
Alert('Error!', 'Failed to retrieve related set: ' + set + '. GET returned status: ' + status);
|
||||
});
|
||||
}
|
||||
}]);
|
||||
41
ansibleworks/ui/static/js/helpers/refresh.js
Normal file
41
ansibleworks/ui/static/js/helpers/refresh.js
Normal file
@@ -0,0 +1,41 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* RefreshHelper
|
||||
*
|
||||
* Used to refresh a related set whenever pagination or filter options change.
|
||||
*
|
||||
* RefreshRelated({
|
||||
* scope: <current scope>,
|
||||
* set: <model>,
|
||||
* iterator: <model name in singular form (i.e. organization),
|
||||
* url: <the api url to call>
|
||||
* });
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('RefreshHelper', ['RestServices', 'Utilities'])
|
||||
.factory('Refresh', ['Alert', 'Rest', function(Alert, Rest) {
|
||||
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) {
|
||||
scope[iterator + 'NextUrl'] = data.next;
|
||||
scope[iterator + 'PrevUrl'] = data.previous;
|
||||
scope[iterator + 'Count'] = data.count;
|
||||
scope[iterator + 'PageCount'] = Math.ceil((data.count / scope[iterator + 'PageSize']));
|
||||
scope[iterator + 'SearchSpin'] = false;
|
||||
scope[set] = data['results'];
|
||||
scope.$emit('PostRefresh');
|
||||
})
|
||||
.error ( function(data, status, headers, config) {
|
||||
scope[iterator + 'SearchSpin'] = false;
|
||||
Alert('Error!', 'Failed to retrieve ' + set + '. GET returned status: ' + status);
|
||||
});
|
||||
}
|
||||
}]);
|
||||
52
ansibleworks/ui/static/js/helpers/related-paginate.js
Normal file
52
ansibleworks/ui/static/js/helpers/related-paginate.js
Normal file
@@ -0,0 +1,52 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* RelatedPaginateHelper
|
||||
*
|
||||
* All the parts for controlling the search widget on
|
||||
* related collections.
|
||||
*
|
||||
* RelatedPaginateInit({
|
||||
* scope: <scope>,
|
||||
* relatedSets: <array of related collections {model_name, url, iterator}>,
|
||||
* form: <form object used by FormGenerator>
|
||||
* });
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('RelatedPaginateHelper', ['RefreshRelatedHelper'])
|
||||
.factory('RelatedPaginateInit', [ 'RefreshRelated', function(RefreshRelated) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var relatedSets = params.relatedSets;
|
||||
|
||||
for (var key in relatedSets){
|
||||
scope[relatedSets[key].iterator + 'Page'] = 0;
|
||||
scope[relatedSets[key].iterator + 'PageSize'] = 20;
|
||||
}
|
||||
|
||||
scope.nextSet = function(set, iterator) {
|
||||
scope[iterator + 'Page']++;
|
||||
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: scope[iterator + 'NextUrl'] });
|
||||
};
|
||||
|
||||
scope.prevSet = function(set, iterator) {
|
||||
scope[iterator + 'Page']--;
|
||||
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: scope[iterator + 'PrevUrl'] });
|
||||
};
|
||||
|
||||
scope.changePageSize = function(set, iterator) {
|
||||
// Called when a new page size is selected
|
||||
var defaultUrl;
|
||||
scope[iterator + 'Page'] = 0;
|
||||
for (var key in relatedSets) {
|
||||
if (key == set) {
|
||||
defaultUrl = relatedSets[key].url;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: defaultUrl });
|
||||
}
|
||||
}
|
||||
}]);
|
||||
80
ansibleworks/ui/static/js/helpers/related-search.js
Normal file
80
ansibleworks/ui/static/js/helpers/related-search.js
Normal file
@@ -0,0 +1,80 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* RelatedSearchHelper
|
||||
*
|
||||
* 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', ['Alert', 'Rest', 'RefreshRelated', function(Alert, Rest, RefreshRelated) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var relatedSets = params.relatedSets;
|
||||
var form = params.form;
|
||||
|
||||
// Set default values
|
||||
for (var set in form.related) {
|
||||
for (var fld in form.related[set].fields) {
|
||||
if (form.related[set].fields[fld].key) {
|
||||
scope[form.related[set].iterator + 'SearchField'] = fld
|
||||
scope[form.related[set].iterator + 'SearchFieldLabel'] = form.related[set].fields[fld].label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
scope[form.related[set].iterator + 'SearchType'] = 'contains';
|
||||
scope[form.related[set].iterator + 'SearchTypeLabel'] = 'Contains';
|
||||
}
|
||||
|
||||
// Functions to handle search widget changes
|
||||
scope.setSearchField = function(model, fld, label) {
|
||||
scope[model + 'SearchFieldLabel'] = label;
|
||||
scope[model + 'SearchField'] = fld;
|
||||
scope.search(model);
|
||||
}
|
||||
|
||||
scope.setSearchType = function(model, type, label) {
|
||||
scope[model + 'SearchTypeLabel'] = label;
|
||||
scope[model + 'SearchType'] = type;
|
||||
scope.search(model);
|
||||
}
|
||||
|
||||
scope.search = function(model) {
|
||||
scope[model + 'SearchSpin'] = true;
|
||||
var set, url, iterator, default_order;
|
||||
for (var key in relatedSets) {
|
||||
if (relatedSets[key].iterator == model) {
|
||||
set = key;
|
||||
iterator = relatedSets[key].iterator;
|
||||
url = relatedSets[key].url;
|
||||
|
||||
for (var fld in form.related[key].fields) {
|
||||
if (form.related[key].fields[fld].key) {
|
||||
default_order = fld;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (scope[model + 'SearchValue'] != '' && scope[model + 'SearchValue'] != undefined) {
|
||||
url += '?' + scope[model + 'SearchField'] +
|
||||
'__' + scope[model + 'SearchType'] + '=' + escape(scope[model + 'SearchValue']);
|
||||
url += (default_order) ? '&order_by=' + escape(default_order) : '';
|
||||
}
|
||||
else {
|
||||
url += (default_order) ? '?order_by=' + escape(default_order) : '';
|
||||
}
|
||||
RefreshRelated({ scope: scope, set: set, iterator: iterator, url: url });
|
||||
}
|
||||
}
|
||||
}]);
|
||||
128
ansibleworks/ui/static/js/helpers/search.js
Normal file
128
ansibleworks/ui/static/js/helpers/search.js
Normal file
@@ -0,0 +1,128 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* SearchHelper
|
||||
*
|
||||
* All the parts for controlling the search widget on
|
||||
* related collections.
|
||||
*
|
||||
* SearchInit({
|
||||
* scope: <scope>,
|
||||
* set: <model name (i.e. organizations),
|
||||
* name was given in ng-repeat>
|
||||
* url: <default api url used to load data>
|
||||
* list: <list object used by ListGenerator>
|
||||
* });
|
||||
*
|
||||
*/
|
||||
|
||||
angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
|
||||
.factory('SearchInit', ['Alert', 'Rest', 'Refresh', function(Alert, Rest, Refresh) {
|
||||
return function(params) {
|
||||
|
||||
var scope = params.scope;
|
||||
var set = params.set;
|
||||
var defaultUrl = params.url;
|
||||
var list = params.list;
|
||||
var iterator = (params.iterator) ? params.iterator : list.iterator;
|
||||
var default_order;
|
||||
|
||||
// Set default values
|
||||
for (fld in list.fields) {
|
||||
if (list.fields[fld].key) {
|
||||
default_order = (list.fields[fld].desc) ? '-' + fld : fld;
|
||||
scope[iterator + 'SearchField'] = fld
|
||||
scope[iterator + 'SearchFieldLabel'] = list.fields[fld].label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
scope[iterator + 'SearchType'] = 'icontains';
|
||||
scope[iterator + 'SearchTypeLabel'] = 'Contains';
|
||||
scope[iterator + 'SearchParams'] = '';
|
||||
scope[iterator + 'SearchValue'] = '';
|
||||
scope[iterator + 'SelectShow'] = false; // show/hide the Select
|
||||
scope[iterator + 'HideSearchType'] = false;
|
||||
|
||||
var f = scope[iterator + 'SearchField']
|
||||
if (list.fields[f].searchType && list.fields[f].searchType == 'boolean') {
|
||||
scope[iterator + 'SelectShow'] = true;
|
||||
scope[iterator + 'SearchSelectOpts'] = list.fields[fld].searchOptions;
|
||||
}
|
||||
if (list.fields[f].searchType && list.fields[f].searchType == 'int') {
|
||||
scope[iterator + 'HideSearchType'] = true;
|
||||
}
|
||||
|
||||
// Functions to handle search widget changes
|
||||
scope.setSearchField = function(iterator, fld, label) {
|
||||
scope[iterator + 'SearchFieldLabel'] = label;
|
||||
scope[iterator + 'SearchField'] = fld;
|
||||
scope[iterator + 'SearchValue'] = '';
|
||||
scope[iterator + 'SelectShow'] = false;
|
||||
scope[iterator + 'HideSearchType'] = false;
|
||||
|
||||
if (list.fields[fld].searchType && list.fields[fld].searchType == 'boolean') {
|
||||
scope[iterator + 'SelectShow'] = true;
|
||||
scope[iterator + 'SearchSelectOpts'] = list.fields[f].searchOptions;
|
||||
}
|
||||
if (list.fields[fld].searchType && list.fields[fld].searchType == 'int') {
|
||||
scope[iterator + 'HideSearchType'] = true;
|
||||
}
|
||||
|
||||
scope.search(iterator);
|
||||
}
|
||||
|
||||
scope.setSearchType = function(iterator, type, label) {
|
||||
scope[iterator + 'SearchTypeLabel'] = label;
|
||||
scope[iterator + 'SearchType'] = type;
|
||||
scope.search(iterator);
|
||||
}
|
||||
|
||||
scope.search = function(iterator) {
|
||||
//
|
||||
// need to be able to search by related set. Ex: /api/v1/inventories/?organization__name__icontains=
|
||||
//
|
||||
scope[iterator + 'SearchSpin'] = true;
|
||||
var url = defaultUrl;
|
||||
if ( (scope[iterator + 'SelectShow'] == false && scope[iterator + 'SearchValue'] != '' && scope[iterator + 'SearchValue'] != undefined) ||
|
||||
(scope[iterator + 'SelectShow'] && scope[iterator + 'SearchSelectValue']) ) {
|
||||
if (list.fields[scope[iterator + 'SearchField']].sourceModel) {
|
||||
// handle fields whose source is a related model e.g. inventories.organization
|
||||
scope[iterator + 'SearchParams'] = '?' + list.fields[scope[iterator + 'SearchField']].sourceModel + '__' +
|
||||
list.fields[scope[iterator + 'SearchField']].sourceField + '__';
|
||||
}
|
||||
else if (list.fields[scope[iterator + 'SearchField']].searchField) {
|
||||
scope[iterator + 'SearchParams'] = '?' + list.fields[scope[iterator + 'SearchField']].searchField + '__';
|
||||
}
|
||||
else {
|
||||
scope[iterator + 'SearchParams'] = '?' + scope[iterator + 'SearchField'] + '__';
|
||||
}
|
||||
|
||||
if ( list.fields[scope[iterator + 'SearchField']].searchType &&
|
||||
(list.fields[scope[iterator + 'SearchField']].searchType == 'int' ||
|
||||
list.fields[scope[iterator + 'SearchField']].searchType == 'boolean') ) {
|
||||
scope[iterator + 'SearchParams'] += 'int=';
|
||||
}
|
||||
else {
|
||||
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchType'] + '=';
|
||||
}
|
||||
|
||||
if ( list.fields[scope[iterator + 'SearchField']].searchType &&
|
||||
list.fields[scope[iterator + 'SearchField']].searchType == 'boolean' ) {
|
||||
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchSelectValue'].value;
|
||||
}
|
||||
else {
|
||||
scope[iterator + 'SearchParams'] += escape(scope[iterator + 'SearchValue']);
|
||||
}
|
||||
scope[iterator + 'SearchParams'] += (default_order) ? '&order_by=' + escape(default_order) : '';
|
||||
}
|
||||
else {
|
||||
scope[iterator + 'SearchParams'] = '';
|
||||
scope[iterator + 'SearchParams'] += (default_order) ? '?order_by=' + escape(default_order) : '';
|
||||
}
|
||||
scope[iterator + 'Page'] = 0;
|
||||
url += scope[iterator + 'SearchParams'];
|
||||
url += (scope[iterator + 'PageSize']) ? '&page_size=' + scope[iterator + 'PageSize'] : "";
|
||||
Refresh({ scope: scope, set: set, iterator: iterator, url: url });
|
||||
}
|
||||
}
|
||||
}]);
|
||||
109
ansibleworks/ui/static/js/helpers/teams.js
Normal file
109
ansibleworks/ui/static/js/helpers/teams.js
Normal file
@@ -0,0 +1,109 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* TeamHelper
|
||||
* Routines shared amongst the team controllers
|
||||
*/
|
||||
|
||||
angular.module('TeamHelper', [ 'RestServices', 'Utilities', 'OrganizationListDefinition',
|
||||
'SearchHelper', 'PaginateHelper', '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
|
||||
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
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) {
|
||||
console.log('here!');
|
||||
console.log(data);
|
||||
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;
|
||||
|
||||
// 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';
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}]);
|
||||
|
||||
|
||||
39
ansibleworks/ui/static/js/lists/Admins.js
Normal file
39
ansibleworks/ui/static/js/lists/Admins.js
Normal file
@@ -0,0 +1,39 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Admins.js
|
||||
* List view object for Admins data model.
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('AdminListDefinition', [])
|
||||
.value(
|
||||
'AdminList', {
|
||||
|
||||
name: 'admins',
|
||||
iterator: 'admin',
|
||||
selectTitle: 'Add Administrators',
|
||||
editTitle: 'Admins',
|
||||
selectInstructions: 'Click on a row to select it. Click the Finished button when done.',
|
||||
base: 'users',
|
||||
index: true,
|
||||
|
||||
fields: {
|
||||
username: {
|
||||
key: true,
|
||||
label: 'Username'
|
||||
},
|
||||
first_name: {
|
||||
label: 'First Name'
|
||||
},
|
||||
last_name: {
|
||||
label: 'Last Name'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
}
|
||||
});
|
||||
68
ansibleworks/ui/static/js/lists/Credentials.js
Normal file
68
ansibleworks/ui/static/js/lists/Credentials.js
Normal file
@@ -0,0 +1,68 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Credentials.js
|
||||
* List view object for Credential data model.
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('CredentialsListDefinition', [])
|
||||
.value(
|
||||
'CredentialList', {
|
||||
|
||||
name: 'credentials',
|
||||
iterator: 'credential',
|
||||
selectTitle: 'Add Credentials',
|
||||
editTitle: 'Credentials',
|
||||
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,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
},
|
||||
team: {
|
||||
label: 'Team',
|
||||
ngBind: 'credential.summary_fields.team.name',
|
||||
sourceModel: 'team',
|
||||
sourceField: 'name'
|
||||
},
|
||||
user: {
|
||||
label: 'User',
|
||||
ngBind: 'credential.summary_fields.user.usename',
|
||||
sourceModel: 'user',
|
||||
sourceField: 'username'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
icon: 'icon-plus',
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addCredential()',
|
||||
basePaths: ['credentials'], // base path must be in list, or action not available
|
||||
class: 'btn-success',
|
||||
awToolTip: 'Create a new credential'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "editCredential(\{\{ credential.id \}\})",
|
||||
icon: 'icon-edit',
|
||||
class: 'btn-mini',
|
||||
awToolTip: 'View/Edit credential'
|
||||
},
|
||||
|
||||
delete: {
|
||||
ngClick: "deleteCredential(\{\{ credential.id \}\},'\{\{ credential.name \}\}')",
|
||||
icon: 'icon-remove',
|
||||
class: 'btn-mini btn-danger',
|
||||
awToolTip: 'Delete credential'
|
||||
}
|
||||
}
|
||||
});
|
||||
55
ansibleworks/ui/static/js/lists/Groups.js
Normal file
55
ansibleworks/ui/static/js/lists/Groups.js
Normal file
@@ -0,0 +1,55 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Groups.js
|
||||
* List view object for Group data model.
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('GroupListDefinition', [])
|
||||
.value(
|
||||
'GroupList', {
|
||||
|
||||
name: 'groups',
|
||||
iterator: 'group',
|
||||
selectTitle: 'Add Group',
|
||||
editTitle: 'Groups',
|
||||
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,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
icon: 'icon-plus',
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addGroup()',
|
||||
class: 'btn-success',
|
||||
awToolTip: 'Create a new group'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "editGroup(\{\{ group.id \}\})",
|
||||
icon: 'icon-edit',
|
||||
class: 'btn-mini',
|
||||
awToolTip: 'View/Edit group'
|
||||
},
|
||||
|
||||
delete: {
|
||||
ngClick: "deleteGroup(\{\{ group.id \}\},'\{\{ group.name \}\}')",
|
||||
icon: 'icon-remove',
|
||||
class: 'btn-mini btn-danger',
|
||||
awToolTip: 'Delete group'
|
||||
}
|
||||
}
|
||||
});
|
||||
55
ansibleworks/ui/static/js/lists/Hosts.js
Normal file
55
ansibleworks/ui/static/js/lists/Hosts.js
Normal file
@@ -0,0 +1,55 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Hosts.js
|
||||
* List view object for Users data model.
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('HostListDefinition', [])
|
||||
.value(
|
||||
'HostList', {
|
||||
|
||||
name: 'hosts',
|
||||
iterator: 'host',
|
||||
selectTitle: 'Add Host',
|
||||
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: 'Hosts',
|
||||
index: true,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
icon: 'icon-plus',
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addHost()',
|
||||
class: 'btn-success',
|
||||
awToolTip: 'Create a new host'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "editHost(\{\{ host.id \}\})",
|
||||
icon: 'icon-edit',
|
||||
class: 'btn-mini',
|
||||
awToolTip: 'View/Edit host'
|
||||
},
|
||||
|
||||
delete: {
|
||||
ngClick: "deleteHost(\{\{ host.id \}\},'\{\{ host.name \}\}')",
|
||||
icon: 'icon-remove',
|
||||
class: 'btn-mini btn-danger',
|
||||
awToolTip: 'Delete host'
|
||||
}
|
||||
}
|
||||
});
|
||||
61
ansibleworks/ui/static/js/lists/Inventories.js
Normal file
61
ansibleworks/ui/static/js/lists/Inventories.js
Normal file
@@ -0,0 +1,61 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Inventories.js
|
||||
* List view object for Inventories data model.
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('InventoriesListDefinition', [])
|
||||
.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.',
|
||||
index: true,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Descriptions'
|
||||
},
|
||||
organization: {
|
||||
label: 'Organization',
|
||||
ngBind: 'inventory.summary_fields.organization.name',
|
||||
sourceModel: 'organization',
|
||||
sourceField: 'name'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
icon: 'icon-plus',
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addInventory()',
|
||||
class: 'btn-success',
|
||||
awToolTip: 'Create a new row'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "editInventory(\{\{ inventory.id \}\})",
|
||||
icon: 'icon-edit',
|
||||
class: 'btn-mini',
|
||||
awToolTip: 'View/Edit inventory'
|
||||
},
|
||||
|
||||
delete: {
|
||||
ngClick: "deleteInventory(\{\{ inventory.id \}\},'\{\{ inventory.name \}\}')",
|
||||
icon: 'icon-remove',
|
||||
class: 'btn-mini btn-danger',
|
||||
awToolTip: 'Delete'
|
||||
}
|
||||
}
|
||||
});
|
||||
62
ansibleworks/ui/static/js/lists/JobTemplates.js
Normal file
62
ansibleworks/ui/static/js/lists/JobTemplates.js
Normal file
@@ -0,0 +1,62 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* JobTemplates.js
|
||||
* List view object for Job Templates data model.
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('JobTemplatesListDefinition', [])
|
||||
.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.',
|
||||
index: true,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
icon: 'icon-plus',
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addJobTemplate()',
|
||||
class: 'btn-success',
|
||||
basePaths: ['job_templates'],
|
||||
awToolTip: 'Create a new template'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "editJobTemplate(\{\{ job_template.id \}\})",
|
||||
icon: 'icon-edit',
|
||||
awToolTip: 'View/Edit template',
|
||||
class: 'btn-mini'
|
||||
},
|
||||
submit: {
|
||||
icon: 'icon-play',
|
||||
mode: 'all',
|
||||
class: 'btn-mini btn-success',
|
||||
ngClick: 'submitJob(\{\{ job_template.id \}\})',
|
||||
awToolTip: 'Create and run a job using this template'
|
||||
},
|
||||
delete: {
|
||||
ngClick: "deleteJobTemplate(\{\{ job_template.id \}\},'\{\{ job_template.name \}\}')",
|
||||
icon: 'icon-remove',
|
||||
class: 'btn-danger btn-mini',
|
||||
awToolTip: 'Delete template'
|
||||
}
|
||||
}
|
||||
});
|
||||
85
ansibleworks/ui/static/js/lists/Jobs.js
Normal file
85
ansibleworks/ui/static/js/lists/Jobs.js
Normal file
@@ -0,0 +1,85 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Jobs.js
|
||||
* List view object for Team data model.
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('JobsListDefinition', [])
|
||||
.value(
|
||||
'JobList', {
|
||||
|
||||
name: 'jobs',
|
||||
iterator: 'job',
|
||||
editTitle: 'Jobs',
|
||||
index: false,
|
||||
hover: true,
|
||||
class: 'jobs-table',
|
||||
|
||||
fields: {
|
||||
id: {
|
||||
label: 'Job ID',
|
||||
key: true,
|
||||
desc: true,
|
||||
searchType: 'int'
|
||||
},
|
||||
name: {
|
||||
label: 'Name',
|
||||
link: true,
|
||||
},
|
||||
created: {
|
||||
label: 'Creation Date',
|
||||
link: true
|
||||
},
|
||||
status: {
|
||||
label: 'Status',
|
||||
icon: 'icon-circle',
|
||||
class: 'job-\{\{ job.status \}\}'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
refresh: {
|
||||
ngClick: "refreshJob(\{\{ job.id \}\})",
|
||||
icon: 'icon-refresh',
|
||||
awToolTip: 'Refresh the page',
|
||||
mode: 'all'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "editJob(\{\{ job.id \}\})",
|
||||
icon: 'icon-edit',
|
||||
class: 'btn-mini',
|
||||
awToolTip: 'View/Edit detail',
|
||||
},
|
||||
summary: {
|
||||
title: 'Summary',
|
||||
icon: 'icon-filter',
|
||||
ngClick: 'viewSummary(\{{ job.id \}\})',
|
||||
class: 'btn-success btn-mini',
|
||||
awToolTip: 'View host summary',
|
||||
ngDisabled: "job.status == 'new'"
|
||||
},
|
||||
events: {
|
||||
title: 'Detail',
|
||||
icon: 'icon-list-ul',
|
||||
mode: 'all',
|
||||
ngClick: 'viewEvents(\{{ job.id \}\})',
|
||||
class: 'btn-success btn-mini',
|
||||
awToolTip: 'View events',
|
||||
ngDisabled: "job.status == 'new'"
|
||||
},
|
||||
cancel: {
|
||||
title: 'Cancel',
|
||||
icon: 'icon-minus-sign',
|
||||
mode: 'all',
|
||||
ngClick: 'deleteJob(\{\{ job.id \}\})',
|
||||
class: 'btn-danger btn-mini',
|
||||
awToolTip: 'Cancel job',
|
||||
ngDisabled: "job.status == 'error' || job.status == 'failed' || job.status == 'success'"
|
||||
}
|
||||
}
|
||||
});
|
||||
54
ansibleworks/ui/static/js/lists/Organizations.js
Normal file
54
ansibleworks/ui/static/js/lists/Organizations.js
Normal file
@@ -0,0 +1,54 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Organizations.js
|
||||
* List view object for Organizations data model.
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('OrganizationListDefinition', [])
|
||||
.value(
|
||||
'OrganizationList', {
|
||||
|
||||
name: 'organizations',
|
||||
iterator: 'organization',
|
||||
selectTitle: 'Add Organizations',
|
||||
editTitle: 'Organizations',
|
||||
index: true,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Description'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
icon: 'icon-plus',
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addOrganization()',
|
||||
class: 'btn-success',
|
||||
awToolTip: 'Create a new row'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "editOrganization(\{\{ organization.id \}\})",
|
||||
icon: 'icon-edit',
|
||||
class: 'btn-mini',
|
||||
awToolTip: 'View/Edit organization'
|
||||
},
|
||||
|
||||
delete: {
|
||||
ngClick: "deleteOrganization(\{\{ organization.id \}\},'\{\{ organization.name \}\}')",
|
||||
icon: 'icon-remove',
|
||||
class: 'btn-mini btn-danger',
|
||||
awToolTip: 'Delete organization'
|
||||
}
|
||||
}
|
||||
});
|
||||
55
ansibleworks/ui/static/js/lists/Projects.js
Normal file
55
ansibleworks/ui/static/js/lists/Projects.js
Normal file
@@ -0,0 +1,55 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Projects.js
|
||||
* List view object for Project data model.
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('ProjectsListDefinition', [])
|
||||
.value(
|
||||
'ProjectList', {
|
||||
|
||||
name: 'projects',
|
||||
iterator: 'project',
|
||||
selectTitle: 'Add Project',
|
||||
editTitle: '{{ name }}',
|
||||
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,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Descriptions'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
icon: 'icon-plus',
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addProject()',
|
||||
class: 'btn-success',
|
||||
awToolTip: 'Create a new project'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "editProject(\{\{ project.id \}\})",
|
||||
icon: 'icon-edit',
|
||||
class: 'btn-mini',
|
||||
awToolTip: 'View/edit project'
|
||||
},
|
||||
|
||||
delete: {
|
||||
ngClick: "deleteProject(\{\{ project.id \}\},'\{\{ project.name \}\}')",
|
||||
icon: 'icon-remove',
|
||||
class: 'btn-mini btn-danger',
|
||||
awToolTip: 'Delete project'
|
||||
}
|
||||
}
|
||||
});
|
||||
61
ansibleworks/ui/static/js/lists/Teams.js
Normal file
61
ansibleworks/ui/static/js/lists/Teams.js
Normal file
@@ -0,0 +1,61 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Teams.js
|
||||
* List view object for Team data model.
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('TeamsListDefinition', [])
|
||||
.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.',
|
||||
index: true,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Name'
|
||||
},
|
||||
description: {
|
||||
label: 'Descriptions'
|
||||
},
|
||||
organization: {
|
||||
label: 'Organization',
|
||||
ngBind: 'team.organization_name',
|
||||
sourceModel: 'organization',
|
||||
sourceField: 'name'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
icon: 'icon-plus',
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addTeam()',
|
||||
class: 'btn-success',
|
||||
awToolTip: 'Create a new team'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "editTeam(\{\{ team.id \}\})",
|
||||
icon: 'icon-edit',
|
||||
class: 'btn-mini',
|
||||
awToolTip: 'View/Edit team'
|
||||
},
|
||||
|
||||
delete: {
|
||||
ngClick: "deleteTeam(\{\{ team.id \}\},'\{\{ team.name \}\}')",
|
||||
icon: 'icon-remove',
|
||||
class: 'btn-mini btn-danger',
|
||||
awToolTip: 'Delete team'
|
||||
}
|
||||
}
|
||||
});
|
||||
60
ansibleworks/ui/static/js/lists/Users.js
Normal file
60
ansibleworks/ui/static/js/lists/Users.js
Normal file
@@ -0,0 +1,60 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2013 AnsibleWorks, Inc.
|
||||
*
|
||||
* Users.js
|
||||
* List view object for Users data model.
|
||||
*
|
||||
*
|
||||
*/
|
||||
angular.module('UserListDefinition', [])
|
||||
.value(
|
||||
'UserList', {
|
||||
|
||||
name: 'users',
|
||||
iterator: 'user',
|
||||
selectTitle: 'Add Users',
|
||||
editTitle: 'Users',
|
||||
selectInstructions: 'Check the Select checkbox next to each user to be added, and click Finished when done. Use the green <i class=\"icon-plus\"></i> button to create a new user.',
|
||||
editInstructions: 'Create new users from the Organizations tab. Each Organization has an associated list of Users.',
|
||||
index: true,
|
||||
|
||||
fields: {
|
||||
username: {
|
||||
key: true,
|
||||
label: 'Username'
|
||||
},
|
||||
first_name: {
|
||||
label: 'First Name'
|
||||
},
|
||||
last_name: {
|
||||
label: 'Last Name'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
add: {
|
||||
icon: 'icon-plus',
|
||||
mode: 'select', // One of: edit, select, all
|
||||
ngClick: 'addUser()',
|
||||
basePaths: ['organizations'], // base path must be in list, or action not available
|
||||
class: 'btn-success',
|
||||
awToolTip: 'Create a new user'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
edit: {
|
||||
ngClick: "editUser(\{\{ user.id \}\})",
|
||||
icon: 'icon-edit',
|
||||
class: 'btn-mini',
|
||||
awToolTip: 'View/Edit user'
|
||||
},
|
||||
|
||||
delete: {
|
||||
ngClick: "deleteUser(\{\{ user.id \}\},'\{\{ user.username \}\}')",
|
||||
icon: 'icon-remove',
|
||||
class: 'btn-mini btn-danger',
|
||||
awToolTip: 'Delete user'
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user