Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Large UI/UX improvements:

* User search when adding to namespace, with a drop down activating once user input field text length is >= 4 characters
* Search retrieves users whose name contains search characters, shows and adds to drop-down
* If no option selected or none available, username interpreted as is (can still be added as non-existing / technical user then)

Signed-off-by: Menahem Julien Raccah Lisei <[email protected]>
  • Loading branch information
menajrl committed Dec 23, 2019
1 parent d5c8291 commit 0b8a898
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,14 @@ public interface IUserAccountService {
* @return users who are system administrators
*/
Collection<User> getSystemAdministrators();


/**
* Finds a list of users matching the given partial username.
* @param partial
* @return
*/
Collection<User> findUsers(String partial);

/**
*
* @param tenantId the tenant from which to remove the user
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,11 @@ public User getUser(String username) {
return this.userRepository.findByUsername(username);
}

@Override
public Collection<User> findUsers(String partial) {
return this.userRepository.findUserByPartial(partial);
}

@Override
public void saveUser(User user) {
this.userRepository.save(user);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,15 @@ public interface IUserRepository extends CrudRepository<User, Long> {
* @return
*/
User findByUsername(String username);


/**
* Finds a list of users matching the given partial username.
* @param partial
* @return
*/
@Query("SELECT u from User u WHERE u.username LIKE %?1%")
Collection<User> findUserByPartial(String partial);

@Query("SELECT u from User u, TenantUser tu, UserRole r " +
"WHERE u.id = tu.user.id AND " +
"tu.id = r.user.id AND " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,20 @@ public ResponseEntity<UserDto> getUser(
}
}

@RequestMapping(method = RequestMethod.GET, value = "/rest/accounts/search/{partial:.+}")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<Collection<UserDto>> findUsers(
@ApiParam(value = "Username", required = true) @PathVariable String partial) {

Collection<User> users = accountService.findUsers(ControllerUtils.sanitize(partial));
if (users != null) {
return new ResponseEntity<>(users.stream().map(UserDto::fromUser).collect(Collectors.toList()), HttpStatus.OK);
} else {
// TODO return something to prompt front-end to request creating technical user with given authentication provider ID
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}

@RequestMapping(method = RequestMethod.POST, consumes = "application/json",
value = "/rest/accounts")
@PreAuthorize("hasRole('ROLE_SYS_ADMIN') or #user.name == authentication.name")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*/
package org.eclipse.vorto.repository.web.account.dto;

import org.eclipse.vorto.repository.domain.User;

/**
* Represents a payload for requests to perform both:
* <ul>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,41 @@ repositoryControllers.controller("createOrUpdateUserController",
$scope.isCurrentlyAddingOrUpdating = false;
$scope.errorMessage = "";
$scope.selectedAuthenticationProviderId = null;
$scope.userPartial = "";
$scope.selectedUser = null;
$scope.retrievedUsers = [];

$scope.selectUser = function() {
document.getElementById('userId').value = $scope.selectedUser.username;
}

$scope.findUsers = function() {
// only initiates user search if partial name is larger >= 4 characters
// this is to prevent unmanageably large drop-downs
if ($scope.userPartial && $scope.userPartial.length >= 4) {
//document.getElementById("userSearchSelect").style.visibility = 'visible';
$http.get("./rest/accounts/search/" + $scope.userPartial)
.then(function (result) {
console.log(result);
if (result.data) {
$scope.retrievedUsers = result.data;
if ($scope.retrievedUsers.length == 1) {
$scope.selectedUser = $scope.retrievedUsers[0];
$scope.selectUser();
}
} else {
$scope.retrievedUsers = [];
$scope.selectedUser = null;
}
});
}
else {
$scope.retrievedUsers = [];
$scope.selectedUser = null;
}
};

//$scope.findUsers();

$scope.cancel = function() {
$uibModalInstance.dismiss("Canceled.");
Expand Down Expand Up @@ -153,6 +188,14 @@ repositoryControllers.controller("createOrUpdateUserController",
};

$scope.addOrUpdateUser = function() {
// adds username to scope user by either using selected user from
// drop-down if any, or using the string in user's input box
if ($scope.selectedUser) {
$scope.user.username = $scope.selectedUser.username;
}
else {
$scope.user.username = $scope.userPartial;
}
$scope.validate($scope.user, function(result) {
if (result.valid) {
$scope.isCurrentlyAddingOrUpdating = false;
Expand Down
107 changes: 66 additions & 41 deletions repository/repository-web/dist/partials/admin/createOrUpdateUser.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
<form class="form-horizontal" name="tenantForm">
<style>
.ng-hide:not(.ng-hide-animate) {
display:block;
visibility: hidden;
}
</style>
<div class="modal-header">
<button ng-disabled="isCurrentlyAddingOrUpdating" type="button" class="close" ng-click="cancel()">&times;</button>
<h4 class="modal-title">{{ mode }} User <a class="help-icon"
Expand All @@ -11,74 +17,93 @@ <h4 class="modal-title">{{ mode }} User <a class="help-icon"
<div class="row" ng-show="errorMessage !== ''">
<div class="alert alert-danger" role="alert">{{ errorMessage }}</div>
</div>

<div class="form-group">
<label for="userId" class="col-sm-2 control-label">User ID</label>
<div class="col-sm-10">
<input autofocus type="text" class="form-control" id="userId" placeholder="userId" ng-model="user.username" ng-readonly="user.edit">
</div>
</div>


<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="user.roleUser"> VIEW <small>permission to browse models</small>
</label>
</div>
</div>
<div class="row">
<label for="userId" class="col-sm-2 control-label">User ID</label>
<div class="col-sm-10">
<input autofocus type="search" class="search-box-query-filter form-control search-input"
id="userId" placeholder="userId" ng-model="userPartial" ng-readonly="user.edit"
ng-model-options="{ debounce: 1000 }" ng-change="findUsers()">
</div>
</div>

<div class="row" ng-show="retrievedUsers.length > 0">
<div class="col-sm-offset-2 col-sm-10">
<select class="form-control" id="userSearchSelect"
ng-options="user as user.username for user in retrievedUsers track by user.username"
ng-model="selectedUser"
ng-value="retrievedUsers[0].username"
ng-show="retrievedUsers.length > 0"
ng-change="selectUser()"
>
</select>

</div>
</div>
</div>

<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="user.roleModelCreator"> CREATE <small>permission to create and modify models</small>
</label>
</div>
</div>

<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="user.roleUser"> VIEW <small>permission to browse models</small>
</label>
</div>
</div>
</div>

<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="user.roleModelCreator"> CREATE <small>permission to create and modify models</small>
</label>
</div>
</div>
</div>

<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="user.roleModelPromoter"> PROMOTE <small>permission to release models</small>
</label>
</div>
</div>
</label>
</div>
</div>
</div>

<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="user.roleModelReviewer"> REVIEW <small>permission to review and approve models</small>
</label>
</div>
</div>
</label>
</div>
</div>
</div>

<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="user.roleModelPublisher"> PUBLISH <small>permission to change the visibility of models</small>
</label>
</div>
</div>
</label>
</div>
</div>
</div>

<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="user.roleAdmin"> MANAGE <small>permission to manage namespaces</small>
</label>
</div>
</div>
</label>
</div>
</div>
</div>
</div>
</div>

<div class="modal-footer">
<div class="form-group">
<div class="col-sm-12">
Expand Down

0 comments on commit 0b8a898

Please sign in to comment.