feat: Gruppen- und Modultabellen zur Benutzerseite hinzugefügt; Frontend- und Backend-APIs aktualisiert, um Gruppen basierend auf der Benutzerauswahl zu filtern

This commit is contained in:
Developer 02 2024-07-25 11:00:42 +02:00
parent 21d7507726
commit 19ba6f0da9
10 changed files with 92 additions and 12 deletions

View File

@ -127,7 +127,7 @@ export class BaseTableComponent<TModel, TApiService extends ApiService<TModel>>
return this.mainGrid.api;
}
set source(data: TModel[]) {
set source(data: any[]) {
this.api.setSource(data)
}

View File

@ -7,6 +7,7 @@ import { ColorModeService } from '../../../services/color-mode.service';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { env } from '../../../../environments/environment';
import { GroupOfUserService } from '../../../services/group-of-user.service';
@Component({
standalone: true,
@ -16,8 +17,14 @@ import { env } from '../../../../environments/environment';
styleUrl: './group-table.component.css'
})
export class GroupTableComponent extends BaseTableComponent<Group, GroupService> {
constructor(
service: GroupService, cModeService: ColorModeService) {
constructor(service: GroupService, cModeService: ColorModeService, private gouService: GroupOfUserService) {
super(service, env.columnNames.group.complete, cModeService)
}
fetchDataByUsername(username: string) {
console.log(username)
this.gouService.getByUsername(username)
.then(gos_list => gos_list.map(gos => gos.group))
.then(groups => this.source = groups)
}
}

View File

@ -1 +1,26 @@
<app-user-table #userTable [cellEditing]="cellEditing"></app-user-table>
<div class="container-fluid text-center">
<div class="row m-0 p-0">
<div class="col-6">
<mat-tab-group>
<mat-tab label="Benutzer">
<app-user-table #userTable [onSelectedRows]="usersOnSelectedRows"
[cellEditing]="cellEditing"></app-user-table>
</mat-tab>
</mat-tab-group>
</div>
<div class="col-3">
<mat-tab-group>
<mat-tab label="Gruppen">
<app-group-table #groupTable [initData]="initWithoutData"></app-group-table>
</mat-tab>
</mat-tab-group>
</div>
<div class="col-3">
<mat-tab-group>
<mat-tab label="Module">
<app-module-table #moduleTable [initData]="initWithoutData"></app-module-table>
</mat-tab>
</mat-tab-group>
</div>
</div>
</div>

View File

@ -1,16 +1,21 @@
import { AfterViewInit, Component, ViewChild } from '@angular/core';
import { GuiCellEdit } from '@generic-ui/ngx-grid';
import { GuiCellEdit, GuiSelectedRow } from '@generic-ui/ngx-grid';
import { UserTableComponent } from '../tables/user-table/user-table.component';
import { RefreshService } from '../../services/refresh.service';
import { MatTabsModule } from '@angular/material/tabs';
import { GroupTableComponent } from '../../components/tables/group-table/group-table.component';
import { ModuleTableComponent } from '../../components/tables/module-table/module-table.component';
@Component({
standalone: true,
imports: [UserTableComponent],
imports: [UserTableComponent, MatTabsModule, GroupTableComponent, ModuleTableComponent],
selector: 'app-user',
templateUrl: './user.component.html',
styleUrl: './user.component.css'
})
export class UserComponent implements AfterViewInit {
initWithoutData = () => { }
cellEditing: GuiCellEdit = {
enabled: true,
rowEdit: (value: any, item: any, index: number) => {
@ -21,6 +26,8 @@ export class UserComponent implements AfterViewInit {
}
}
private sUsername = null;
constructor(private refreshService: RefreshService) { }
ngAfterViewInit(): void {
@ -31,4 +38,15 @@ export class UserComponent implements AfterViewInit {
}
@ViewChild("userTable") userTable!: UserTableComponent
@ViewChild("groupTable") groupTable!: GroupTableComponent;
@ViewChild("moduleTable") moduleTable!: ModuleTableComponent;
usersOnSelectedRows = (rows: GuiSelectedRow[]) => {
if (rows.length > 0) {
this.sUsername = rows[0].source.username;
if (this.sUsername != null)
this.groupTable.fetchDataByUsername(this.sUsername);
}
}
}

View File

@ -2,14 +2,14 @@ import { Injectable, Inject } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { GroupOfUser } from '../models/user-management.api.models';
import { ApiService } from './user-management.api.service';
import { Observable } from 'rxjs';
import { Observable, firstValueFrom } from 'rxjs';
import { UrlService } from './url.service';
@Injectable({
providedIn: 'root'
})
export class GroupOfUserService extends ApiService<GroupOfUser> {
constructor(http: HttpClient, urlService : UrlService) {
constructor(http: HttpClient, urlService: UrlService) {
super(http, urlService.apiRoute.groupOfUser);
}
@ -29,4 +29,9 @@ export class GroupOfUserService extends ApiService<GroupOfUser> {
return this.http.get<GroupOfUser[]>(this.baseUrl, { params, withCredentials: true });
}
async getByUsername(username: string): Promise<GroupOfUser[]> {
const url = `${this.baseUrl}?username=${username}`;
return await firstValueFrom(this.http.get<GroupOfUser[]>(url, { withCredentials: true }));
}
}

View File

@ -37,10 +37,17 @@ namespace DigitalData.UserManager.API.Controllers
public override Task<IActionResult> GetAll() => base.GetAll();
[HttpGet]
public async Task<IActionResult> GetAll([FromQuery]bool withUser = false, [FromQuery]bool withGroup = false)
public async Task<IActionResult> GetAll([FromQuery]bool withUser = false, [FromQuery]bool withGroup = false, [FromQuery] string? username = null)
{
try
{
if (username is not null)
return await _service.ReadByUsernameAsync(username).ThenAsync(Ok, IActionResult (m, n) =>
{
_logger.LogNotice(n);
return NotFound();
});
return await _service.ReadAllAsyncWith(withUser, withGroup).ThenAsync(Ok, IActionResult (m, n) =>
{
_logger.LogNotice(n);

View File

@ -12,5 +12,7 @@ namespace DigitalData.UserManager.Application.Contracts
Task<DataResult<IEnumerable<GroupOfUserReadDto>>> ReadAllAsyncWith(bool user, bool group);
Task<Result> HasGroup(string username, string groupname, bool caseSensitive = true);
Task<DataResult<IEnumerable<GroupOfUserReadDto>>> ReadByUsernameAsync(string username);
}
}

View File

@ -5,7 +5,6 @@ using DigitalData.UserManager.Application.Contracts;
using DigitalData.UserManager.Application.DTOs.GroupOfUser;
using DigitalData.UserManager.Domain.Entities;
using DigitalData.UserManager.Infrastructure.Contracts;
using Microsoft.Extensions.Localization;
namespace DigitalData.UserManager.Application.Services
{
@ -63,5 +62,12 @@ namespace DigitalData.UserManager.Application.Services
return gous.Any() ? Result.Success() : Result.Fail();
}
public async Task<DataResult<IEnumerable<GroupOfUserReadDto>>> ReadByUsernameAsync(string username)
{
var groups = await _repository.ReadByUsernameAsync(username);
var groupDtos = _mapper.MapOrThrow<IEnumerable<GroupOfUserReadDto>>(groups);
return Result.Success(groupDtos);
}
}
}

View File

@ -14,5 +14,7 @@ namespace DigitalData.UserManager.Infrastructure.Contracts
Task<IEnumerable<GroupOfUser>> ReadAllAsyncWithUser();
Task<IEnumerable<GroupOfUser>> ReadAllAsyncWithGroupAndUser();
Task<IEnumerable<GroupOfUser>> ReadByUsernameAsync(string username);
}
}

View File

@ -12,9 +12,15 @@ namespace DigitalData.UserManager.Infrastructure.Repositories
{
}
//TODO: making it public and having it in the interface is against Clean Architecture. Make it private
public IQueryable<GroupOfUser> ReadByGroupId(int groupId)
{
return _dbSet.Where<GroupOfUser>(mou => mou.GroupId == groupId);
return _dbSet.Where(mou => mou.GroupId == groupId);
}
private IQueryable<GroupOfUser> ReadByUsername(string userName)
{
return _dbSet.Where(gou => gou.User!.Username == userName).Include(gou => gou.Group);
}
public async Task<IEnumerable<GroupOfUser>> ReadByGroupUserIdAsync(int groupId, int userId)
@ -26,6 +32,8 @@ namespace DigitalData.UserManager.Infrastructure.Repositories
public async Task<IEnumerable<GroupOfUser>> ReadAllAsyncWithUser() => await _dbSet.Include(gou => gou.User).ToListAsync();
public async Task<IEnumerable<GroupOfUser>> ReadAllAsyncWithGroupAndUser() => await _dbSet.Include(gou => gou.Group).Include(gou => gou.User).ToListAsync();
public async Task<IEnumerable<GroupOfUser>> ReadAllAsyncWithGroupAndUser() => await _dbSet.Include(gou => gou.Group).Include(gou => gou.User).ToListAsync();
public async Task<IEnumerable<GroupOfUser>> ReadByUsernameAsync(string username) => await ReadByUsername(username).ToListAsync();
}
}