Compare commits

...

5 Commits

Author SHA1 Message Date
Developer 02
698151baf3 feat(Konstanten): Erzeugen von Optionen aus Appsettings über IOptions.
- Konstantenmodell mit UserLanguages String-Array erstellen. Hinzufügen einer benutzerdefinierten Methode zum Abrufen der Eigenschaft über Name.
- imlement in appsettings und confgire in Program.cs
2024-09-26 13:03:49 +02:00
Developer 02
84982e0286 feat(user-update-form): Initilisiertes Formular
- Formularfelder mit Controllern für eail, prename, username, name und Buttons für speichern und löschen hinzugefügt.
2024-09-26 11:26:46 +02:00
Developer 02
ae75e54bdc refacor(user-update-component): MAT_DIALOG_DATA mit Funktionsinjektion anstelle von Konstruktorinjektion injizieren 2024-09-26 09:25:28 +02:00
Developer 02
2b51fde1fe feat(user-update-form): erstellt, um Benutzer mit einem Pop-up nach dem Zeilen-Klick-Ereignis zu aktualisieren.
- integriert in die Benutzer-Seite anstelle der Benutzer-Zusammenfassung
2024-09-25 17:12:39 +02:00
Developer 02
76104b4976 refactor(user-form): Umbenennung in user-create-form 2024-09-25 16:47:49 +02:00
13 changed files with 290 additions and 12 deletions

View File

@@ -17,10 +17,10 @@ import Swal from 'sweetalert2';
selector: 'app-user-form',
standalone: true,
imports: [MatFormFieldModule, MatInputModule, FormsModule, ReactiveFormsModule, MatIconModule, MatButtonModule, CommonModule, MatTabsModule, UserGroupDirImportComponent],
templateUrl: './user-form.component.html',
styleUrl: './user-form.component.scss'
templateUrl: './user-create-form.component.html',
styleUrl: './user-create-form.component.scss'
})
export class UserFormComponent {
export class UserCreateFormComponent {
readonly email = new FormControl('', [Validators.required, Validators.email]);
readonly username = new FormControl('', [Validators.required]);
readonly name = new FormControl('', [Validators.required]);

View File

@@ -0,0 +1,72 @@
<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()"
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>
</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>
</div>
</div>

View File

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UserUpdateFormComponent } from './user-update-form.component';
describe('UserUpdateFormComponent', () => {
let component: UserUpdateFormComponent;
let fixture: ComponentFixture<UserUpdateFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [UserUpdateFormComponent]
})
.compileComponents();
fixture = TestBed.createComponent(UserUpdateFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,130 @@
import { Component, inject, signal } from '@angular/core';
import { User } from '../../../models/user-management.api.models';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { FormControl, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { merge } from 'rxjs';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { CommonModule } from '@angular/common';
import { MatTabsModule } from '@angular/material/tabs';
import { UserGroupDirImportComponent } from "../../user-group-dir-import/user-group-dir-import.component";
import { UserService } from '../../../services/api/user.service';
import { RefreshService } from '../../../services/button/refresh.service';
import Swal from 'sweetalert2';
@Component({
selector: 'app-user-update-form',
standalone: true,
imports: [MatFormFieldModule, MatInputModule, FormsModule, ReactiveFormsModule, MatIconModule, MatButtonModule, CommonModule, MatTabsModule, UserGroupDirImportComponent],
templateUrl: './user-update-form.component.html',
styleUrl: './user-update-form.component.scss'
})
export class UserUpdateFormComponent {
readonly dialogRef: MatDialogRef<UserUpdateFormComponent> = inject(MatDialogRef<UserUpdateFormComponent>);
readonly user: User = inject(MAT_DIALOG_DATA);
readonly username = new FormControl(this.user.username, [Validators.required]);
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]);
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)
.pipe(takeUntilDestroyed())
.subscribe(() => this.updateMailErrorMessage());
merge(
this.username.statusChanges, this.username.valueChanges,
this.name.statusChanges, this.name.valueChanges,
this.surname.statusChanges, this.surname.valueChanges)
.pipe(takeUntilDestroyed())
.subscribe(() => this.updateErrorMessage());
}
updateMailErrorMessage() {
if (this.email.hasError('required')) {
this.mailErrorMessage.set('Wert eingeben');
} else if (this.email.hasError('email')) {
this.mailErrorMessage.set('Ungültige E-Mail');
} else {
this.mailErrorMessage.set('');
}
}
updateErrorMessage() {
if (this.email.hasError('required')) {
this.errorMessage.set('Wert eingeben');
} else {
this.errorMessage.set('');
}
}
update() {
if (this.email.valid && this.username.valid && this.name.valid && this.surname.valid) {
this.user.email = this.email.value!;
this.user.prename = this.name.value!;
this.user.username = this.username.value!;
this.user.name = this.surname.value!;
this.uService.update(this.user).subscribe({
next: () => {
this.rService.executeAll();
},
error: err => {
console.error(err)
Swal.fire({
title: "Interner Dienstfehler",
text: "Bitte wenden Sie sich an das IT-Team, um den Fehler zu beheben.",
icon: "error"
});
}
})
}
}
delete() {
Swal.fire({
text: "Sind Sie sicher, dass Sie diesen Datensatz löschen wollen?",
icon: "question",
showDenyButton: true,
confirmButtonText: "Ja",
denyButtonText: `Nein`
}).then((result) => {
if (result.isConfirmed) {
if (this.user.id) {
this.uService.delete(this.user.id).subscribe({
next: () => {
this.rService.executeAll();
this.dialogRef.close();
},
error: err => {
Swal.fire({
title: "Interner Dienstfehler",
text: "Bitte wenden Sie sich an das IT-Team, um den Fehler zu beheben.",
icon: "error"
});
},
})
}
else
Swal.fire({
title: "Ein unerwarteter Fehler",
text: "Die Benutzer-ID existiert nicht (Nullwert).",
icon: "error"
});
}
});
}
}

