Merge pull request #1911 from jlmitch5/addUsersOrg

modal to add users and admins to organizations
This commit is contained in:
jlmitch5 2016-05-16 14:21:06 -04:00
commit 3bb407b39c
10 changed files with 434 additions and 7 deletions

View File

@ -737,6 +737,7 @@ var tower = angular.module('Tower', [
CheckLicense.notify();
}
$rootScope.$broadcast("closePermissionsModal");
$rootScope.$broadcast("closeUsersModal");
// this line removes the query params attached to a route
if(prev && prev.$$route &&
prev.$$route.name === 'systemTracking'){

View File

@ -0,0 +1,218 @@
@import "../../../shared/branding/colors.default.less";
/** @define AddUsers */
.AddUsers-backDrop {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: 1041;
opacity: 0.2;
transition: 0.5s opacity;
background: @login-backdrop;
}
.AddUsers-dialog {
margin: 30px auto;
margin-top: 95px;
}
.AddUsers-content {
max-width: 750px;
margin: 0 auto;
border: 0;
box-shadow: none;
background-color: @login-bg;
border-radius: 4px;
transition: opacity 0.5s;
z-index: 1042;
position: relative;
opacity: 1;
}
.AddUsers-header {
padding: 20px;
padding-bottom: 10px;
padding-top: 15px;
}
.AddUsers-body {
padding: 0px 20px;
}
.AddUsers-footer {
display: flex;
flex-wrap: wrap-reverse;
align-items: center;
padding: 20px;
padding-bottom: 0px;
padding-top: 20px;
}
.AddUsers-list .List-searchRow {
height: 0px;
}
.AddUsers-list .List-searchWidget {
height: 66px;
}
.AddUsers-list .List-tableHeader:last-child {
border-top-right-radius: 5px;
}
.AddUsers-list select-all {
display: none;
}
.AddUsers-title {
margin-top: 5px;
margin-bottom: 20px;
}
.AddUsers-buttons {
margin-left: auto;
margin-bottom: 20px;
}
.AddUsers-directions {
margin-top: 10px;
margin-bottom: 20px;
color: @default-interface-txt;
display: flex;
align-items: center;
}
.AddUsers-directionNumber {
font-size: 14px;
font-weight: bold;
border-radius: 50%;
background-color: @default-list-header-bg;
padding: 1px 8px;
margin-right: 10px;
width: 23px;
height: 23px;
}
.AddUsers-separator {
margin-top: 20px 0px;
width: 100%;
border-bottom: 1px solid @d7grey;
}
.AddUsers-roleRow {
display: flex;
margin-bottom: 10px;
align-items: center;
}
.AddUsers-roleName {
width: 30%;
padding-right: 10px;
display: flex;
align-items: center;
}
.AddUsers-roleNameVal {
font-size: 14px;
max-width: ~"calc(100% - 46px)";
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.AddUsers-roleType {
padding: 0px 6px;
font-size: 10px;
color: @default-interface-txt;
text-transform: uppercase;
background-color: @default-bg;
margin-left: 6px;
}
.AddUsers-roleSelect {
width: ~"calc(70% - 40px)";
margin-right: 20px;
}
.AddUsers-roleSelect .Form-dropDown {
height: inherit !important;
}
.AddUsers-roleRemove {
border-radius: 50%;
padding: 1px 0;
line-height: 11px;
color: @default-icon;
background-color: @default-tertiary-bg;
border: 0;
height: 23px;
width: 23px;
}
.AddUsers-roleRemove:hover {
background-color: @default-err;
color: @default-bg;
}
.AddUsers-selectHide {
display: none;
}
.AddUsers .select2-search__field {
text-transform: uppercase;
}
.AddUsers-keyToggle {
margin-left: auto;
text-transform: uppercase;
padding: 3px 9px;
font-size: 12px;
background-color: @default-bg;
border-radius: 5px;
color: @default-interface-txt;
border: 1px solid @d7grey;
cursor: pointer;
}
.AddUsers-keyToggle:hover {
background-color: @default-tertiary-bg;
}
.AddUsers-keyToggle.is-active {
background-color: @default-link;
border-color: @default-link;
color: @default-bg;
}
.AddUsers-keyPane {
margin: 20px 0;
font-size: 12px;
width: 100%;
padding: 15px;
padding-top: 10px;
margin-bottom: 15px;
border-radius: 4px;
border: 1px solid @login-notice-border;
background-color: @login-notice-bg;
color: @login-notice-text;
}
.AddUsers-keyRow {
display: flex;
flex-direction: column;
margin-bottom: 15px;
}
.AddUsers-keyName {
flex: 1 0 auto;
text-transform: uppercase;
font-weight: bold;
padding-bottom: 3px;
}
.AddUsers-keyDescription {
flex: 1 0 auto;
}

View File

@ -0,0 +1,82 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
/**
* @ngdoc function
* @name controllers.function:Access
* @description
* Controller for handling permissions adding
*/
export default ['$scope', '$rootScope', 'ProcessErrors', 'UserList', 'generateList', 'GetBasePath', 'SelectionInit', 'SearchInit', 'templateUrl', 'PaginateInit', '$state', 'Rest', '$q', 'Wait', function($scope, $rootScope, ProcessErrors, UserList, generateList, GetBasePath, SelectionInit, SearchInit, templateUrl, PaginateInit, $state, Rest, $q, Wait) {
$scope.$on("linkLists", function() {
var generator = generateList,
list = _.cloneDeep(UserList),
url = GetBasePath("users"),
set = "users",
id = "addUsersList",
mode = "add";
if ($state.current.name.split(".")[1] === "users") {
$scope.addType = "Users";
} else {
$scope.addType = "Administrators";
}
list.multiSelect = true;
generator.inject(list, { id: id,
title: false, mode: mode, scope: $scope });
SearchInit({ scope: $scope, set: set,
list: list, url: url });
PaginateInit({ scope: $scope,
list: list, url: url, pageSize: 5 });
$scope.search(list.iterator);
$scope.updateUsers = function() {
var url, listToClose,
payloads = $scope.selectedItems.map(function(val) {
return {id: val.id};
});
if ($scope.addType === 'Users') {
url = $scope.$parent.orgRelatedUrls.users;
listToClose = 'user';
} else {
url = $scope.$parent.orgRelatedUrls.admins;
listToClose = 'admin';
}
Wait('start');
var requests = payloads
.map(function(post) {
Rest.setUrl(url);
return Rest.post(post);
});
$q.all(requests)
.then(function () {
Wait('stop');
$scope.$emit('ReloadOrganzationCards', $scope.$parent.org_id);
$scope.$parent.search('user');
$scope.closeModal();
}, function (error) {
Wait('stop');
$rootScope.$broadcast("refreshList", listToClose);
ProcessErrors(null, error.data, error.status, null, {
hdr: 'Error!',
msg: 'Failed to post ' + $scope.addType +
': POST returned status' + error.status
});
});
};
});
}];

View File

@ -0,0 +1,54 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
/* jshint unused: vars */
import addUsers from './addUsers.controller';
export default
['Wait', 'templateUrl', function(Wait, templateUrl) {
return {
restrict: 'E',
scope: {},
controller: addUsers,
templateUrl: templateUrl('organizations/linkout/addUsers/addUsers'),
link: function(scope, element, attrs, ctrl) {
$("body").addClass("is-modalOpen");
$("body").append(element);
Wait('start');
scope.$broadcast("linkLists");
setTimeout(function() {
$('#add-users-modal').modal("show");
}, 200);
$('.modal[aria-hidden=false]').each(function () {
if ($(this).attr('id') !== 'add-users-modal') {
$(this).modal('hide');
}
});
scope.closeModal = function() {
$("body").removeClass("is-modalOpen");
$('#add-users-modal').on('hidden.bs.modal',
function () {
$('.AddUsers').remove();
});
$('#add-users-modal').modal('hide');
};
scope.$on('closeUsersModal', function() {
scope.closeModal();
});
Wait('stop');
window.scrollTo(0,0);
}
};
}
];

View File

@ -0,0 +1,39 @@
<div id="add-users-modal" class="AddUsers modal fade">
<div class="AddUsers-backDrop is-loggedOut"></div>
<div class="AddUsers-dialog">
<div class="AddUsers-content is-loggedOut">
<div class="AddUsers-header">
<div class="List-header">
<div class="List-title">
<div class="List-titleText ng-binding">{{ $parent.org_name }}<div class="List-titleLockup"></div>Add {{ addType }}
</div>
</div>
<div class="Form-exitHolder">
<button class="Form-exit" ng-click="closeModal()">
<i class="fa fa-times-circle"></i>
</button>
</div>
</div>
</div>
<div class="AddUsers-body">
<div class="AddUsers-inner" id="addUsersList">
</div>
</div>
<div class="AddUsers-footer">
<div class="buttons Form-buttons AddUsers-buttons">
<button type="button"
class="btn btn-sm Form-saveButton"
ng-click="updateUsers()"
ng-disabled="!selectedItems || !selectedItems.length">
Save
</button>
<button type="button"
class="btn btn-sm Form-cancelButton"
ng-click="closeModal()">
Cancel
</button>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,11 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import addUsersDirective from './addUsers.directive';
export default
angular.module('AddUsers', [])
.directive('addUsers', addUsersDirective);

View File

@ -1,6 +1,7 @@
import routes from './organizations-linkout.route';
import AddUsers from './addUsers/main';
export default angular.module('organizationsLinkout', [])
export default angular.module('organizationsLinkout', [AddUsers.name])
.run(['$stateExtender', function($stateExtender) {
routes.forEach(function(route) {
$stateExtender.addState(route);

View File

@ -1,11 +1,14 @@
export default ['$scope', '$stateParams', '$state', 'Rest', 'UserList', 'InventoryList', 'JobTemplateList', 'TeamList', 'ProjectList', 'generateList', 'SearchInit', 'PaginateInit', function($scope, $stateParams, $state, Rest, UserList, InventoryList, JobTemplateList, TeamList, ProjectList, GenerateList, SearchInit, PaginateInit) {
export default ['$compile', '$scope', '$stateParams', '$state', 'Rest', 'UserList', 'InventoryList', 'JobTemplateList', 'TeamList', 'ProjectList', 'generateList', 'SearchInit', 'PaginateInit', function($compile, $scope, $stateParams, $state, Rest, UserList, InventoryList, JobTemplateList, TeamList, ProjectList, GenerateList, SearchInit, PaginateInit) {
var getList = function(mode) {
var list = {};
if (mode === 'users') {
list = _.cloneDeep(UserList);
list.emptyListText = "Please add items to this list";
list.actions.add.label = "Add a user to the organization";
list.actions.add.buttonContent = '&#43; ADD user';
list.actions.add.awToolTip = 'Add existing user to organization';
list.actions.add.ngClick = 'addUsers()';
} else if (mode === 'inventories') {
list = _.cloneDeep(InventoryList);
list.emptyListText = "List is empty";
@ -26,6 +29,8 @@ export default ['$scope', '$stateParams', '$state', 'Rest', 'UserList', 'Invento
list = _.cloneDeep(UserList);
list.emptyListText = "Please add items to this list";
list.actions.add.buttonContent = '&#43; ADD administrator';
list.actions.add.awToolTip = 'Add existing user to organization as administrator';
list.actions.add.ngClick = 'addUsers()';
}
return list;
};
@ -61,18 +66,27 @@ export default ['$scope', '$stateParams', '$state', 'Rest', 'UserList', 'Invento
generator = GenerateList;
$scope.$parent.activeCard = parseInt($stateParams.organization_id);
$scope.$parent.activeMode = mode;
$scope.org_name = data.name;
$scope.org_id = data.id;
var listMode = (mode === 'admins') ? 'users' : mode;
list = getList(mode);
list.listTitle = listTitle;
url = getUrl(mode, data);
list.listTitle = listTitle;
list.basePath = url;
$scope.orgRelatedUrls = data.related;
generator
.inject(list, { mode: 'edit', scope: $scope });
$scope.addUsers = function () {
$compile("<add-users class='AddUsers'></add-users>")($scope);
};
SearchInit({
scope: $scope,
set: mode,
set: listMode,
list: list,
url: url
});

View File

@ -31,7 +31,11 @@ export default ['GetBasePath', function(GetBasePath) {
if (endPoint === 'inventories') {
endPoint = 'inventory';
}
return GetBasePath(endPoint);
if (endPoint.indexOf("/api/v1") > -1) {
return endPoint;
} else {
return GetBasePath(endPoint);
}
};
// inject the directive with the list and endpoint

View File

@ -162,7 +162,10 @@ export default ['Rest', '$q', 'GetBasePath', 'Wait', 'ProcessErrors', '$log', fu
tags = relatedTags.concat(nonRelatedTags);
}
return basePath + "?" +
var returnedUrl = basePath;
returnedUrl += (basePath.indexOf("?") > - 1) ? "&" : "?";
return returnedUrl +
(tags || []).map(function (t) {
return t.url;
}).join("&") + "&page_size=" + pageSize;