root/resilient#2 Change the User selection control to a 'on type' combo.
Also restricted the user list to only users that have NO association to org yet
This commit is contained in:
parent
4890950952
commit
2aa75f0e13
8 changed files with 174 additions and 82 deletions
|
@ -9,6 +9,7 @@ import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.jpa.repository.EntityGraph;
|
import org.springframework.data.jpa.repository.EntityGraph;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import com.oguerreiro.resilient.domain.User;
|
import com.oguerreiro.resilient.domain.User;
|
||||||
|
@ -43,4 +44,13 @@ public interface UserRepository extends JpaRepository<User, Long> {
|
||||||
Optional<User> findOneWithAuthoritiesByEmailIgnoreCase(String email);
|
Optional<User> findOneWithAuthoritiesByEmailIgnoreCase(String email);
|
||||||
|
|
||||||
Page<User> findAllByIdNotNullAndActivatedIsTrue(Pageable pageable);
|
Page<User> findAllByIdNotNullAndActivatedIsTrue(Pageable pageable);
|
||||||
|
|
||||||
|
@Query("""
|
||||||
|
SELECT u
|
||||||
|
FROM User u
|
||||||
|
WHERE u.id IS NOT NULL
|
||||||
|
AND u.activated = TRUE
|
||||||
|
AND u.id NOT IN (SELECT o.user.id FROM Organization o WHERE o.user IS NOT NULL)
|
||||||
|
""")
|
||||||
|
Page<User> findActiveUsersNotInOrganization(Pageable pageable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,6 +274,11 @@ public class UserService {
|
||||||
return userRepository.findAllByIdNotNullAndActivatedIsTrue(pageable).map(UserDTO::new);
|
return userRepository.findAllByIdNotNullAndActivatedIsTrue(pageable).map(UserDTO::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public Page<UserDTO> getAllPublicUsersForOrganization(Pageable pageable) {
|
||||||
|
return userRepository.findActiveUsersNotInOrganization(pageable).map(UserDTO::new);
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public Optional<User> getUserWithAuthoritiesByLogin(String login) {
|
public Optional<User> getUserWithAuthoritiesByLogin(String login) {
|
||||||
return userRepository.findOneWithAuthoritiesByLogin(login);
|
return userRepository.findOneWithAuthoritiesByLogin(login);
|
||||||
|
|
|
@ -1,69 +1,83 @@
|
||||||
package com.oguerreiro.resilient.service.dto;
|
package com.oguerreiro.resilient.service.dto;
|
||||||
|
|
||||||
import com.oguerreiro.resilient.domain.User;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import com.oguerreiro.resilient.domain.User;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A DTO representing a user, with only the public attributes.
|
* A DTO representing a user, with only the public attributes.
|
||||||
*/
|
*/
|
||||||
public class UserDTO implements Serializable {
|
public class UserDTO implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
private String login;
|
private String login;
|
||||||
|
|
||||||
public UserDTO() {
|
private String email;
|
||||||
// Empty constructor needed for Jackson.
|
|
||||||
|
public UserDTO() {
|
||||||
|
// Empty constructor needed for Jackson.
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserDTO(User user) {
|
||||||
|
this.id = user.getId();
|
||||||
|
this.login = user.getLogin();
|
||||||
|
this.email = user.getEmail();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLogin() {
|
||||||
|
return login;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogin(String login) {
|
||||||
|
this.login = login;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserDTO(User user) {
|
UserDTO userDTO = (UserDTO) o;
|
||||||
this.id = user.getId();
|
if (userDTO.getId() == null || getId() == null) {
|
||||||
// Customize it here if you need, or not, firstName/lastName/etc
|
return false;
|
||||||
this.login = user.getLogin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getId() {
|
return Objects.equals(getId(), userDTO.getId()) && Objects.equals(getLogin(), userDTO.getLogin());
|
||||||
return id;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Long id) {
|
// prettier-ignore
|
||||||
this.id = id;
|
@Override
|
||||||
}
|
public String toString() {
|
||||||
|
//@formatter:off
|
||||||
public String getLogin() {
|
return "UserDTO{"
|
||||||
return login;
|
+ "id='" + id + '\''
|
||||||
}
|
+ ", login='" + login + '\''
|
||||||
|
+ ", email='" + email + '\''
|
||||||
public void setLogin(String login) {
|
+ "}";
|
||||||
this.login = login;
|
//@formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (o == null || getClass() != o.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UserDTO userDTO = (UserDTO) o;
|
|
||||||
if (userDTO.getId() == null || getId() == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Objects.equals(getId(), userDTO.getId()) && Objects.equals(getLogin(), userDTO.getLogin());
|
|
||||||
}
|
|
||||||
|
|
||||||
// prettier-ignore
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "UserDTO{" +
|
|
||||||
"id='" + id + '\'' +
|
|
||||||
", login='" + login + '\'' +
|
|
||||||
"}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package com.oguerreiro.resilient.web.rest;
|
package com.oguerreiro.resilient.web.rest;
|
||||||
|
|
||||||
import com.oguerreiro.resilient.service.UserService;
|
import java.util.Arrays;
|
||||||
import com.oguerreiro.resilient.service.dto.UserDTO;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
|
@ -12,45 +12,72 @@ import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||||
|
|
||||||
|
import com.oguerreiro.resilient.service.UserService;
|
||||||
|
import com.oguerreiro.resilient.service.dto.UserDTO;
|
||||||
|
|
||||||
import tech.jhipster.web.util.PaginationUtil;
|
import tech.jhipster.web.util.PaginationUtil;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api")
|
@RequestMapping("/api")
|
||||||
public class PublicUserResource {
|
public class PublicUserResource {
|
||||||
|
|
||||||
private static final List<String> ALLOWED_ORDERED_PROPERTIES = Collections.unmodifiableList(
|
private static final List<String> ALLOWED_ORDERED_PROPERTIES = Collections.unmodifiableList(
|
||||||
Arrays.asList("id", "login", "firstName", "lastName", "email", "activated", "langKey")
|
Arrays.asList("id", "login", "firstName", "lastName", "email", "activated", "langKey"));
|
||||||
);
|
|
||||||
|
|
||||||
private final Logger log = LoggerFactory.getLogger(PublicUserResource.class);
|
private final Logger log = LoggerFactory.getLogger(PublicUserResource.class);
|
||||||
|
|
||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
|
|
||||||
public PublicUserResource(UserService userService) {
|
public PublicUserResource(UserService userService) {
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code GET /users} : get all users with only public information - calling this method is allowed for anyone.
|
||||||
|
*
|
||||||
|
* @param pageable the pagination information.
|
||||||
|
* @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body all users.
|
||||||
|
*/
|
||||||
|
@GetMapping("/users")
|
||||||
|
public ResponseEntity<List<UserDTO>> getAllPublicUsers(
|
||||||
|
@org.springdoc.core.annotations.ParameterObject Pageable pageable) {
|
||||||
|
log.debug("REST request to get all public User names");
|
||||||
|
if (!onlyContainsAllowedProperties(pageable)) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
final Page<UserDTO> page = userService.getAllPublicUsers(pageable);
|
||||||
* {@code GET /users} : get all users with only public information - calling this method is allowed for anyone.
|
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(),
|
||||||
*
|
page);
|
||||||
* @param pageable the pagination information.
|
return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
|
||||||
* @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body all users.
|
}
|
||||||
*/
|
|
||||||
@GetMapping("/users")
|
|
||||||
public ResponseEntity<List<UserDTO>> getAllPublicUsers(@org.springdoc.core.annotations.ParameterObject Pageable pageable) {
|
|
||||||
log.debug("REST request to get all public User names");
|
|
||||||
if (!onlyContainsAllowedProperties(pageable)) {
|
|
||||||
return ResponseEntity.badRequest().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
final Page<UserDTO> page = userService.getAllPublicUsers(pageable);
|
/**
|
||||||
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page);
|
* {@code GET /users} : get all users with only public information - calling this method is allowed for anyone.
|
||||||
return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
|
*
|
||||||
|
* @param pageable the pagination information.
|
||||||
|
* @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body all users.
|
||||||
|
*/
|
||||||
|
@GetMapping("/users/for/organization")
|
||||||
|
public ResponseEntity<List<UserDTO>> getAllPublicUsersForOrganization(
|
||||||
|
@org.springdoc.core.annotations.ParameterObject Pageable pageable) {
|
||||||
|
log.debug("REST request to get all public User names, restricted to users not yet associated in the organization");
|
||||||
|
if (!onlyContainsAllowedProperties(pageable)) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean onlyContainsAllowedProperties(Pageable pageable) {
|
final Page<UserDTO> page = userService.getAllPublicUsersForOrganization(pageable);
|
||||||
return pageable.getSort().stream().map(Sort.Order::getProperty).allMatch(ALLOWED_ORDERED_PROPERTIES::contains);
|
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(),
|
||||||
}
|
page);
|
||||||
|
return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean onlyContainsAllowedProperties(Pageable pageable) {
|
||||||
|
return pageable.getSort().stream().map(Sort.Order::getProperty).allMatch(ALLOWED_ORDERED_PROPERTIES::contains);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,12 +186,36 @@
|
||||||
<!-- User property applies only to OrganizationNature.PERSON -->
|
<!-- User property applies only to OrganizationNature.PERSON -->
|
||||||
<div class="mb-3" *ngIf="editForm.get('organizationType')?.value?.nature === organizationNature.PERSON">
|
<div class="mb-3" *ngIf="editForm.get('organizationType')?.value?.nature === organizationNature.PERSON">
|
||||||
<label class="form-label" for="field_user" jhiTranslate="resilientApp.organization.user">User</label>
|
<label class="form-label" for="field_user" jhiTranslate="resilientApp.organization.user">User</label>
|
||||||
<select class="form-control" id="field_user" data-cy="user" name="user" formControlName="user" [compareWith]="compareUser">
|
<!--
|
||||||
|
<select
|
||||||
|
class="form-control"
|
||||||
|
id="field_user"
|
||||||
|
data-cy="user"
|
||||||
|
name="user"
|
||||||
|
formControlName="user"
|
||||||
|
[compareWith]="compareUser">
|
||||||
<option [ngValue]="null"></option>
|
<option [ngValue]="null"></option>
|
||||||
@for (userOption of usersSharedCollection; track $index) {
|
@for (userOption of usersSharedCollection; track $index) {
|
||||||
<option [ngValue]="userOption">{{ userOption.login }}</option>
|
<option [ngValue]="userOption">{{ userOption.login }}</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ng-select
|
||||||
|
class="form-control drop-down-panel"
|
||||||
|
formControlName="user"
|
||||||
|
[items]="usersSharedCollection"
|
||||||
|
[compareWith]="compareUser"
|
||||||
|
[clearable]="true"
|
||||||
|
[searchFn]="userSearchFn"
|
||||||
|
>
|
||||||
|
<ng-template ng-label-tmp let-item="item">
|
||||||
|
{{ item.login }} ( {{ item.email }} )
|
||||||
|
</ng-template>
|
||||||
|
<ng-template ng-option-tmp let-item="item">
|
||||||
|
{{ item.login }} ( {{ item.email }} )
|
||||||
|
</ng-template>
|
||||||
|
</ng-select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { finalize, map } from 'rxjs/operators';
|
||||||
|
|
||||||
import SharedModule from 'app/shared/shared.module';
|
import SharedModule from 'app/shared/shared.module';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { NgSelectModule } from '@ng-select/ng-select';
|
||||||
|
|
||||||
import { AlertError } from 'app/shared/alert/alert-error.model';
|
import { AlertError } from 'app/shared/alert/alert-error.model';
|
||||||
import { EventManager, EventWithContent } from 'app/core/util/event-manager.service';
|
import { EventManager, EventWithContent } from 'app/core/util/event-manager.service';
|
||||||
|
@ -23,7 +24,7 @@ import { OrganizationNature } from 'app/entities/enumerations/organization-natur
|
||||||
standalone: true,
|
standalone: true,
|
||||||
selector: 'jhi-organization-update',
|
selector: 'jhi-organization-update',
|
||||||
templateUrl: './organization-update.component.html',
|
templateUrl: './organization-update.component.html',
|
||||||
imports: [SharedModule, FormsModule, ReactiveFormsModule],
|
imports: [SharedModule, FormsModule, ReactiveFormsModule, NgSelectModule],
|
||||||
})
|
})
|
||||||
export class OrganizationUpdateComponent implements OnInit {
|
export class OrganizationUpdateComponent implements OnInit {
|
||||||
// Properties with defaults by router
|
// Properties with defaults by router
|
||||||
|
@ -181,7 +182,7 @@ export class OrganizationUpdateComponent implements OnInit {
|
||||||
|
|
||||||
protected loadRelationshipsOptionsUser(): void {
|
protected loadRelationshipsOptionsUser(): void {
|
||||||
this.userService
|
this.userService
|
||||||
.query()
|
.queryForOrganization()
|
||||||
.pipe(map((res: HttpResponse<IUser[]>) => res.body ?? []))
|
.pipe(map((res: HttpResponse<IUser[]>) => res.body ?? []))
|
||||||
.pipe(map((users: IUser[]) => this.userService.addUserToCollectionIfMissing<IUser>(users, this.organization?.user)))
|
.pipe(map((users: IUser[]) => this.userService.addUserToCollectionIfMissing<IUser>(users, this.organization?.user)))
|
||||||
.subscribe((users: IUser[]) => (this.usersSharedCollection = users));
|
.subscribe((users: IUser[]) => (this.usersSharedCollection = users));
|
||||||
|
@ -227,4 +228,9 @@ export class OrganizationUpdateComponent implements OnInit {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userSearchFn = (term: string, item: any) => {
|
||||||
|
term = term.toLowerCase();
|
||||||
|
return (item.login + "( " + item.email + " )").toLowerCase().includes(term);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,11 @@ export class UserService {
|
||||||
return this.http.get<IUser[]>(this.resourceUrl, { params: options, observe: 'response' });
|
return this.http.get<IUser[]>(this.resourceUrl, { params: options, observe: 'response' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
queryForOrganization(req?: any): Observable<EntityArrayResponseType> {
|
||||||
|
const options = createRequestOption(req);
|
||||||
|
return this.http.get<IUser[]>(`${this.resourceUrl}/for/organization`, { params: options, observe: 'response' });
|
||||||
|
}
|
||||||
|
|
||||||
getUserIdentifier(user: Pick<IUser, 'id'>): number {
|
getUserIdentifier(user: Pick<IUser, 'id'>): number {
|
||||||
return user.id;
|
return user.id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
export interface IUser {
|
export interface IUser {
|
||||||
id: number;
|
id: number;
|
||||||
login?: string | null;
|
login?: string | null;
|
||||||
|
email?: string | null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue