mirror of
https://github.com/ansible/awx.git
synced 2026-03-18 17:37:30 -02:30
Add a Galaxy Credential multi-select field to the Organizations form
This commit is contained in:
@@ -4,11 +4,12 @@
|
|||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
export default ['$scope', '$rootScope', '$location', '$stateParams',
|
export default ['$scope', '$rootScope', '$location', '$stateParams', 'OrganizationForm',
|
||||||
'OrganizationForm', 'GenerateForm', 'Rest', 'Alert',
|
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'GetBasePath', 'Wait', 'CreateSelect2',
|
||||||
'ProcessErrors', 'GetBasePath', 'Wait', 'CreateSelect2', '$state','InstanceGroupsService', 'ConfigData',
|
'$state','InstanceGroupsService', 'ConfigData', 'MultiCredentialService',
|
||||||
function($scope, $rootScope, $location, $stateParams, OrganizationForm,
|
function($scope, $rootScope, $location, $stateParams, OrganizationForm,
|
||||||
GenerateForm, Rest, Alert, ProcessErrors, GetBasePath, Wait, CreateSelect2, $state, InstanceGroupsService, ConfigData) {
|
GenerateForm, Rest, Alert, ProcessErrors, GetBasePath, Wait, CreateSelect2,
|
||||||
|
$state, InstanceGroupsService, ConfigData, MultiCredentialService) {
|
||||||
|
|
||||||
Rest.setUrl(GetBasePath('organizations'));
|
Rest.setUrl(GetBasePath('organizations'));
|
||||||
Rest.options()
|
Rest.options()
|
||||||
@@ -57,18 +58,32 @@ export default ['$scope', '$rootScope', '$location', '$stateParams',
|
|||||||
const organization_id = data.id,
|
const organization_id = data.id,
|
||||||
instance_group_url = data.related.instance_groups;
|
instance_group_url = data.related.instance_groups;
|
||||||
|
|
||||||
InstanceGroupsService.addInstanceGroups(instance_group_url, $scope.instance_groups)
|
MultiCredentialService
|
||||||
|
.saveRelatedSequentially({
|
||||||
|
related: {
|
||||||
|
credentials: data.related.galaxy_credentials
|
||||||
|
}
|
||||||
|
}, $scope.credentials)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
Wait('stop');
|
InstanceGroupsService.addInstanceGroups(instance_group_url, $scope.instance_groups)
|
||||||
$rootScope.$broadcast("EditIndicatorChange", "organizations", organization_id);
|
.then(() => {
|
||||||
$state.go('organizations.edit', {organization_id: organization_id}, {reload: true});
|
Wait('stop');
|
||||||
})
|
$rootScope.$broadcast("EditIndicatorChange", "organizations", organization_id);
|
||||||
.catch(({data, status}) => {
|
$state.go('organizations.edit', {organization_id: organization_id}, {reload: true});
|
||||||
|
})
|
||||||
|
.catch(({data, status}) => {
|
||||||
|
ProcessErrors($scope, data, status, form, {
|
||||||
|
hdr: 'Error!',
|
||||||
|
msg: 'Failed to save instance groups. POST returned status: ' + status
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}).catch(({data, status}) => {
|
||||||
ProcessErrors($scope, data, status, form, {
|
ProcessErrors($scope, data, status, form, {
|
||||||
hdr: 'Error!',
|
hdr: 'Error!',
|
||||||
msg: 'Failed to save instance groups. POST returned status: ' + status
|
msg: 'Failed to save Galaxy credentials. POST returned status: ' + status
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch(({data, status}) => {
|
.catch(({data, status}) => {
|
||||||
let explanation = _.has(data, "name") ? data.name[0] : "";
|
let explanation = _.has(data, "name") ? data.name[0] : "";
|
||||||
|
|||||||
@@ -6,10 +6,12 @@
|
|||||||
|
|
||||||
export default ['$scope', '$location', '$stateParams', 'isOrgAdmin', 'isNotificationAdmin',
|
export default ['$scope', '$location', '$stateParams', 'isOrgAdmin', 'isNotificationAdmin',
|
||||||
'OrganizationForm', 'Rest', 'ProcessErrors', 'Prompt', 'i18n', 'isOrgAuditor',
|
'OrganizationForm', 'Rest', 'ProcessErrors', 'Prompt', 'i18n', 'isOrgAuditor',
|
||||||
'GetBasePath', 'Wait', '$state', 'ToggleNotification', 'CreateSelect2', 'InstanceGroupsService', 'InstanceGroupsData', 'ConfigData',
|
'GetBasePath', 'Wait', '$state', 'ToggleNotification', 'CreateSelect2', 'InstanceGroupsService',
|
||||||
|
'InstanceGroupsData', 'ConfigData', 'GalaxyCredentialsData', 'MultiCredentialService',
|
||||||
function($scope, $location, $stateParams, isOrgAdmin, isNotificationAdmin,
|
function($scope, $location, $stateParams, isOrgAdmin, isNotificationAdmin,
|
||||||
OrganizationForm, Rest, ProcessErrors, Prompt, i18n, isOrgAuditor,
|
OrganizationForm, Rest, ProcessErrors, Prompt, i18n, isOrgAuditor,
|
||||||
GetBasePath, Wait, $state, ToggleNotification, CreateSelect2, InstanceGroupsService, InstanceGroupsData, ConfigData) {
|
GetBasePath, Wait, $state, ToggleNotification, CreateSelect2, InstanceGroupsService,
|
||||||
|
InstanceGroupsData, ConfigData, GalaxyCredentialsData, MultiCredentialService) {
|
||||||
|
|
||||||
let form = OrganizationForm(),
|
let form = OrganizationForm(),
|
||||||
defaultUrl = GetBasePath('organizations'),
|
defaultUrl = GetBasePath('organizations'),
|
||||||
@@ -29,6 +31,7 @@ export default ['$scope', '$location', '$stateParams', 'isOrgAdmin', 'isNotifica
|
|||||||
});
|
});
|
||||||
|
|
||||||
$scope.instance_groups = InstanceGroupsData;
|
$scope.instance_groups = InstanceGroupsData;
|
||||||
|
$scope.credentials = GalaxyCredentialsData;
|
||||||
const virtualEnvs = ConfigData.custom_virtualenvs || [];
|
const virtualEnvs = ConfigData.custom_virtualenvs || [];
|
||||||
$scope.custom_virtualenvs_visible = virtualEnvs.length > 1;
|
$scope.custom_virtualenvs_visible = virtualEnvs.length > 1;
|
||||||
$scope.custom_virtualenvs_options = virtualEnvs.filter(
|
$scope.custom_virtualenvs_options = virtualEnvs.filter(
|
||||||
@@ -100,7 +103,14 @@ export default ['$scope', '$location', '$stateParams', 'isOrgAdmin', 'isNotifica
|
|||||||
Rest.setUrl(defaultUrl + id + '/');
|
Rest.setUrl(defaultUrl + id + '/');
|
||||||
Rest.put(params)
|
Rest.put(params)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
InstanceGroupsService.editInstanceGroups(instance_group_url, $scope.instance_groups)
|
MultiCredentialService
|
||||||
|
.saveRelatedSequentially({
|
||||||
|
related: {
|
||||||
|
credentials: $scope.organization_obj.related.galaxy_credentials
|
||||||
|
}
|
||||||
|
}, $scope.credentials)
|
||||||
|
.then(() => {
|
||||||
|
InstanceGroupsService.editInstanceGroups(instance_group_url, $scope.instance_groups)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
Wait('stop');
|
Wait('stop');
|
||||||
$state.go($state.current, {}, { reload: true });
|
$state.go($state.current, {}, { reload: true });
|
||||||
@@ -111,6 +121,12 @@ export default ['$scope', '$location', '$stateParams', 'isOrgAdmin', 'isNotifica
|
|||||||
msg: 'Failed to update instance groups. POST returned status: ' + status
|
msg: 'Failed to update instance groups. POST returned status: ' + status
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}).catch(({data, status}) => {
|
||||||
|
ProcessErrors($scope, data, status, form, {
|
||||||
|
hdr: 'Error!',
|
||||||
|
msg: 'Failed to save Galaxy credentials. POST returned status: ' + status
|
||||||
|
});
|
||||||
|
});
|
||||||
$scope.organization_name = $scope.name;
|
$scope.organization_name = $scope.name;
|
||||||
main = params;
|
main = params;
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
export default ['templateUrl', '$window', function(templateUrl, $window) {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
galaxyCredentials: '='
|
||||||
|
},
|
||||||
|
templateUrl: templateUrl('organizations/galaxy-credentials-multiselect/galaxy-credentials-modal/galaxy-credentials-modal'),
|
||||||
|
|
||||||
|
link: function(scope, element) {
|
||||||
|
|
||||||
|
$('#galaxy-credentials-modal').on('hidden.bs.modal', function () {
|
||||||
|
$('#galaxy-credentials-modal').off('hidden.bs.modal');
|
||||||
|
$(element).remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
scope.showModal = function() {
|
||||||
|
$('#galaxy-credentials-modal').modal('show');
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.destroyModal = function() {
|
||||||
|
$('#galaxy-credentials-modal').modal('hide');
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
controller: ['$scope', '$compile', 'QuerySet', 'GetBasePath','generateList', 'CredentialList', function($scope, $compile, qs, GetBasePath, GenerateList, CredentialList) {
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
|
||||||
|
$scope.credential_queryset = {
|
||||||
|
order_by: 'name',
|
||||||
|
page_size: 5,
|
||||||
|
credential_type__kind: 'galaxy'
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.credential_default_params = {
|
||||||
|
order_by: 'name',
|
||||||
|
page_size: 5,
|
||||||
|
credential_type__kind: 'galaxy'
|
||||||
|
};
|
||||||
|
|
||||||
|
qs.search(GetBasePath('credentials'), $scope.credential_queryset)
|
||||||
|
.then(res => {
|
||||||
|
$scope.credential_dataset = res.data;
|
||||||
|
$scope.credentials = $scope.credential_dataset.results;
|
||||||
|
|
||||||
|
let credentialList = _.cloneDeep(CredentialList);
|
||||||
|
|
||||||
|
credentialList.listTitle = false;
|
||||||
|
credentialList.well = false;
|
||||||
|
credentialList.multiSelect = true;
|
||||||
|
credentialList.multiSelectPreview = {
|
||||||
|
selectedRows: 'igTags',
|
||||||
|
availableRows: 'credentials'
|
||||||
|
};
|
||||||
|
credentialList.fields.name.ngClick = "linkoutCredential(credential)";
|
||||||
|
credentialList.fields.name.columnClass = 'col-md-11 col-sm-11 col-xs-11';
|
||||||
|
delete credentialList.fields.consumed_capacity;
|
||||||
|
delete credentialList.fields.jobs_running;
|
||||||
|
|
||||||
|
let html = `${GenerateList.build({
|
||||||
|
list: credentialList,
|
||||||
|
input_type: 'galaxy-credentials-modal-body',
|
||||||
|
hideViewPerPage: true,
|
||||||
|
mode: 'lookup'
|
||||||
|
})}`;
|
||||||
|
|
||||||
|
$scope.list = credentialList;
|
||||||
|
$('#galaxy-credentials-modal-body').append($compile(html)($scope));
|
||||||
|
|
||||||
|
if ($scope.galaxyCredentials) {
|
||||||
|
$scope.galaxyCredentials = $scope.galaxyCredentials.map( (item) => {
|
||||||
|
item.isSelected = true;
|
||||||
|
if (!$scope.igTags) {
|
||||||
|
$scope.igTags = [];
|
||||||
|
}
|
||||||
|
$scope.igTags.push(item);
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.showModal();
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$watch('credentials', function(){
|
||||||
|
angular.forEach($scope.credentials, function(credentialRow) {
|
||||||
|
angular.forEach($scope.igTags, function(selectedCredential){
|
||||||
|
if(selectedCredential.id === credentialRow.id) {
|
||||||
|
credentialRow.isSelected = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
$scope.$on("selectedOrDeselected", function(e, value) {
|
||||||
|
let item = value.value;
|
||||||
|
if (value.isSelected) {
|
||||||
|
if(!$scope.igTags) {
|
||||||
|
$scope.igTags = [];
|
||||||
|
}
|
||||||
|
$scope.igTags.push(item);
|
||||||
|
} else {
|
||||||
|
_.remove($scope.igTags, { id: item.id });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.linkoutCredential = function(credential) {
|
||||||
|
$window.open('/#/credentials/' + credential.id,'_blank');
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.cancelForm = function() {
|
||||||
|
$scope.destroyModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.saveForm = function() {
|
||||||
|
$scope.galaxyCredentials = $scope.igTags;
|
||||||
|
$scope.destroyModal();
|
||||||
|
};
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}];
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<div id="galaxy-credentials-modal" class="Lookup modal fade">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header Form-header">
|
||||||
|
<div class="Form-title Form-title--uppercase" translate>Select Galaxy Credentials</div>
|
||||||
|
<div class="Form-header--fields"></div>
|
||||||
|
<div class="Form-exitHolder">
|
||||||
|
<button aria-label="{{'Close'|translate}}" type="button" class="Form-exit" ng-click="cancelForm()">
|
||||||
|
<i class="fa fa-times-circle"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div id="galaxy-credentials-modal-body"> {{ credential }} </div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" ng-click="cancelForm()" class="btn btn-default" translate>CANCEL</button>
|
||||||
|
<button type="button" ng-click="saveForm()" ng-disabled="!credentials || credentials.length === 0" class="Lookup-save btn btn-primary" translate>SAVE</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
export default ['$scope',
|
||||||
|
function($scope) {
|
||||||
|
|
||||||
|
$scope.galaxyCredentialsTags = [];
|
||||||
|
|
||||||
|
$scope.$watch('galaxyCredentials', function() {
|
||||||
|
$scope.galaxyCredentialsTags = $scope.galaxyCredentials;
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
$scope.deleteTag = function(tag){
|
||||||
|
_.remove($scope.galaxyCredentials, {id: tag.id});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#instance-groups-panel {
|
||||||
|
table {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.List-header {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.isActive {
|
||||||
|
border-left: 10px solid @list-row-select-bord;
|
||||||
|
}
|
||||||
|
.instances-list,
|
||||||
|
.instance-jobs-list {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import galaxyCredentialsMultiselectController from './galaxy-credentials-multiselect.controller';
|
||||||
|
export default ['templateUrl', '$compile',
|
||||||
|
function(templateUrl, $compile) {
|
||||||
|
return {
|
||||||
|
scope: {
|
||||||
|
galaxyCredentials: '=',
|
||||||
|
fieldIsDisabled: '='
|
||||||
|
},
|
||||||
|
restrict: 'E',
|
||||||
|
templateUrl: templateUrl('organizations/galaxy-credentials-multiselect/galaxy-credentials'),
|
||||||
|
controller: galaxyCredentialsMultiselectController,
|
||||||
|
link: function(scope) {
|
||||||
|
scope.openInstanceGroupsModal = function() {
|
||||||
|
$('#content-container').append($compile('<galaxy-credentials-modal galaxy-credentials="galaxyCredentials"></galaxy-credentials-modal>')(scope));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<div class="input-group Form-mixedInputGroup">
|
||||||
|
<span class="input-group-btn input-group-prepend Form-variableHeightButtonGroup">
|
||||||
|
<button aria-label="{{'Open Galaxy credentials'|translate}}" type="button" class="Form-lookupButton Form-lookupButton--variableHeight btn btn-default" ng-click="openInstanceGroupsModal()"
|
||||||
|
ng-disabled="fieldIsDisabled">
|
||||||
|
<i class="fa fa-search"></i>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
<span id="InstanceGroups" class="form-control Form-textInput Form-textInput--variableHeight input-medium lookup LabelList-lookupTags"
|
||||||
|
ng-disabled="fieldIsDisabled"
|
||||||
|
ng-class="{'LabelList-lookupTags--disabled' : fieldIsDisabled}">
|
||||||
|
<div ng-if="!fieldIsDisabled" class="LabelList-tagContainer" ng-repeat="tag in galaxyCredentialsTags">
|
||||||
|
<at-tag tag="tag.name" remove-tag="deleteTag(tag)"></at-tag>
|
||||||
|
</div>
|
||||||
|
<div ng-if="fieldIsDisabled" class="LabelList-tag" ng-repeat="tag in galaxyCredentialsTags">
|
||||||
|
<span class="LabelList-name">{{tag.name | sanitize}}</span>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
@@ -12,8 +12,10 @@ import organizationsLinkout from './linkout/main';
|
|||||||
import OrganizationsLinkoutStates from './linkout/organizations-linkout.route';
|
import OrganizationsLinkoutStates from './linkout/organizations-linkout.route';
|
||||||
import OrganizationForm from './organizations.form';
|
import OrganizationForm from './organizations.form';
|
||||||
import OrganizationList from './organizations.list';
|
import OrganizationList from './organizations.list';
|
||||||
import { N_ } from '../i18n';
|
import galaxyCredentialsMultiselect from './galaxy-credentials-multiselect/galaxy-credentials.directive';
|
||||||
|
import galaxyCredentialsModal from './galaxy-credentials-multiselect/galaxy-credentials-modal/galaxy-credentials-modal.directive';
|
||||||
|
|
||||||
|
import { N_ } from '../i18n';
|
||||||
|
|
||||||
export default
|
export default
|
||||||
angular.module('Organizations', [
|
angular.module('Organizations', [
|
||||||
@@ -24,6 +26,8 @@ angular.module('Organizations', [
|
|||||||
.controller('OrganizationsEdit', OrganizationsEdit)
|
.controller('OrganizationsEdit', OrganizationsEdit)
|
||||||
.factory('OrganizationForm', OrganizationForm)
|
.factory('OrganizationForm', OrganizationForm)
|
||||||
.factory('OrganizationList', OrganizationList)
|
.factory('OrganizationList', OrganizationList)
|
||||||
|
.directive('galaxyCredentialsMultiselect', galaxyCredentialsMultiselect)
|
||||||
|
.directive('galaxyCredentialsModal', galaxyCredentialsModal)
|
||||||
.config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider',
|
.config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider',
|
||||||
function($stateProvider, stateDefinitionsProvider, $stateExtenderProvider) {
|
function($stateProvider, stateDefinitionsProvider, $stateExtenderProvider) {
|
||||||
let stateExtender = $stateExtenderProvider.$get(),
|
let stateExtender = $stateExtenderProvider.$get(),
|
||||||
@@ -81,6 +85,24 @@ angular.module('Organizations', [
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}],
|
}],
|
||||||
|
GalaxyCredentialsData: ['$stateParams', 'Rest', 'GetBasePath', 'ProcessErrors',
|
||||||
|
function($stateParams, Rest, GetBasePath, ProcessErrors){
|
||||||
|
let path = `${GetBasePath('organizations')}${$stateParams.organization_id}/galaxy_credentials/`;
|
||||||
|
Rest.setUrl(path);
|
||||||
|
return Rest.get()
|
||||||
|
.then(({data}) => {
|
||||||
|
if (data.results.length > 0) {
|
||||||
|
return data.results;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(({data, status}) => {
|
||||||
|
ProcessErrors(null, data, status, null, {
|
||||||
|
hdr: 'Error!',
|
||||||
|
msg: 'Failed to get credentials. GET returned ' +
|
||||||
|
'status: ' + status
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}],
|
||||||
InstanceGroupsData: ['$stateParams', 'Rest', 'GetBasePath', 'ProcessErrors',
|
InstanceGroupsData: ['$stateParams', 'Rest', 'GetBasePath', 'ProcessErrors',
|
||||||
function($stateParams, Rest, GetBasePath, ProcessErrors){
|
function($stateParams, Rest, GetBasePath, ProcessErrors){
|
||||||
let path = `${GetBasePath('organizations')}${$stateParams.organization_id}/instance_groups/`;
|
let path = `${GetBasePath('organizations')}${$stateParams.organization_id}/instance_groups/`;
|
||||||
|
|||||||
@@ -55,6 +55,15 @@ export default ['NotificationsList', 'i18n',
|
|||||||
ngDisabled: '!(organization_obj.summary_fields.user_capabilities.edit || canAdd)',
|
ngDisabled: '!(organization_obj.summary_fields.user_capabilities.edit || canAdd)',
|
||||||
ngShow: 'custom_virtualenvs_visible'
|
ngShow: 'custom_virtualenvs_visible'
|
||||||
},
|
},
|
||||||
|
credential: {
|
||||||
|
label: i18n._('Galaxy Credentials'),
|
||||||
|
type: 'custom',
|
||||||
|
awPopOver: "<p>" + i18n._("Select Galaxy credentials. The selection order sets precedence for the sync and lookup of the content") + "</p>",
|
||||||
|
dataTitle: i18n._('Galaxy Credentials'),
|
||||||
|
dataContainer: 'body',
|
||||||
|
dataPlacement: 'right',
|
||||||
|
control: '<galaxy-credentials-multiselect galaxy-credentials="credentials" field-is-disabled="!(organization_obj.summary_fields.user_capabilities.edit || canAdd) || (!current_user.is_superuser && isOrgAdmin)"></galaxy-credentials-multiselect>',
|
||||||
|
},
|
||||||
max_hosts: {
|
max_hosts: {
|
||||||
label: i18n._('Max Hosts'),
|
label: i18n._('Max Hosts'),
|
||||||
type: 'number',
|
type: 'number',
|
||||||
@@ -69,7 +78,7 @@ export default ['NotificationsList', 'i18n',
|
|||||||
awPopOver: "<p>" + i18n._("The maximum number of hosts allowed to be managed by this organization. Value defaults to 0 which means no limit. Refer to the Ansible documentation for more details.") + "</p>",
|
awPopOver: "<p>" + i18n._("The maximum number of hosts allowed to be managed by this organization. Value defaults to 0 which means no limit. Refer to the Ansible documentation for more details.") + "</p>",
|
||||||
ngDisabled: '!current_user.is_superuser',
|
ngDisabled: '!current_user.is_superuser',
|
||||||
ngShow: 'BRAND_NAME === "Tower"'
|
ngShow: 'BRAND_NAME === "Tower"'
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
buttons: { //for now always generates <button> tags
|
buttons: { //for now always generates <button> tags
|
||||||
|
|||||||
@@ -46,6 +46,52 @@ function MultiCredentialService (Rest, ProcessErrors, $q, GetBasePath) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.saveRelatedSequentially = ({ related }, credentials) => {
|
||||||
|
Rest.setUrl(related.credentials);
|
||||||
|
return Rest
|
||||||
|
.get()
|
||||||
|
.then(res => {
|
||||||
|
const { data: { results = [] } } = res;
|
||||||
|
const updatedCredentialIds = (credentials || []).map(({ id }) => id);
|
||||||
|
const currentCredentialIds = results.map(({ id }) => id);
|
||||||
|
const credentialIdsToAssociate = [];
|
||||||
|
const credentialIdsToDisassociate = [];
|
||||||
|
let disassociateRemainingIds = false;
|
||||||
|
|
||||||
|
currentCredentialIds.forEach((currentId, position) => {
|
||||||
|
if (!disassociateRemainingIds && updatedCredentialIds[position] !== currentId) {
|
||||||
|
disassociateRemainingIds = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disassociateRemainingIds) {
|
||||||
|
credentialIdsToDisassociate.push(currentId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
updatedCredentialIds.forEach(updatedId => {
|
||||||
|
if (credentialIdsToDisassociate.includes(updatedId)) {
|
||||||
|
credentialIdsToAssociate.push(updatedId);
|
||||||
|
} else if (!currentCredentialIds.includes(updatedId)) {
|
||||||
|
credentialIdsToAssociate.push(updatedId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let disassociationPromise = Promise.resolve();
|
||||||
|
credentialIdsToDisassociate.forEach(id => {
|
||||||
|
disassociationPromise = disassociationPromise.then(() => disassociate({ related }, id));
|
||||||
|
});
|
||||||
|
|
||||||
|
return disassociationPromise
|
||||||
|
.then(() => {
|
||||||
|
let associationPromise = Promise.resolve();
|
||||||
|
credentialIdsToAssociate.forEach(id => {
|
||||||
|
associationPromise = associationPromise.then(() => associate({ related }, id));
|
||||||
|
});
|
||||||
|
return associationPromise;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
this.getRelated = ({ related }, params = { permitted: [] }) => {
|
this.getRelated = ({ related }, params = { permitted: [] }) => {
|
||||||
Rest.setUrl(related.credentials);
|
Rest.setUrl(related.credentials);
|
||||||
return Rest
|
return Rest
|
||||||
|
|||||||
Reference in New Issue
Block a user