Updating role management

This commit is contained in:
Martin Stockhammer 2020-12-22 20:27:51 +01:00
parent b247e09a9e
commit 3012e2f76f
10 changed files with 141 additions and 24 deletions

View File

@ -163,6 +163,7 @@
<h4>{{'roles.edit.usersParents'|translate}}</h4>
<app-paginated-entities [service]="roleUserParentService" pageSize="5" [(sortField)]="userParentSortField"
[(sortOrder)]="userParentSortOrder" [displayControlsIfSinglePage]="false"
[id]="'userParentSection'"
#userParentSection>
<ng-container *ngIf="userParentSection.items$ |async as itemLoader">
@ -198,8 +199,10 @@
<hr/>
<h4>{{'roles.edit.usersInstance'|translate}}</h4>
<app-paginated-entities [service]="roleUserService" pageSize="5" [(sortField)]="userSortField"
[id]="'userSection'"
[(sortOrder)]="userSortOrder"
[displayIfEmpty]="false" [displayKeyIfEmpty]="'roles.edit.noUsersAssigned'"
[displayControlsIfSinglePage]="false"
#userSection>
<ng-container *ngIf="userSection.items$ |async as itemLoader">
@ -219,6 +222,7 @@
contentText="users.attributes.user_id"></app-th-sorted>
<app-th-sorted [fieldArray]="['full_name']"
contentText="users.attributes.full_name"></app-th-sorted>
<th>{{'headers.action'|translate}}</th>
</tr>
</thead>
<tbody>
@ -227,6 +231,8 @@
ngbTooltip="{{user.id}}">{{user.user_id}}</span>
</td>
<td>{{user.full_name}}</td>
<td><a href="javascript: void(0)" (click)="unassignUser(user.user_id)"><span
class="fas fa-user-minus"></span></a></td>
</tr>
</tbody>
</table>
@ -235,7 +241,7 @@
<hr/>
<form class="mt-2">
<ng-template #userResultTemplate let-r="result" let-t="term">
<ngb-highlight [result]="r.user_id + '-' + r.full_name" [term]="t"></ngb-highlight>
<ngb-highlight [result]="r.user_id + ' - ' + r.full_name" [term]="t"></ngb-highlight>
</ng-template>
<div class="form-group">
<label for="typeahead-http">{{'roles.edit.assignUserSearch'|translate}}</label>
@ -254,6 +260,12 @@
</form>
</ng-template>
<div *ngIf="success">
Success
</div>
<div *ngIf="error">
<div>Error {{errorResult.error_messages}}</div>
</div>
</ngb-panel>
</ngb-accordion>

View File

