mirror of
https://github.com/ansible/awx.git
synced 2026-01-19 21:51:26 -03:30
Merge pull request #5170 from mabashian/5153-permission-scope
Related lists custom scope
This commit is contained in:
commit
3913ddb331
@ -7,10 +7,12 @@
|
||||
import roleList from './rbac-role-column/roleList.directive';
|
||||
import addRbacResource from './add-rbac-resource/main';
|
||||
import addRbacUserTeam from './add-rbac-user-team/main';
|
||||
import permissionsList from './permissions-list.controller';
|
||||
|
||||
export default
|
||||
angular.module('RbacModule', [
|
||||
addRbacResource.name,
|
||||
addRbacUserTeam.name
|
||||
])
|
||||
.controller('PermissionsList', permissionsList)
|
||||
.directive('roleList', roleList);
|
||||
|
||||
82
awx/ui/client/src/access/permissions-list.controller.js
Normal file
82
awx/ui/client/src/access/permissions-list.controller.js
Normal file
@ -0,0 +1,82 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2016 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
export default ['$scope', 'ListDefinition', 'Dataset', 'Wait', 'Rest', 'ProcessErrors', 'Prompt', '$state',
|
||||
function($scope, list, Dataset, Wait, Rest, ProcessErrors, Prompt, $state) {
|
||||
|
||||
init();
|
||||
|
||||
function init() {
|
||||
$scope.list = list;
|
||||
$scope[`${list.iterator}_dataset`] = Dataset.data;
|
||||
$scope[`${list.iterator}s`] = $scope[`${list.iterator}_dataset`].results;
|
||||
}
|
||||
|
||||
$scope.deletePermissionFromUser = function(userId, userName, roleName, roleType, url) {
|
||||
var action = function() {
|
||||
$('#prompt-modal').modal('hide');
|
||||
Wait('start');
|
||||
Rest.setUrl(url);
|
||||
Rest.post({ "disassociate": true, "id": userId })
|
||||
.success(function() {
|
||||
Wait('stop');
|
||||
$state.go('.', null, {reload: true});
|
||||
})
|
||||
.error(function(data, status) {
|
||||
ProcessErrors($scope, data, status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Could not disassociate user from role. Call to ' + url + ' failed. DELETE returned status: ' + status
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({
|
||||
hdr: `Remove role`,
|
||||
body: `
|
||||
<div class="Prompt-bodyQuery">
|
||||
Confirm the removal of the ${roleType}
|
||||
<span class="Prompt-emphasis"> ${roleName} </span>
|
||||
role associated with ${userName}.
|
||||
</div>
|
||||
`,
|
||||
action: action,
|
||||
actionText: 'REMOVE'
|
||||
});
|
||||
};
|
||||
|
||||
$scope.deletePermissionFromTeam = function(teamId, teamName, roleName, roleType, url) {
|
||||
var action = function() {
|
||||
$('#prompt-modal').modal('hide');
|
||||
Wait('start');
|
||||
Rest.setUrl(url);
|
||||
Rest.post({ "disassociate": true, "id": teamId })
|
||||
.success(function() {
|
||||
Wait('stop');
|
||||
$state.go('.', null, {reload: true});
|
||||
})
|
||||
.error(function(data, status) {
|
||||
ProcessErrors($scope, data, status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Could not disassociate team from role. Call to ' + url + ' failed. DELETE returned status: ' + status
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({
|
||||
hdr: `Remove role`,
|
||||
body: `
|
||||
<div class="Prompt-bodyQuery">
|
||||
Confirm the removal of the ${roleType}
|
||||
<span class="Prompt-emphasis"> ${roleName} </span>
|
||||
role associated with the ${teamName} team.
|
||||
</div>
|
||||
`,
|
||||
action: action,
|
||||
actionText: 'REMOVE'
|
||||
});
|
||||
};
|
||||
}
|
||||
];
|
||||
@ -44,7 +44,6 @@ import './filters';
|
||||
import { Home } from './controllers/Home';
|
||||
import { SocketsController } from './controllers/Sockets';
|
||||
import { CredentialsAdd, CredentialsEdit, CredentialsList } from './controllers/Credentials';
|
||||
import { JobsListController } from './controllers/Jobs';
|
||||
import portalMode from './portal-mode/main';
|
||||
import systemTracking from './system-tracking/main';
|
||||
import inventories from './inventories/main';
|
||||
@ -70,6 +69,7 @@ import activityStream from './activity-stream/main';
|
||||
import standardOut from './standard-out/main';
|
||||
import Templates from './templates/main';
|
||||
import credentials from './credentials/main';
|
||||
import jobs from './jobs/main';
|
||||
import { ProjectsList, ProjectsAdd, ProjectsEdit } from './controllers/Projects';
|
||||
import { UsersList, UsersAdd, UsersEdit } from './controllers/Users';
|
||||
import { TeamsList, TeamsAdd, TeamsEdit } from './controllers/Teams';
|
||||
@ -134,6 +134,7 @@ var tower = angular.module('Tower', [
|
||||
portalMode.name,
|
||||
config.name,
|
||||
credentials.name,
|
||||
jobs.name,
|
||||
//'templates',
|
||||
'Utilities',
|
||||
'OrganizationFormDefinition',
|
||||
@ -422,53 +423,6 @@ var tower = angular.module('Tower', [
|
||||
}
|
||||
});
|
||||
|
||||
$stateExtender.addState({
|
||||
searchPrefix: 'job',
|
||||
name: 'jobs',
|
||||
url: '/jobs',
|
||||
ncyBreadcrumb: {
|
||||
label: N_("JOBS")
|
||||
},
|
||||
params: {
|
||||
job_search: {
|
||||
value: {
|
||||
not__launch_type: 'sync',
|
||||
order_by: '-finished'
|
||||
},
|
||||
squash: ''
|
||||
}
|
||||
},
|
||||
data: {
|
||||
socket: {
|
||||
"groups": {
|
||||
"jobs": ["status_changed"],
|
||||
"schedules": ["changed"]
|
||||
}
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
Dataset: ['AllJobsList', 'QuerySet', '$stateParams', 'GetBasePath', (list, qs, $stateParams, GetBasePath) => {
|
||||
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
|
||||
return qs.search(path, $stateParams[`${list.iterator}_search`]);
|
||||
}]
|
||||
},
|
||||
views: {
|
||||
'@': {
|
||||
templateUrl: urlPrefix + 'partials/jobs.html',
|
||||
},
|
||||
'list@jobs': {
|
||||
templateProvider: function(AllJobsList, generateList) {
|
||||
let html = generateList.build({
|
||||
list: AllJobsList,
|
||||
mode: 'edit'
|
||||
});
|
||||
return html;
|
||||
},
|
||||
controller: JobsListController
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$stateExtender.addState({
|
||||
name: 'userCredentials',
|
||||
url: '/users/:user_id/credentials',
|
||||
@ -500,70 +454,6 @@ var tower = angular.module('Tower', [
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.deletePermissionFromUser = function(userId, userName, roleName, roleType, url) {
|
||||
var action = function() {
|
||||
$('#prompt-modal').modal('hide');
|
||||
Wait('start');
|
||||
Rest.setUrl(url);
|
||||
Rest.post({ "disassociate": true, "id": userId })
|
||||
.success(function() {
|
||||
Wait('stop');
|
||||
$rootScope.$broadcast("refreshList", "permission");
|
||||
})
|
||||
.error(function(data, status) {
|
||||
ProcessErrors($rootScope, data, status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Could not disassociate user from role. Call to ' + url + ' failed. DELETE returned status: ' + status
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({
|
||||
hdr: `Remove role`,
|
||||
body: `
|
||||
<div class="Prompt-bodyQuery">
|
||||
Confirm the removal of the ${roleType}
|
||||
<span class="Prompt-emphasis"> ${roleName} </span>
|
||||
role associated with ${userName}.
|
||||
</div>
|
||||
`,
|
||||
action: action,
|
||||
actionText: 'REMOVE'
|
||||
});
|
||||
};
|
||||
|
||||
$rootScope.deletePermissionFromTeam = function(teamId, teamName, roleName, roleType, url) {
|
||||
var action = function() {
|
||||
$('#prompt-modal').modal('hide');
|
||||
Wait('start');
|
||||
Rest.setUrl(url);
|
||||
Rest.post({ "disassociate": true, "id": teamId })
|
||||
.success(function() {
|
||||
Wait('stop');
|
||||
$rootScope.$broadcast("refreshList", "role");
|
||||
})
|
||||
.error(function(data, status) {
|
||||
ProcessErrors($rootScope, data, status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Could not disassociate team from role. Call to ' + url + ' failed. DELETE returned status: ' + status
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Prompt({
|
||||
hdr: `Remove role`,
|
||||
body: `
|
||||
<div class="Prompt-bodyQuery">
|
||||
Confirm the removal of the ${roleType}
|
||||
<span class="Prompt-emphasis"> ${roleName} </span>
|
||||
role associated with the ${teamName} team.
|
||||
</div>
|
||||
`,
|
||||
action: action,
|
||||
actionText: 'REMOVE'
|
||||
});
|
||||
};
|
||||
|
||||
function activateTab() {
|
||||
// Make the correct tab active
|
||||
var base = $location.path().replace(/^\//, '').split('/')[0];
|
||||
|
||||
@ -10,14 +10,16 @@
|
||||
* @description This controller's for the jobs page
|
||||
*/
|
||||
|
||||
|
||||
|
||||
export function JobsListController($state, $rootScope, $log, $scope, $compile, $stateParams,
|
||||
ClearScope, Find, DeleteJob, RelaunchJob, AllJobsList, ScheduledJobsList, GetBasePath, Dataset, qs) {
|
||||
export default ['$state', '$rootScope', '$log', '$scope', '$compile', '$stateParams',
|
||||
'ClearScope', 'Find', 'DeleteJob', 'RelaunchJob', 'AllJobsList', 'ScheduledJobsList',
|
||||
'GetBasePath', 'Dataset', 'QuerySet', 'ListDefinition', '$interpolate',
|
||||
function($state, $rootScope, $log, $scope, $compile, $stateParams,
|
||||
ClearScope, Find, DeleteJob, RelaunchJob, AllJobsList, ScheduledJobsList,
|
||||
GetBasePath, Dataset, qs, ListDefinition, $interpolate) {
|
||||
|
||||
ClearScope();
|
||||
|
||||
var list = AllJobsList;
|
||||
var list = ListDefinition;
|
||||
|
||||
init();
|
||||
|
||||
@ -44,27 +46,29 @@ export function JobsListController($state, $rootScope, $log, $scope, $compile, $
|
||||
// OPTIONS request returns, or the list is sorted/paginated/searched
|
||||
function optionsRequestDataProcessing(){
|
||||
|
||||
$scope[list.name].forEach(function(item, item_idx) {
|
||||
var itm = $scope[list.name][item_idx];
|
||||
if($scope[list.name] && $scope[list.name].length > 0) {
|
||||
$scope[list.name].forEach(function(item, item_idx) {
|
||||
var itm = $scope[list.name][item_idx];
|
||||
|
||||
if(item.summary_fields && item.summary_fields.source_workflow_job &&
|
||||
item.summary_fields.source_workflow_job.id){
|
||||
item.workflow_result_link = `/#/workflows/${item.summary_fields.source_workflow_job.id}`;
|
||||
}
|
||||
|
||||
// Set the item type label
|
||||
if (list.fields.type && $scope.options &&
|
||||
$scope.options.hasOwnProperty('type')) {
|
||||
$scope.options.type.choices.every(function(choice) {
|
||||
if (choice[0] === item.type) {
|
||||
itm.type_label = choice[1];
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if(item.summary_fields && item.summary_fields.source_workflow_job &&
|
||||
item.summary_fields.source_workflow_job.id){
|
||||
item.workflow_result_link = `/#/workflows/${item.summary_fields.source_workflow_job.id}`;
|
||||
}
|
||||
buildTooltips(itm);
|
||||
});
|
||||
|
||||
// Set the item type label
|
||||
if (list.fields.type && $scope.options &&
|
||||
$scope.options.hasOwnProperty('type')) {
|
||||
$scope.options.type.choices.every(function(choice) {
|
||||
if (choice[0] === item.type) {
|
||||
itm.type_label = choice[1];
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
buildTooltips(itm);
|
||||
});
|
||||
}
|
||||
}
|
||||
function buildTooltips(job) {
|
||||
job.status_tip = 'Job ' + job.status + ". Click for details.";
|
||||
@ -75,14 +79,31 @@ export function JobsListController($state, $rootScope, $log, $scope, $compile, $
|
||||
};
|
||||
|
||||
$scope.relaunchJob = function(event, id) {
|
||||
var job, typeId;
|
||||
let job, typeId, jobs;
|
||||
try {
|
||||
$(event.target).tooltip('hide');
|
||||
} catch (e) {
|
||||
//ignore
|
||||
}
|
||||
|
||||
job = Find({ list: $scope.jobs, key: 'id', val: id });
|
||||
if ($scope.completed_jobs) {
|
||||
jobs = $scope.completed_jobs;
|
||||
}
|
||||
else if ($scope.running_jobs) {
|
||||
jobs = $scope.running_jobs;
|
||||
}
|
||||
else if ($scope.queued_jobs) {
|
||||
jobs = $scope.queued_jobs;
|
||||
}
|
||||
else if ($scope.all_jobs) {
|
||||
jobs = $scope.all_jobs;
|
||||
}
|
||||
else if ($scope.jobs) {
|
||||
jobs = $scope.jobs;
|
||||
}
|
||||
|
||||
job = Find({list: jobs, key: 'id', val: id });
|
||||
|
||||
if (job.type === 'inventory_update') {
|
||||
typeId = job.inventory_source;
|
||||
} else if (job.type === 'project_update') {
|
||||
@ -122,7 +143,14 @@ export function JobsListController($state, $rootScope, $log, $scope, $compile, $
|
||||
};
|
||||
|
||||
$scope.$on('ws-jobs', function(){
|
||||
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
|
||||
let path;
|
||||
if (GetBasePath(list.basePath) || GetBasePath(list.name)) {
|
||||
path = GetBasePath(list.basePath) || GetBasePath(list.name);
|
||||
} else {
|
||||
// completed jobs base path involves $stateParams
|
||||
let interpolator = $interpolate(list.basePath);
|
||||
path = interpolator({ $rootScope: $rootScope, $stateParams: $stateParams });
|
||||
}
|
||||
qs.search(path, $state.params[`${list.iterator}_search`])
|
||||
.then(function(searchResponse) {
|
||||
$scope[`${list.iterator}_dataset`] = searchResponse.data;
|
||||
@ -133,8 +161,4 @@ export function JobsListController($state, $rootScope, $log, $scope, $compile, $
|
||||
$scope.$on('ws-schedules', function(){
|
||||
$state.reload();
|
||||
});
|
||||
}
|
||||
|
||||
JobsListController.$inject = ['$state', '$rootScope', '$log', '$scope', '$compile', '$stateParams',
|
||||
'ClearScope', 'Find', 'DeleteJob', 'RelaunchJob', 'AllJobsList', 'ScheduledJobsList', 'GetBasePath', 'Dataset','QuerySet'
|
||||
];
|
||||
}];
|
||||
58
awx/ui/client/src/jobs/jobs.route.js
Normal file
58
awx/ui/client/src/jobs/jobs.route.js
Normal file
@ -0,0 +1,58 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2016 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
import { N_ } from '../i18n';
|
||||
import {templateUrl} from '../shared/template-url/template-url.factory';
|
||||
|
||||
export default {
|
||||
searchPrefix: 'job',
|
||||
name: 'jobs',
|
||||
url: '/jobs',
|
||||
ncyBreadcrumb: {
|
||||
label: N_("JOBS")
|
||||
},
|
||||
params: {
|
||||
job_search: {
|
||||
value: {
|
||||
not__launch_type: 'sync',
|
||||
order_by: '-finished'
|
||||
},
|
||||
squash: ''
|
||||
}
|
||||
},
|
||||
data: {
|
||||
socket: {
|
||||
"groups": {
|
||||
"jobs": ["status_changed"],
|
||||
"schedules": ["changed"]
|
||||
}
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
Dataset: ['AllJobsList', 'QuerySet', '$stateParams', 'GetBasePath', (list, qs, $stateParams, GetBasePath) => {
|
||||
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
|
||||
return qs.search(path, $stateParams[`${list.iterator}_search`]);
|
||||
}],
|
||||
ListDefinition: ['AllJobsList', (list) => {
|
||||
return list;
|
||||
}]
|
||||
},
|
||||
views: {
|
||||
'@': {
|
||||
templateUrl: templateUrl('jobs/jobs')
|
||||
},
|
||||
'list@jobs': {
|
||||
templateProvider: function(AllJobsList, generateList) {
|
||||
let html = generateList.build({
|
||||
list: AllJobsList,
|
||||
mode: 'edit'
|
||||
});
|
||||
return html;
|
||||
},
|
||||
controller: 'JobsList'
|
||||
}
|
||||
}
|
||||
};
|
||||
15
awx/ui/client/src/jobs/main.js
Normal file
15
awx/ui/client/src/jobs/main.js
Normal file
@ -0,0 +1,15 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2017 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
import jobsList from './jobs-list.controller';
|
||||
import jobsRoute from './jobs.route';
|
||||
|
||||
export default
|
||||
angular.module('JobsModule', [])
|
||||
.run(['$stateExtender', function($stateExtender) {
|
||||
$stateExtender.addState(jobsRoute);
|
||||
}])
|
||||
.controller('JobsList', jobsList);
|
||||
@ -230,7 +230,7 @@ export default ['$injector', '$stateExtender', '$log', 'i18n', function($injecto
|
||||
break;
|
||||
}
|
||||
states.push(formNode);
|
||||
states = states.concat(this.generateLookupNodes(form, formNode)).concat(this.generateFormListDefinitions(form, formNode));
|
||||
states = states.concat(this.generateLookupNodes(form, formNode)).concat(this.generateFormListDefinitions(form, formNode, params));
|
||||
return states;
|
||||
},
|
||||
/**
|
||||
@ -241,7 +241,7 @@ export default ['$injector', '$stateExtender', '$log', 'i18n', function($injecto
|
||||
* @params {object} formStateDefinition - the parent form node
|
||||
* @returns {array} Array of state definitions [{...}, {...}, ...]
|
||||
*/
|
||||
generateFormListDefinitions: function(form, formStateDefinition) {
|
||||
generateFormListDefinitions: function(form, formStateDefinition, params) {
|
||||
|
||||
function buildRbacUserTeamDirective(){
|
||||
let states = [];
|
||||
@ -559,14 +559,17 @@ export default ['$injector', '$stateExtender', '$log', 'i18n', function($injecto
|
||||
|
||||
function buildListDefinition(field) {
|
||||
let state,
|
||||
list = field.include ? $injector.get(field.include) : field;
|
||||
state = $stateExtender.buildDefinition({
|
||||
list = field.include ? $injector.get(field.include) : field,
|
||||
// Added this line specifically for Completed Jobs but should be OK
|
||||
// for all the rest of the related tabs
|
||||
breadcrumbLabel = field.iterator.replace('_', ' '),
|
||||
stateConfig = {
|
||||
searchPrefix: `${list.iterator}`,
|
||||
name: `${formStateDefinition.name}.${list.iterator}s`,
|
||||
url: `/${list.iterator}s`,
|
||||
ncyBreadcrumb: {
|
||||
parent: `${formStateDefinition.name}`,
|
||||
label: `${field.iterator}s`
|
||||
label: `${breadcrumbLabel}s`
|
||||
},
|
||||
params: {
|
||||
[list.iterator + '_search']: {
|
||||
@ -583,14 +586,7 @@ export default ['$injector', '$stateExtender', '$log', 'i18n', function($injecto
|
||||
FormDefinition() : FormDefinition
|
||||
});
|
||||
return html;
|
||||
},
|
||||
controller: ['$scope', 'ListDefinition', 'Dataset',
|
||||
function($scope, list, Dataset) {
|
||||
$scope.list = list;
|
||||
$scope[`${list.iterator}_dataset`] = Dataset.data;
|
||||
$scope[`${list.iterator}s`] = $scope[`${list.iterator}_dataset`].results;
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
@ -611,7 +607,26 @@ export default ['$injector', '$stateExtender', '$log', 'i18n', function($injecto
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if(params.controllers && params.controllers.related && params.controllers.related[field.name]) {
|
||||
stateConfig.views.related.controller = params.controllers.related[field.name];
|
||||
}
|
||||
else if(field.name === 'permissions') {
|
||||
stateConfig.views.related.controller = 'PermissionsList';
|
||||
}
|
||||
else {
|
||||
// Generic controller
|
||||
stateConfig.views.related.controller = ['$scope', 'ListDefinition', 'Dataset',
|
||||
function($scope, list, Dataset) {
|
||||
$scope.list = list;
|
||||
$scope[`${list.iterator}_dataset`] = Dataset.data;
|
||||
$scope[`${list.iterator}s`] = $scope[`${list.iterator}_dataset`].results;
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
state = $stateExtender.buildDefinition(stateConfig);
|
||||
// appy any default search parameters in form definition
|
||||
if (field.search) {
|
||||
state.params[`${field.iterator}_search`].value = _.merge(state.params[`${field.iterator}_search`].value, field.search);
|
||||
|
||||
@ -52,7 +52,10 @@ angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplatesA
|
||||
modes: ['edit'],
|
||||
form: 'JobTemplateForm',
|
||||
controllers: {
|
||||
edit: 'JobTemplateEdit'
|
||||
edit: 'JobTemplateEdit',
|
||||
related: {
|
||||
completed_jobs: 'JobsList'
|
||||
}
|
||||
},
|
||||
data: {
|
||||
activityStream: true,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user