View File

@@ -4,16 +4,16 @@ import { UserTableComponent } from '../../components/tables/user-table/user-tabl
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';
import { UserFormComponent } from '../../components/forms/user-form/user-form.component';
import { UserCreateFormComponent } from '../../components/forms/user-create-form/user-create-form.component';
import { BasePageComponent } from '../base-page/base-page.component';
import { User } from '../../models/user-management.api.models';
import { firstValueFrom, forkJoin } from 'rxjs';
import Swal from 'sweetalert2';
import { env } from '../../../environments/environment'
import { UserSummaryComponent } from '../../components/summaries/user-summary/user-summary.component'
import { MatBottomSheet, MatBottomSheetModule } from '@angular/material/bottom-sheet';
import { MatButtonModule } from '@angular/material/button';
import { MatDialog } from '@angular/material/dialog';
import { UserUpdateFormComponent } from '../../components/forms/user-update-form/user-update-form.component';
@Component({
standalone: true,
@@ -42,6 +42,8 @@ export class UserComponent extends BasePageComponent implements AfterViewInit {
private _bottomSheet = inject(MatBottomSheet);
private readonly dialog: MatDialog = inject(MatDialog);
ngAfterViewInit(): void {
this.buttonVisibilityService.setVisibleOnly(this.refreshService, this.creationService, this.updateService)
this.refreshService.removeAll()
@@ -53,7 +55,7 @@ export class UserComponent extends BasePageComponent implements AfterViewInit {
}
});
this.creationService.component = UserFormComponent;
this.creationService.component = UserCreateFormComponent;
this.deletionService.add(() => this.handleDeleteRequest());
}
@@ -69,7 +71,7 @@ export class UserComponent extends BasePageComponent implements AfterViewInit {
if (this.sUsername != null) {
this.groupTable.fetchDataByUsername(this.sUsername);
this.moduleTable.fetchDataByUsername(this.sUsername)
this.openBottomSheet(rows[0].source);
this.openUpdateSheet(rows[0].source);
}
}
}
@@ -110,8 +112,9 @@ export class UserComponent extends BasePageComponent implements AfterViewInit {
return env.columnNames.user.detailed
}
openBottomSheet(user: User): void {
this._bottomSheet.open(UserSummaryComponent, {
openUpdateSheet(user: User): void {
this.dialog.open(UserUpdateFormComponent, {
width: "50rem",
data: user
});
}

View File

@@ -0,0 +1,27 @@
using DigitalData.UserManager.API.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
namespace DigitalData.UserManager.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ConstantsController : ControllerBase
{
private readonly Constants _constants;
public ConstantsController(IOptions<Constants> constantsOptions)
{
_constants = constantsOptions.Value;
}
[HttpGet]
public IActionResult GetConstant(string? name = null)
{
if(name is null)
return Ok(_constants);
return Ok(_constants[name]);
}
}
}

View File

@@ -0,0 +1,13 @@
using System.Reflection;
namespace DigitalData.UserManager.API.Models
{
public class Constants
{
public IEnumerable<string> UserLanguages { get; init; } = Array.Empty<string>();
public object? this[string propertyName] => GetType()
.GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance)?
.GetValue(this, null);
}
}

View File

@@ -9,6 +9,8 @@ using DigitalData.Core.API;
using DigitalData.UserManager.API.Controllers;
using DigitalData.UserManager.Application.Services;
using Microsoft.Data.SqlClient;
using System.Reflection.Metadata;
using DigitalData.UserManager.API.Models;
var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
logger.Debug("init main");
@@ -77,7 +79,9 @@ try {
builder.Services.AddDirectorySearchService();
builder.Services.AddCookieBasedLocalizer();
builder.ConfigureBySection<Constants>();
var app = builder.Build();
cnn_str = new(() =>

View File

@@ -73,5 +73,11 @@
},
// Delete below in production
"UseEncryptor": true,
"UseSwagger": true
"UseSwagger": true,
"Constants": {
"UserLanguages": [
"de-DE",
"en-US"
]
}
}