@ -16,7 +16,16 @@
* under the License.
*/
import {AfterContentInit, Component, EventEmitter, OnInit, Output} from '@angular/core';
import {
AfterContentInit,
ChangeDetectorRef,
Component,
EventEmitter,
OnInit,
Output,
TemplateRef,
ViewChild
} from '@angular/core';
import {ActivatedRoute} from "@angular/router";
import {FormBuilder, Validators} from "@angular/forms";
import {RoleService} from "@app/services/role.service";
@ -31,6 +40,8 @@ import {User} from '@app/model/user';
import {PagedResult} from "@app/model/paged-result";
import {UserService} from "@app/services/user.service";
import {UserInfo} from '@app/model/user-info';
import {HttpResponse} from "@angular/common/http";
import {PaginatedEntitiesComponent} from "@app/modules/shared/paginated-entities/paginated-entities.component";
@Component({
selector: 'app-manage-roles-edit',
@ -55,11 +66,14 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
public userSearchModel:any;
@ViewChild('userSection') roleUserComponent: PaginatedEntitiesComponent<UserInfo>;
@ViewChild('userParentSection') roleUserParentComponent: PaginatedEntitiesComponent<UserInfo>;
@Output()
roleIdEvent: EventEmitter<string> = new EventEmitter<string>(true);
constructor(private route: ActivatedRoute, public roleService: RoleService, private userService: UserService, public fb: FormBuilder) {
constructor(private route: ActivatedRoute, public roleService: RoleService, private userService: UserService,
public fb: FormBuilder, private changeDetect : ChangeDetectorRef) {
super(fb);
super.init(fb.group({
id: [''],
@ -100,6 +114,12 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
this.roleUserParentService = function (searchTerm: string, offset: number, limit: number, orderBy: string[], order: string): Observable<PagedResult<User>> {
return fRoleService.queryAssignedParentUsers(roleId, searchTerm, offset, limit, orderBy, order, true);
};
if (this.roleUserComponent) {
this.roleUserComponent.changeService(this.roleUserService);
}
if (this.roleUserParentComponent) {
this.roleUserParentComponent.changeService(this.roleUserParentService);
}
}, error => {
this.editRole = new Role();
});
@ -166,7 +186,7 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
let role = new RoleUpdate();
role.id=this.userForm.get('id').value;
role.description = this.userForm.get('description').value;
console.log("Submitting changes " + role);
// console.log("Submitting changes " + role);
this.roleService.updateRole(role).pipe(
catchError((err: ErrorResult) => {
this.error = true;
@ -185,6 +205,7 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
}
ngAfterContentInit(): void {
// console.log("AfterContentInit")
if (this.originRole) {
this.editRole = this.originRole;
}
@ -196,7 +217,7 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
distinctUntilChanged(),
tap(() => this.userSearching = true),
switchMap(term =>
this.userService.query(term, 0, 10).pipe(
this.roleService.queryUnAssignedUsers(this.editRole.id, term, 0, 10).pipe(
tap(() => this.userSearchFailed = false),
map(pagedResult=>
pagedResult.data),
@ -221,7 +242,45 @@ export class ManageRolesEditComponent extends EditBaseComponent<Role> implements
userId = this.userSearchModel.user_id;
}
}
console.log("Assigning user " + userId)
if (this.editRole.id!=null && userId!=null && userId.length>0) {
this.roleService.assignRole(this.editRole.id, userId).pipe(
catchError((err: ErrorResult) => {
this.error = true;
this.success = false;
this.errorResult = err;
return [];
})
).subscribe((response : HttpResponse<Role>) => {
this.error = false;
this.success = true;
this.errorResult = null;
this.result = response.body;
this.roleUserComponent.changePage(1);
this.userSearchModel=''
});
}
}
unassignUser(user_id:string) {
// console.log("Unassigning " + this.editRole.id + " - " + user_id);
if (this.editRole.id!=null && user_id!=null && user_id.length>0) {
this.roleService.unAssignRole(this.editRole.id, user_id).pipe(
catchError((err: ErrorResult) => {
this.error = true;
this.success = false;
this.errorResult = err;
return [];
})
).subscribe((response : HttpResponse<Role>) => {
// console.log("Deleted ");
this.error = false;
this.success = true;
this.errorResult = null;
this.result = response.body;
this.roleUserComponent.changePage(1);
}
);
}
}
}

View File

@ -38,7 +38,7 @@ export class ManageRolesListComponent extends SortedTableComponent<Role> impleme
constructor(translator: TranslateService, roleService : RoleService, private ngbModal:NgbModal) {
super(translator, function (searchTerm: string, offset: number, limit: number, orderBy: string[], order: string): Observable<PagedResult<Role>> {
console.log("Retrieving data " + searchTerm + "," + offset + "," + limit + "," + orderBy + "," + order);
// console.log("Retrieving data " + searchTerm + "," + offset + "," + limit + "," + orderBy + "," + order);
return roleService.query(searchTerm, offset, limit, orderBy, order);
});
}

View File

@ -68,7 +68,7 @@ export class ManageUsersBaseComponent {
for (let prop of properties) {
user[prop] = this.userForm.get(prop).value;
}
console.log("User " + user);
// console.log("User " + user);
return user;
}
@ -79,7 +79,7 @@ export class ManageUsersBaseComponent {
propMap[prop] = propValue;
}
this.userForm.patchValue(propMap);
console.log("User " + user);
// console.log("User " + user);
}

View File

@ -48,7 +48,7 @@ export class ManageUsersDeleteComponent implements OnInit, AfterViewInit {
private runModal() {
if (this.user_id!=null && this.user_id!='') {
let modalInstance = this.modal.open(this.askModal).result.then((result) => {
console.log("Result: " + result);
// console.log("Result: " + result);
let userId = this.user_id;
if (result=='YES' && userId!=null && userId!='') {
let deleted = this.userService.deleteUser(userId).subscribe();
@ -59,7 +59,7 @@ export class ManageUsersDeleteComponent implements OnInit, AfterViewInit {
this.router.navigate(['/security','users','list']);
}
}, (reason) => {
console.log("Reason: " + reason);
// console.log("Reason: " + reason);
});
}
}

View File

@ -39,7 +39,7 @@ export class ManageUsersListComponent implements OnInit {
constructor(private translator: TranslateService, private userService : UserService) {
this.service = function (searchTerm: string, offset: number, limit: number, orderBy: string[], order: string) : Observable<PagedResult<UserInfo>> {
console.log("Retrieving data " + searchTerm + "," + offset + "," + limit + "," + orderBy + "," + order);
// console.log("Retrieving data " + searchTerm + "," + offset + "," + limit + "," + orderBy + "," + order);
return userService.query(searchTerm, offset, limit, orderBy, order);
}

View File

@ -22,7 +22,7 @@
<div class="row col-md-6">
<h4 class="col-md-2 mt-3">{{'users.roles.base_roles'|translate}} </h4>
<h4 class="col-md-2 offset-md-4 mt-3"><span class="badge badge-primary">{{userid}}</span></h4>
<h4 class="col-md-2 offset-md-4 mt-3" *ngIf="roles$"><span class="badge badge-primary">{{userid}}</span></h4>
</div>
<ng-container *ngIf="roles$|async as myRoles">
<table class="table col-md-12">

View File

@ -44,7 +44,6 @@ export class ManageUsersComponent implements OnInit {
// console.log("Activating "+componentReference+" - "+JSON.stringify(componentReference,getCircularReplacer()))
if (componentReference.userIdEvent!=null) {
let componentEmit : Observable<string> = componentReference.userIdEvent.pipe(
tap(userid=>console.log("Event "+componentReference.class+" "+userid)),
map((userid: string) => this.getSubPath(userid)));
if (this.userId$!=null) {
this.userId$ = merge(this.userId$, componentEmit)

View File

@ -16,7 +16,7 @@
* under the License.
*/
import {AfterViewInit, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {AfterViewInit, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {concat, merge, Observable, of, pipe, Subject} from "rxjs";
import {
concatAll,
@ -29,7 +29,8 @@ import {
pluck,
share,
startWith,
switchMap
switchMap,
tap
} from "rxjs/operators";
import {EntityService} from "../../../model/entity-service";
import {FieldToggle} from "../../../model/field-toggle";
@ -64,6 +65,8 @@ import {PagedResult} from "@app/model/paged-result";
})
export class PaginatedEntitiesComponent<T> implements OnInit, FieldToggle, AfterViewInit {
@Input() id: string;
/**
* This must be set, if you use the component. This service retrieves the entity data.
*/
@ -138,26 +141,30 @@ export class PaginatedEntitiesComponent<T> implements OnInit, FieldToggle, After
/**
* The total number of elements available for the given search term
*/
total$: Observable<number>;
public total$: Observable<number>;
/**
* The entity items retrieved from the service
*/
items$: Observable<LoadingValue<PagedResult<T>>>;
public items$: Observable<LoadingValue<PagedResult<T>>>;
/**
* true, if the current page result value represents a result with multiple pages,
* otherwise false.
*/
multiplePages$:Observable<boolean>;
public multiplePages$:Observable<boolean>;
private pageStream: Subject<number> = new Subject<number>();
private searchTermStream: Subject<string> = new Subject<string>();
constructor() {
// console.log("Construct " + this.id);
this.items$=null;
this.total$=null;
this.multiplePages$=null;
}
ngOnInit(): void {
// console.log("Pag Init " + this.id);
// We combine the sources for the page and the search input field to a observable 'source'
const pageSource = this.pageStream.pipe(map(pageNumber => {
return new PageQuery(this.searchTerm, pageNumber);
@ -177,10 +184,13 @@ export class PaginatedEntitiesComponent<T> implements OnInit, FieldToggle, After
this.service(params.search, (params.page - 1) * this.pageSize, this.pageSize, this.sortField, this.sortOrder)
.pipe(map(pagedResult=>LoadingValue.finish<PagedResult<T>>(pagedResult)))
)
), share());
this.total$ = source.pipe(filter(val=>val.hasValue()),map(val=>val.value),pluck('pagination', 'total_count'));
)
);
this.total$ = source.pipe(filter(val=>val.hasValue()),map(val=>val.value),
pluck('pagination', 'total_count'));
this.multiplePages$ = source.pipe(filter(val => val.hasValue()),
map(val => val.value.pagination.total_count > val.value.pagination.limit));
this.items$ = source;
this.multiplePages$ = source.pipe(filter(val => val.hasValue()), map(val => val.value.pagination.total_count >= val.value.pagination.limit));
}
search(terms: string) {
@ -189,7 +199,7 @@ export class PaginatedEntitiesComponent<T> implements OnInit, FieldToggle, After
this.searchTermStream.next(terms)
}
changePage(pageNumber: number) {
public changePage(pageNumber: number) {
// console.log("Page change " +pageNumber);
this.pageChange.emit(pageNumber);
this.pageStream.next(pageNumber);
@ -242,9 +252,16 @@ export class PaginatedEntitiesComponent<T> implements OnInit, FieldToggle, After
}
ngAfterViewInit(): void {
// console.log("Pag afterViewInit " + this.id);
// We emit the current value to push them to the containing reading components
this.sortOrderChange.emit(this.sortOrder);
this.sortFieldChange.emit(this.sortField);
}
public changeService(newService : EntityService<T>): void {
this.service = newService;
this.changePage(1);
}
}

View File

@ -80,6 +80,17 @@ export class RoleService {
});
}
/**
* Query for assigned users, that are part of the parent roles.
*
* @param roleId
* @param searchTerm
* @param offset
* @param limit
* @param orderBy
* @param order
* @param parentsOnly
*/
public queryAssignedParentUsers(roleId: string,
searchTerm: string, offset: number = 0, limit: number = 5,
orderBy: string[] = ['id'], order: string = 'asc', parentsOnly:boolean=true): Observable<PagedResult<User>> {
@ -100,6 +111,25 @@ export class RoleService {
});
}
public queryUnAssignedUsers(roleId: string,
searchTerm: string, offset: number = 0, limit: number = 5,
orderBy: string[] = ['id'], order: string = 'asc'): Observable<PagedResult<User>> {
if (searchTerm == null) {
searchTerm = ""
}
if (orderBy == null || orderBy.length == 0) {
orderBy = ['id'];
}
return this.rest.executeRestCall<PagedResult<User>>("get", "redback", "roles/" + roleId + "/unassigned", {
'q': searchTerm,
'offset': offset,
'limit': limit,
'orderBy': orderBy,
'order': order
});
}
public getRole(roleId:string) : Observable<Role> {
return this.rest.executeRestCall("get", "redback", "roles/" + roleId, null);
}