Compare commits
13 Commits
e80ec2cf8d
...
2800392be3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2800392be3 | ||
|
|
b7f4ed7597 | ||
|
|
16cc729373 | ||
|
|
4d38cce459 | ||
|
|
80a3f96404 | ||
|
|
2a4358a7c7 | ||
|
|
978d8aaa55 | ||
|
|
ae729198b9 | ||
|
|
76f57676b1 | ||
|
|
97cefb3fea | ||
|
|
1273b7ac46 | ||
|
|
4c02607409 | ||
|
|
9f99bb0bc9 |
@@ -1,72 +1,70 @@
|
||||
<div class="container my-3">
|
||||
<div class="row">
|
||||
<div [ngClass]="formFieldBSClass">
|
||||
<mat-form-field>
|
||||
<mat-label>Benutzername</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[formControl]="username"
|
||||
(blur)="updateErrorMessage()"
|
||||
<div class="dd-container">
|
||||
<!-- username, e-mail -->
|
||||
<div class="dd-row input-row">
|
||||
<mat-form-field>
|
||||
<mat-label>Benutzername</mat-label>
|
||||
<input matInput [formControl]="username" (blur)="updateErrorMessage()" required />
|
||||
@if (email.invalid) {
|
||||
<mat-error>{{errorMessage()}}</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>E-Mail</mat-label>
|
||||
<input matInput placeholder="user@example.com" [formControl]="email" (blur)="updateMailErrorMessage()"
|
||||
required />
|
||||
@if (email.invalid) {
|
||||
<mat-error>{{errorMessage()}}</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div [ngClass]="formFieldBSClass">
|
||||
<mat-form-field>
|
||||
<mat-label>E-Mail</mat-label>
|
||||
<input
|
||||
matInput placeholder="user@example.com"
|
||||
[formControl]="email"
|
||||
(blur)="updateMailErrorMessage()"
|
||||
required />
|
||||
@if (email.invalid) {
|
||||
<mat-error>{{mailErrorMessage()}}</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div [ngClass]="formFieldBSClass">
|
||||
<div [ngClass]="buttonBSClass">
|
||||
<button mat-fab extended (click)="update()">
|
||||
<mat-icon>save</mat-icon>
|
||||
Speichern
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@if (email.invalid) {
|
||||
<mat-error>{{mailErrorMessage()}}</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div [ngClass]="formFieldBSClass">
|
||||
<mat-form-field>
|
||||
<mat-label>Vorname</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[formControl]="name"
|
||||
(blur)="updateErrorMessage()"
|
||||
required />
|
||||
@if (email.invalid) {
|
||||
<mat-error>{{errorMessage()}}</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div [ngClass]="formFieldBSClass">
|
||||
<mat-form-field>
|
||||
<mat-label>Nachname</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[formControl]="surname"
|
||||
(blur)="updateErrorMessage()"
|
||||
required />
|
||||
@if (email.invalid) {
|
||||
<mat-error>{{errorMessage()}}</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div [ngClass]="formFieldBSClass">
|
||||
<button mat-fab extended (click)="delete()">
|
||||
<mat-icon>delete</mat-icon>
|
||||
Löschen
|
||||
</button>
|
||||
</div>
|
||||
<!-- firstname, surname -->
|
||||
<div class="dd-row input-row">
|
||||
<mat-form-field>
|
||||
<mat-label>Vorname</mat-label>
|
||||
<input matInput [formControl]="name" (blur)="updateErrorMessage()" required />
|
||||
@if (email.invalid) {
|
||||
<mat-error>{{errorMessage()}}</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Nachname</mat-label>
|
||||
<input matInput [formControl]="surname" (blur)="updateErrorMessage()" required />
|
||||
@if (email.invalid) {
|
||||
<mat-error>{{errorMessage()}}</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<!-- shortname -->
|
||||
<div class="dd-row input-row">
|
||||
<mat-form-field>
|
||||
<mat-label>Kürzel</mat-label>
|
||||
<input matInput [formControl]="shortname" />
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>Datumsformat</mat-label>
|
||||
<mat-select [(value)]="user.dateFormat" [(ngModel)]="user.dateFormat">
|
||||
<mat-option value="dd.MM.yyyy">dd.MM.yyyy</mat-option>
|
||||
<mat-option value="MM.dd.yyyy">MM.dd.yyyy</mat-option>
|
||||
<mat-option value="yyyy-MM-dd">yyyy-MM-dd</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<!-- comment -->
|
||||
<div class="dd-row input-row">
|
||||
<mat-form-field>
|
||||
<mat-label>Kommentar</mat-label>
|
||||
<input matInput [formControl]="comment" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<!-- save-button, delete-button -->
|
||||
<div class="dd-row button-row">
|
||||
<button mat-fab extended (click)="update()">
|
||||
<mat-icon>save</mat-icon>
|
||||
Speichern
|
||||
</button>
|
||||
<button mat-fab extended (click)="delete()">
|
||||
<mat-icon>delete</mat-icon>
|
||||
Löschen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,32 @@
|
||||
.dd-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
margin: 1rem 0 1rem 0;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.dd-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.input-row {
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.button-row {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
mat-form-field {
|
||||
width: 100%;
|
||||
margin: 0 1rem 0 1rem;
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 0 1rem 0 1rem;
|
||||
}
|
||||
@@ -14,11 +14,12 @@ import { UserGroupDirImportComponent } from "../../user-group-dir-import/user-gr
|
||||
import { UserService } from '../../../services/api/user.service';
|
||||
import { RefreshService } from '../../../services/button/refresh.service';
|
||||
import Swal from 'sweetalert2';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
|
||||
@Component({
|
||||
selector: 'app-user-update-form',
|
||||
standalone: true,
|
||||
imports: [MatFormFieldModule, MatInputModule, FormsModule, ReactiveFormsModule, MatIconModule, MatButtonModule, CommonModule, MatTabsModule, UserGroupDirImportComponent],
|
||||
imports: [MatFormFieldModule, MatInputModule, FormsModule, ReactiveFormsModule, MatIconModule, MatButtonModule, CommonModule, MatTabsModule, UserGroupDirImportComponent, MatSelectModule],
|
||||
templateUrl: './user-update-form.component.html',
|
||||
styleUrl: './user-update-form.component.scss'
|
||||
})
|
||||
@@ -29,16 +30,15 @@ export class UserUpdateFormComponent {
|
||||
readonly user: User = inject(MAT_DIALOG_DATA);
|
||||
|
||||
readonly username = new FormControl(this.user.username, [Validators.required]);
|
||||
readonly email = new FormControl(this.user.email, [Validators.required, Validators.email]);
|
||||
readonly name = new FormControl(this.user.prename, [Validators.required]);
|
||||
readonly surname = new FormControl(this.user.name, [Validators.required]);
|
||||
readonly email = new FormControl(this.user.email, [Validators.required, Validators.email]);
|
||||
readonly shortname = new FormControl(this.user.shortname);
|
||||
readonly comment = new FormControl(this.user.comment);
|
||||
|
||||
mailErrorMessage = signal('');
|
||||
errorMessage = signal('');
|
||||
|
||||
public readonly formFieldBSClass: string = "col d-flex justify-content-center mx-1 my-2"
|
||||
public readonly buttonBSClass: string = "d-flex justify-content-center mx-1 my-2"
|
||||
|
||||
constructor(private uService: UserService, private rService: RefreshService) {
|
||||
merge(
|
||||
this.email.statusChanges, this.email.valueChanges)
|
||||
@@ -77,7 +77,9 @@ export class UserUpdateFormComponent {
|
||||
this.user.prename = this.name.value!;
|
||||
this.user.username = this.username.value!;
|
||||
this.user.name = this.surname.value!;
|
||||
|
||||
this.user.shortname = this.shortname.value!;
|
||||
this.user.comment = this.comment.value!;
|
||||
|
||||
this.uService.update(this.user).subscribe({
|
||||
next: () => {
|
||||
this.rService.executeAll();
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace DigitalData.UserManager.Application
|
||||
.AddScoped<IModuleRepository, ModuleRepository<TDbContext>>()
|
||||
.AddScoped<IModuleOfUserRepository, ModuleOfUserRepository<TDbContext>>()
|
||||
.AddScoped<IUserRepRepository, UserRepRepository<TDbContext>>()
|
||||
.AddScoped<IClientUserRepository, ClientUserRepository<TDbContext>>()
|
||||
|
||||
.AddScoped<IUserService, UserService>()
|
||||
.AddScoped<IGroupService, GroupService>()
|
||||
|
||||
35
DigitalData.UserManager.Domain/Entities/ClientUser.cs
Normal file
35
DigitalData.UserManager.Domain/Entities/ClientUser.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using DigitalData.Core.Abstractions;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace DigitalData.UserManager.Domain.Entities
|
||||
{
|
||||
[Table("TBDD_CLIENT_USER", Schema = "dbo")]
|
||||
public class ClientUser : IUnique<int>
|
||||
{
|
||||
[Column("GUID")]
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("USER_ID")]
|
||||
public int UserId { get; init; }
|
||||
|
||||
[Required]
|
||||
[Column("CLIENT_ID")]
|
||||
public int ClientId { get; init; }
|
||||
|
||||
[Column("COMMENT")]
|
||||
public string? Comment { get; init; }
|
||||
|
||||
[StringLength(50)]
|
||||
[Column("ADDED_WHO")]
|
||||
public string? AddedWho { get; set; }
|
||||
|
||||
[Column("ADDED_WHEN", TypeName = "datetime")]
|
||||
[DefaultValue("GETDATE()")]
|
||||
public DateTime AddedWhen { get; set; } = DateTime.Now;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using DigitalData.Core.Abstractions.Infrastructure;
|
||||
using DigitalData.UserManager.Domain.Entities;
|
||||
|
||||
namespace DigitalData.UserManager.Infrastructure.Contracts
|
||||
{
|
||||
public interface IClientUserRepository : ICRUDRepository<ClientUser, int>
|
||||
{
|
||||
Task<IEnumerable<ClientUser>> ReadAsync(bool readOnly = true, int? userId = null);
|
||||
}
|
||||
}
|
||||
@@ -16,5 +16,7 @@ namespace DigitalData.UserManager.Infrastructure.Contracts
|
||||
public DbSet<User> Users { get; }
|
||||
|
||||
public DbSet<UserRep> UserReps { get; }
|
||||
|
||||
public DbSet<ClientUser> ClientUsers { get; }
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,6 @@ namespace DigitalData.UserManager.Infrastructure.Contracts
|
||||
{
|
||||
Task<IEnumerable<UserRep>> ReadAllAsync(
|
||||
bool withUser = false, bool withRepGroup = false, bool withGroup = false, bool withRepUser = false,
|
||||
int? userId = null, int? groupId = null, int? repGroupId = null, bool readOnly = true);
|
||||
int? userId = null, int? repUserId = null, int? groupId = null, int? repGroupId = null, bool readOnly = true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using DigitalData.Core.Infrastructure;
|
||||
using DigitalData.UserManager.Domain.Entities;
|
||||
using DigitalData.UserManager.Infrastructure.Contracts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace DigitalData.UserManager.Infrastructure.Repositories
|
||||
{
|
||||
public class ClientUserRepository<TDbContext> : CRUDRepository<ClientUser, int, TDbContext>, IClientUserRepository
|
||||
where TDbContext : DbContext, IUserManagerDbContext
|
||||
{
|
||||
public ClientUserRepository(TDbContext dbContext) : base(dbContext, dbContext.ClientUsers)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ClientUser>> ReadAsync(bool readOnly = true, int? userId = null)
|
||||
{
|
||||
var query = readOnly ? _dbSet.AsNoTracking() : _dbSet.AsQueryable();
|
||||
|
||||
if (userId is not null)
|
||||
query = query.Where(cu => cu.UserId == userId);
|
||||
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,32 @@ namespace DigitalData.UserManager.Infrastructure.Repositories
|
||||
public class GroupRepository<TDbContext> : CRUDRepository<Group, int, TDbContext>, IGroupRepository
|
||||
where TDbContext : DbContext, IUserManagerDbContext
|
||||
{
|
||||
public GroupRepository(TDbContext dbContext) : base(dbContext, dbContext.Groups)
|
||||
private readonly IGroupOfUserRepository _gouRepo;
|
||||
|
||||
private readonly IUserRepRepository _uRepRepo;
|
||||
|
||||
public GroupRepository(TDbContext dbContext, IGroupOfUserRepository gouRepo, IUserRepRepository userRepRepository) : base(dbContext, dbContext.Groups)
|
||||
{
|
||||
_gouRepo = gouRepo;
|
||||
_uRepRepo = userRepRepository;
|
||||
}
|
||||
|
||||
//TODO: instead of this implmenet .OnDelete(DeleteBehavior.ClientCascade) in DbContext
|
||||
public override async Task<bool> DeleteAsync(Group group)
|
||||
{
|
||||
var gou_list = await _gouRepo.ReadAsync(readOnly: false, groupId: group.Id);
|
||||
if (gou_list.Any())
|
||||
_dbContext.RemoveRange(gou_list);
|
||||
|
||||
var uRep_list = await _uRepRepo.ReadAllAsync(readOnly: false, groupId: group.Id);
|
||||
if (uRep_list.Any())
|
||||
_dbContext.RemoveRange(uRep_list);
|
||||
|
||||
uRep_list = await _uRepRepo.ReadAllAsync(readOnly: false, repGroupId: group.Id);
|
||||
if (uRep_list.Any())
|
||||
_dbContext.RemoveRange(uRep_list);
|
||||
|
||||
return await base.DeleteAsync(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace DigitalData.UserManager.Infrastructure.Repositories
|
||||
|
||||
public async Task<IEnumerable<UserRep>> ReadAllAsync(
|
||||
bool withUser = false, bool withRepGroup = false, bool withGroup = false, bool withRepUser = false,
|
||||
int? userId = null, int? groupId = null, int? repGroupId = null, bool readOnly = true)
|
||||
int? userId = null, int? repUserId = null, int? groupId = null, int? repGroupId = null, bool readOnly = true)
|
||||
{
|
||||
var query = readOnly ? _dbSet.AsNoTracking() : _dbSet.AsQueryable();
|
||||
|
||||
@@ -30,9 +30,12 @@ namespace DigitalData.UserManager.Infrastructure.Repositories
|
||||
if (withRepUser)
|
||||
query = query.Include(ur => ur.RepUser);
|
||||
|
||||
if(userId is not null)
|
||||
if (userId is not null)
|
||||
query = query.Where(ur => ur.UserId == userId);
|
||||
|
||||
if (repUserId is not null)
|
||||
query = query.Where(ur => ur.RepUserId == repUserId);
|
||||
|
||||
if (groupId is not null)
|
||||
query = query.Where(ur => ur.GroupId == groupId);
|
||||
|
||||
|
||||
@@ -9,11 +9,19 @@ namespace DigitalData.UserManager.Infrastructure.Repositories
|
||||
where TDbContext : DbContext, IUserManagerDbContext
|
||||
{
|
||||
private readonly IModuleOfUserRepository _moduleOfUserRepo;
|
||||
|
||||
private readonly IGroupOfUserRepository _groupOfUserRepo;
|
||||
public UserRepository(TDbContext dbContext, IModuleOfUserRepository moduleOfUserRepo, IGroupOfUserRepository groupOfUserRepo) : base(dbContext, dbContext.Users)
|
||||
|
||||
private readonly IUserRepRepository _uRepRepo;
|
||||
|
||||
private readonly IClientUserRepository _cUserRepo;
|
||||
|
||||
public UserRepository(TDbContext dbContext, IModuleOfUserRepository moduleOfUserRepo, IGroupOfUserRepository groupOfUserRepo, IUserRepRepository userRepRepository, IClientUserRepository clientUserRepository) : base(dbContext, dbContext.Users)
|
||||
{
|
||||
_moduleOfUserRepo = moduleOfUserRepo;
|
||||
_groupOfUserRepo = groupOfUserRepo;
|
||||
_uRepRepo = userRepRepository;
|
||||
_cUserRepo = clientUserRepository;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<User>> ReadByModuleIdAsync(int moduleId)
|
||||
@@ -48,14 +56,26 @@ namespace DigitalData.UserManager.Infrastructure.Repositories
|
||||
//TODO: instead of this implmenet .OnDelete(DeleteBehavior.ClientCascade) in DbContext
|
||||
public override async Task<bool> DeleteAsync(User user)
|
||||
{
|
||||
IEnumerable<ModuleOfUser> mou = await _moduleOfUserRepo.ReadByUserAsync(user.Username);
|
||||
if(mou.Any())
|
||||
var mou = await _moduleOfUserRepo.ReadByUserAsync(user.Username);
|
||||
if (mou.Any())
|
||||
_dbContext.RemoveRange(mou);
|
||||
|
||||
IEnumerable<GroupOfUser> gou = await _groupOfUserRepo.ReadByUsernameAsync(user.Username);
|
||||
if(gou.Any())
|
||||
var gou = await _groupOfUserRepo.ReadByUsernameAsync(user.Username);
|
||||
if (gou.Any())
|
||||
_dbContext.RemoveRange(gou);
|
||||
|
||||
var uRep_list = await _uRepRepo.ReadAllAsync(readOnly: false, userId: user.Id);
|
||||
if (uRep_list.Any())
|
||||
_dbContext.RemoveRange(uRep_list);
|
||||
|
||||
uRep_list = await _uRepRepo.ReadAllAsync(readOnly: false, repUserId: user.Id);
|
||||
if (uRep_list.Any())
|
||||
_dbContext.RemoveRange(uRep_list);
|
||||
|
||||
var cu_list = await _cUserRepo.ReadAsync(readOnly: false, userId: user.Id);
|
||||
if (cu_list.Any())
|
||||
_dbContext.RemoveRange(cu_list);
|
||||
|
||||
return await base.DeleteAsync(user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ namespace DigitalData.UserManager.Infrastructure.Repositories
|
||||
|
||||
public DbSet<UserRep> UserReps { get; set; }
|
||||
|
||||
public DbSet<ClientUser> ClientUsers { get; set; }
|
||||
|
||||
public UserManagerDbContext(DbContextOptions<UserManagerDbContext> options) : base(options)
|
||||
{
|
||||
GroupOfUsers = Set<GroupOfUser>();
|
||||
@@ -26,6 +28,7 @@ namespace DigitalData.UserManager.Infrastructure.Repositories
|
||||
Modules = Set<Module>();
|
||||
Users = Set<User>();
|
||||
UserReps = Set<UserRep>();
|
||||
ClientUsers = Set<ClientUser>();
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
|
||||
Reference in New Issue
Block a user