mirror of
https://github.com/ansible/awx.git
synced 2026-05-19 14:57:39 -02:30
working batch requests
This commit is contained in:
@@ -17,7 +17,6 @@ export default ['$compile','templateUrl', 'i18n', 'generateList',
|
|||||||
selected: "="
|
selected: "="
|
||||||
},
|
},
|
||||||
link: function(scope, element, attrs) {
|
link: function(scope, element, attrs) {
|
||||||
console.log(scope.resourceType)
|
|
||||||
let listMap, list, list_html;
|
let listMap, list, list_html;
|
||||||
|
|
||||||
listMap = {
|
listMap = {
|
||||||
@@ -28,12 +27,12 @@ export default ['$compile','templateUrl', 'i18n', 'generateList',
|
|||||||
credentials: CredentialList
|
credentials: CredentialList
|
||||||
};
|
};
|
||||||
|
|
||||||
list = _.cloneDeep(listMap[scope.resourceType])
|
list = _.cloneDeep(listMap[scope.resourceType]);
|
||||||
|
|
||||||
list.fieldActions = {
|
list.fieldActions = {
|
||||||
remove: {
|
remove: {
|
||||||
ngClick: `removeSelection(${list.iterator}, resourceType)`,
|
ngClick: `removeSelection(${list.iterator}, resourceType)`,
|
||||||
icon: 'fa-remove',
|
iconClass: 'fa fa-times-circle',
|
||||||
awToolTip: i18n._(`Remove ${list.iterator}`),
|
awToolTip: i18n._(`Remove ${list.iterator}`),
|
||||||
label: i18n._('Remove'),
|
label: i18n._('Remove'),
|
||||||
class: 'btn-sm'
|
class: 'btn-sm'
|
||||||
@@ -43,6 +42,8 @@ export default ['$compile','templateUrl', 'i18n', 'generateList',
|
|||||||
|
|
||||||
list.listTitleBadge = false;
|
list.listTitleBadge = false;
|
||||||
|
|
||||||
|
// @issue - fix field.columnClass values for this view
|
||||||
|
|
||||||
switch(scope.resourceType){
|
switch(scope.resourceType){
|
||||||
|
|
||||||
case 'projects':
|
case 'projects':
|
||||||
@@ -77,8 +78,7 @@ export default ['$compile','templateUrl', 'i18n', 'generateList',
|
|||||||
description: list.fields.description
|
description: list.fields.description
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
case 'credentials':
|
||||||
default:
|
|
||||||
list.fields = {
|
list.fields = {
|
||||||
name: list.fields.name,
|
name: list.fields.name,
|
||||||
description: list.fields.description
|
description: list.fields.description
|
||||||
@@ -93,12 +93,31 @@ export default ['$compile','templateUrl', 'i18n', 'generateList',
|
|||||||
related: false,
|
related: false,
|
||||||
title: false,
|
title: false,
|
||||||
showSearch: false,
|
showSearch: false,
|
||||||
|
showEmptyPanel: false,
|
||||||
paginate: false
|
paginate: false
|
||||||
});
|
});
|
||||||
|
|
||||||
scope.list = list;
|
scope.list = list;
|
||||||
scope[`${list.iterator}_dataset`] = scope.collection;
|
|
||||||
scope[list.name] = scope.collection;
|
scope.$watchCollection('collection', function(selected){
|
||||||
|
scope[`${list.iterator}_dataset`] = scope.collection;
|
||||||
|
scope[list.name] = _.values(scope.collection);
|
||||||
|
});
|
||||||
|
|
||||||
|
scope.removeSelection = function(resource, type){
|
||||||
|
let multiselect_scope, deselectedIdx;
|
||||||
|
|
||||||
|
delete scope.collection[resource.id];
|
||||||
|
delete scope.selected[type][resource.id];
|
||||||
|
|
||||||
|
// a quick & dirty hack
|
||||||
|
// section 1 and section 2 elements produce sibling scopes
|
||||||
|
// This means events propogated from section 2 are not received in section 1
|
||||||
|
// The following code directly accesses the right scope by list table id
|
||||||
|
multiselect_scope = angular.element('#AddPermissions-body').find(`#${type}_table`).scope()
|
||||||
|
deselectedIdx = _.findIndex(multiselect_scope[type], {id: resource.id});
|
||||||
|
multiselect_scope[type][deselectedIdx].isSelected = false;
|
||||||
|
};
|
||||||
|
|
||||||
element.append(list_html);
|
element.append(list_html);
|
||||||
$compile(element.contents())(scope);
|
$compile(element.contents())(scope);
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
* Controller for handling permissions adding
|
* Controller for handling permissions adding
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default ['$rootScope', '$scope', '$state', 'GetBasePath', 'Rest', '$q', 'Wait', 'ProcessErrors',
|
export default ['$rootScope', '$scope', '$state', 'i18n', 'CreateSelect2', 'GetBasePath', 'Rest', '$q', 'Wait', 'ProcessErrors',
|
||||||
function(rootScope, scope, $state, GetBasePath, Rest, $q, Wait, ProcessErrors) {
|
function(rootScope, scope, $state, i18n, CreateSelect2, GetBasePath, Rest, $q, Wait, ProcessErrors) {
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
@@ -24,12 +24,20 @@ function(rootScope, scope, $state, GetBasePath, Rest, $q, Wait, ProcessErrors) {
|
|||||||
// selected - keyed by type of resource
|
// selected - keyed by type of resource
|
||||||
// selected[type] - keyed by each resource object's id
|
// selected[type] - keyed by each resource object's id
|
||||||
// selected[type][id] === { roles: [ ... ], ... }
|
// selected[type][id] === { roles: [ ... ], ... }
|
||||||
|
|
||||||
|
// collection of resources selected in section 1
|
||||||
scope.selected = {};
|
scope.selected = {};
|
||||||
_.each(resources, (resource) => scope.selected[resource] = {});
|
_.each(resources, (type) => scope.selected[type] = {});
|
||||||
|
|
||||||
|
// collection of assignable roles per type of resource
|
||||||
scope.keys = {};
|
scope.keys = {};
|
||||||
_.each(resources, (resource) => scope.keys[resource] = {});
|
_.each(resources, (type) => scope.keys[type] = {});
|
||||||
|
|
||||||
|
// collection of currently-selected role to assign in section 2
|
||||||
|
scope.roleSelection = {};
|
||||||
|
_.each(resources, (type) => scope.roleSelection[type] = null);
|
||||||
|
|
||||||
|
// tracks currently-selected tabs, initialized with the job templates tab open
|
||||||
scope.tab = {
|
scope.tab = {
|
||||||
job_templates: true,
|
job_templates: true,
|
||||||
workflow_templates: false,
|
workflow_templates: false,
|
||||||
@@ -37,13 +45,39 @@ function(rootScope, scope, $state, GetBasePath, Rest, $q, Wait, ProcessErrors) {
|
|||||||
inventories: false,
|
inventories: false,
|
||||||
credentials: false
|
credentials: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// initializes select2 per select field
|
||||||
|
// html snippet:
|
||||||
|
/*
|
||||||
|
<div ng-repeat="(type, roleSet) in keys">
|
||||||
|
<select
|
||||||
|
ng-show="tab[type]"
|
||||||
|
id="{{type}}-role-select" class="form-control"
|
||||||
|
ng-model="roleSelection[type]"
|
||||||
|
ng-options="value.name for (key , value) in roleSet">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
*/
|
||||||
|
_.each(resources, (type) => buildSelect2(type));
|
||||||
|
|
||||||
|
function buildSelect2(type){
|
||||||
|
CreateSelect2({
|
||||||
|
element: `#${type}-role-select`,
|
||||||
|
multiple: false,
|
||||||
|
placeholder: i18n._('Select a role')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
scope.showKeyPane = false;
|
scope.showKeyPane = false;
|
||||||
|
|
||||||
|
// the user or team being assigned permissions
|
||||||
scope.owner = scope.resolve.resourceData.data;
|
scope.owner = scope.resolve.resourceData.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// aggregate name/descriptions for each available role, based on resource type
|
// aggregate name/descriptions for each available role, based on resource type
|
||||||
|
// reasoning:
|
||||||
function aggregateKey(item, type){
|
function aggregateKey(item, type){
|
||||||
_.merge(scope.keys[type], item.summary_fields.object_roles);
|
_.merge(scope.keys[type], _.omit(item.summary_fields.object_roles, 'read_role'));
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.closeModal = function() {
|
scope.closeModal = function() {
|
||||||
@@ -66,11 +100,6 @@ function(rootScope, scope, $state, GetBasePath, Rest, $q, Wait, ProcessErrors) {
|
|||||||
return Object.keys(scope.selected[tab]).length > 0;
|
return Object.keys(scope.selected[tab]).length > 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
scope.removeSelection = function(resource, type){
|
|
||||||
delete scope.selected[type][resource.id];
|
|
||||||
resource.isSelected = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// handle form tab changes
|
// handle form tab changes
|
||||||
scope.selectTab = function(selected){
|
scope.selectTab = function(selected){
|
||||||
_.each(scope.tab, (value, key, collection) => {
|
_.each(scope.tab, (value, key, collection) => {
|
||||||
@@ -78,7 +107,7 @@ function(rootScope, scope, $state, GetBasePath, Rest, $q, Wait, ProcessErrors) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// pop/push into unified collection of selected users & teams
|
// pop/push into unified collection of selected resourcesf
|
||||||
scope.$on("selectedOrDeselected", function(e, value) {
|
scope.$on("selectedOrDeselected", function(e, value) {
|
||||||
let resourceType = scope.currentTab(),
|
let resourceType = scope.currentTab(),
|
||||||
item = value.value;
|
item = value.value;
|
||||||
@@ -94,15 +123,20 @@ function(rootScope, scope, $state, GetBasePath, Rest, $q, Wait, ProcessErrors) {
|
|||||||
|
|
||||||
// post roles to api
|
// post roles to api
|
||||||
scope.saveForm = function() {
|
scope.saveForm = function() {
|
||||||
Wait('start');
|
//Wait('start');
|
||||||
// scope.selected => { n: {id: n}, ... } => [ {id: n}, ... ]
|
|
||||||
let requests = _(scope.selected).map((type) => {
|
// builds an array of role entities to apply to current user or team
|
||||||
return _.map(type, (resource) => resource.roles);
|
let roles = _(scope.selected).map( (resources, type) =>{
|
||||||
|
return _.map(resources, (resource) => {
|
||||||
|
return resource.summary_fields.object_roles[scope.roleSelection[type]]
|
||||||
|
});
|
||||||
}).flattenDeep().value();
|
}).flattenDeep().value();
|
||||||
|
|
||||||
|
debugger;
|
||||||
|
|
||||||
Rest.setUrl(scope.owner.related.roles);
|
Rest.setUrl(scope.owner.related.roles);
|
||||||
|
|
||||||
$q.all( _.map(requests, (entity) => Rest.post({id: entity.id})) )
|
$q.all( _.map(roles, (entity) => Rest.post({id: entity.id})) )
|
||||||
.then( () =>{
|
.then( () =>{
|
||||||
Wait('stop');
|
Wait('stop');
|
||||||
scope.closeModal();
|
scope.closeModal();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- end header -->
|
<!-- end header -->
|
||||||
<div class="AddPermissions-body">
|
<div id="AddPermissions-body" class="AddPermissions-body">
|
||||||
<!-- begin section 1 -->
|
<!-- begin section 1 -->
|
||||||
<div class="AddPermissions-directions">
|
<div class="AddPermissions-directions">
|
||||||
<span class="AddPermissions-directionNumber">
|
<span class="AddPermissions-directionNumber">
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
<div id="AddPermissions-jobTemplates" class="AddPermissions-list" ng-show="tab.job_templates">
|
<div id="AddPermissions-jobTemplates" class="AddPermissions-list" ng-show="tab.job_templates">
|
||||||
<rbac-multiselect-list view="JobTemplates" all-selected="allSelected" dataset="resolve.jobTemplatesDataset"></rbac-multiselect-list>
|
<rbac-multiselect-list view="JobTemplates" all-selected="allSelected" dataset="resolve.jobTemplatesDataset"></rbac-multiselect-list>
|
||||||
</div>
|
</div>
|
||||||
<div id="AddPermissions-jobTemplates" class="AddPermissions-list" ng-show="tab.workflow_templates">
|
<div id="AddPermissions-workflowTemplates" class="AddPermissions-list" ng-show="tab.workflow_templates">
|
||||||
<rbac-multiselect-list view="WorkflowTemplates" all-selected="allSelected" dataset="resolve.workflowTemplatesDataset"></rbac-multiselect-list>
|
<rbac-multiselect-list view="WorkflowTemplates" all-selected="allSelected" dataset="resolve.workflowTemplatesDataset"></rbac-multiselect-list>
|
||||||
</div>
|
</div>
|
||||||
<div id="AddPermissions-projects" class="AddPermissions-list" ng-show="tab.projects">
|
<div id="AddPermissions-projects" class="AddPermissions-list" ng-show="tab.projects">
|
||||||
@@ -141,7 +141,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- role drop-down -->
|
<!-- role drop-downs -->
|
||||||
|
<div ng-repeat="(type, roleSet) in keys" ng-show="tab[type]">
|
||||||
|
<select
|
||||||
|
id="{{type}}-role-select" class="form-control"
|
||||||
|
ng-model="roleSelection[type]"
|
||||||
|
ng-options="key as value.name for (key , value) in roleSet">
|
||||||
|
<option value="" selected hidden />
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- lists of selected resources -->
|
<!-- lists of selected resources -->
|
||||||
<!-- (type, collection) => ('resource', {id: {}, ... }) -->
|
<!-- (type, collection) => ('resource', {id: {}, ... }) -->
|
||||||
@@ -149,7 +157,8 @@
|
|||||||
<rbac-selected-list
|
<rbac-selected-list
|
||||||
resource-type="type"
|
resource-type="type"
|
||||||
collection="collection"
|
collection="collection"
|
||||||
selected="selected">
|
selected="selected"
|
||||||
|
ng-show="tab[type]">
|
||||||
</rbac-selected-list>
|
</rbac-selected-list>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -167,7 +176,7 @@
|
|||||||
<button type="button"
|
<button type="button"
|
||||||
class="btn btn-sm Form-saveButton"
|
class="btn btn-sm Form-saveButton"
|
||||||
ng-click="saveForm()"
|
ng-click="saveForm()"
|
||||||
ng-disabled="multiselectRoles.$invalid || !showSection2Container()">
|
ng-disabled="!showSection2Container()">
|
||||||
Save
|
Save
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -70,7 +70,13 @@ export default ['addPermissionsTeamsList', 'addPermissionsUsersList', 'TemplateL
|
|||||||
description: list.fields.description
|
description: list.fields.description
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
case 'Users':
|
||||||
|
list.fields = {
|
||||||
|
username: list.fields.username,
|
||||||
|
first_name: list.fields.first_name,
|
||||||
|
last_name: list.fields.last_name
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
list.fields = {
|
list.fields = {
|
||||||
name: list.fields.name,
|
name: list.fields.name,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export default
|
|||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
scope: true,
|
scope: true,
|
||||||
templateUrl: templateUrl('access/rbac-role-list/roleList'),
|
templateUrl: templateUrl('access/rbac-role-column/roleList'),
|
||||||
link: function(scope, element, attrs) {
|
link: function(scope, element, attrs) {
|
||||||
// given a list of roles (things like "project
|
// given a list of roles (things like "project
|
||||||
// auditor") which are pulled from two different
|
// auditor") which are pulled from two different
|
||||||
|
|||||||
@@ -241,9 +241,11 @@ export default ['$location', '$compile', '$rootScope', 'Attr', 'Icon',
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show the "no items" box when loading is done and the user isn't actively searching and there are no results
|
// Show the "no items" box when loading is done and the user isn't actively searching and there are no results
|
||||||
html += `<div class="List-noItems" ng-show="${list.name}.length === 0 && (searchTags | isEmpty)">`;
|
if (options.showEmptyPanel === undefined || options.showEmptyPanel === true){
|
||||||
html += (list.emptyListText) ? list.emptyListText : i18n._("PLEASE ADD ITEMS TO THIS LIST");
|
html += `<div class="List-noItems" ng-show="${list.name}.length === 0 && (searchTags | isEmpty)">`;
|
||||||
html += "</div>";
|
html += (list.emptyListText) ? list.emptyListText : i18n._("PLEASE ADD ITEMS TO THIS LIST");
|
||||||
|
html += "</div>";
|
||||||
|
}
|
||||||
|
|
||||||
// Add a title and optionally a close button (used on Inventory->Groups)
|
// Add a title and optionally a close button (used on Inventory->Groups)
|
||||||
if (options.mode !== 'lookup' && list.showTitle) {
|
if (options.mode !== 'lookup' && list.showTitle) {
|
||||||
|
|||||||
Reference in New Issue
Block a user