From 9690e01fa542ba9c325d8e9a804f8f86c55b887a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=B6rner?= Date: Sat, 21 Jun 2025 11:15:43 +0200 Subject: [PATCH 01/14] Improve UX with offcanvas --- .../rbac-widget/rbac-widget.component.ts | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/Turnierplan.App/Client/src/app/portal/components/rbac-widget/rbac-widget.component.ts b/src/Turnierplan.App/Client/src/app/portal/components/rbac-widget/rbac-widget.component.ts index ba95cf8c..becf850d 100644 --- a/src/Turnierplan.App/Client/src/app/portal/components/rbac-widget/rbac-widget.component.ts +++ b/src/Turnierplan.App/Client/src/app/portal/components/rbac-widget/rbac-widget.component.ts @@ -1,6 +1,9 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { NgbOffcanvas } from '@ng-bootstrap/ng-bootstrap'; +import { NgbOffcanvas, NgbOffcanvasRef } from '@ng-bootstrap/ng-bootstrap'; import { RbacOffcanvasComponent } from '../rbac-offcanvas/rbac-offcanvas.component'; +import { NavigationStart, Router } from '@angular/router'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { filter } from 'rxjs/operators'; interface IRbacWidgetTarget { name: string; @@ -25,19 +28,41 @@ export class RbacWidgetComponent { @Output() public errorOccured = new EventEmitter(); - constructor(private readonly offcanvasService: NgbOffcanvas) {} + private offcanvas?: NgbOffcanvasRef; + + constructor( + private readonly offcanvasService: NgbOffcanvas, + private readonly router: Router + ) { + this.router.events + .pipe( + takeUntilDestroyed(), + filter((event) => event instanceof NavigationStart) + ) + .subscribe({ + next: () => { + this.offcanvas?.close(); + } + }); + } protected buttonClicked(): void { - const ref = this.offcanvasService.open(RbacOffcanvasComponent, { position: 'end' }); - const component = ref.componentInstance as RbacOffcanvasComponent; + if (this.offcanvas) { + return; + } + + this.offcanvas = this.offcanvasService.open(RbacOffcanvasComponent, { position: 'end' }); + const component = this.offcanvas.componentInstance as RbacOffcanvasComponent; component.error$.subscribe({ next: (value) => { - ref.close(); + this.offcanvas?.close(); this.errorOccured.emit(value); } }); component.setTarget(this.target); + + this.offcanvas.hidden.subscribe({ next: () => (this.offcanvas = undefined) }); } } From 1105948d4dd7b57155ac694f295f33d01f29b3f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=B6rner?= Date: Sat, 21 Jun 2025 11:18:33 +0200 Subject: [PATCH 02/14] Add TODO + fix UX in admin page, too --- .../rbac-widget/rbac-widget.component.ts | 6 ------ .../administration-page.component.ts | 16 +++++++++++++++- src/Turnierplan.App/Helpers/DeletionHelper.cs | 1 + 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Turnierplan.App/Client/src/app/portal/components/rbac-widget/rbac-widget.component.ts b/src/Turnierplan.App/Client/src/app/portal/components/rbac-widget/rbac-widget.component.ts index becf850d..e86989b2 100644 --- a/src/Turnierplan.App/Client/src/app/portal/components/rbac-widget/rbac-widget.component.ts +++ b/src/Turnierplan.App/Client/src/app/portal/components/rbac-widget/rbac-widget.component.ts @@ -47,10 +47,6 @@ export class RbacWidgetComponent { } protected buttonClicked(): void { - if (this.offcanvas) { - return; - } - this.offcanvas = this.offcanvasService.open(RbacOffcanvasComponent, { position: 'end' }); const component = this.offcanvas.componentInstance as RbacOffcanvasComponent; @@ -62,7 +58,5 @@ export class RbacWidgetComponent { }); component.setTarget(this.target); - - this.offcanvas.hidden.subscribe({ next: () => (this.offcanvas = undefined) }); } } diff --git a/src/Turnierplan.App/Client/src/app/portal/pages/administration-page/administration-page.component.ts b/src/Turnierplan.App/Client/src/app/portal/pages/administration-page/administration-page.component.ts index ecbda077..de138961 100644 --- a/src/Turnierplan.App/Client/src/app/portal/pages/administration-page/administration-page.component.ts +++ b/src/Turnierplan.App/Client/src/app/portal/pages/administration-page/administration-page.component.ts @@ -9,6 +9,8 @@ import { NotificationService } from '../../../core/services/notification.service import { PageFrameNavigationTab } from '../../components/page-frame/page-frame.component'; import { LoadingState } from '../../directives/loading-state/loading-state.directive'; import { TitleService } from '../../services/title.service'; +import { NavigationStart, Router } from '@angular/router'; +import { filter } from 'rxjs/operators'; @Component({ standalone: false, @@ -35,9 +37,21 @@ export class AdministrationPageComponent implements OnInit { private readonly titleService: TitleService, private readonly authenticationService: AuthenticationService, private readonly offcanvasService: NgbOffcanvas, - private readonly notificationService: NotificationService + private readonly notificationService: NotificationService, + private readonly router: Router ) { this.authenticationService.authentication$.pipe(takeUntilDestroyed()).subscribe((userInfo) => (this.currentUserId = userInfo.id)); + + this.router.events + .pipe( + takeUntilDestroyed(), + filter((event) => event instanceof NavigationStart) + ) + .subscribe({ + next: () => { + this.currentOffcanvas?.close(); + } + }); } public ngOnInit(): void { diff --git a/src/Turnierplan.App/Helpers/DeletionHelper.cs b/src/Turnierplan.App/Helpers/DeletionHelper.cs index 66bef579..d1c1b1b4 100644 --- a/src/Turnierplan.App/Helpers/DeletionHelper.cs +++ b/src/Turnierplan.App/Helpers/DeletionHelper.cs @@ -45,6 +45,7 @@ public DeletionHelper( public async Task DeleteUserAsync(User user, CancellationToken cancellationToken) { // TODO: Decide how to handle this (there is no longer a 1-n relation between user and organisation) + // When this is decided: Update the information text on the "delete user" screen in the frontend // foreach (var organization in user.Organizations.ToList()) // ToList() to avoid invalid operation exception // { From 3849f68aceacc5a9216711a30a71ab8167fd4be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=B6rner?= Date: Wed, 25 Jun 2025 17:07:49 +0200 Subject: [PATCH 03/14] Add tooltip for scope type icon --- src/Turnierplan.App/Client/src/app/i18n/de.ts | 4 ++++ .../components/rbac-offcanvas/rbac-offcanvas.component.html | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Turnierplan.App/Client/src/app/i18n/de.ts b/src/Turnierplan.App/Client/src/app/i18n/de.ts index 57ef4e1a..def69f79 100644 --- a/src/Turnierplan.App/Client/src/app/i18n/de.ts +++ b/src/Turnierplan.App/Client/src/app/i18n/de.ts @@ -945,15 +945,19 @@ export const de = { InheritedTooltip: 'Diese Rollenzuweisung existiert implizit aufgrund der Zugehörigkeit zu einer anderen Resource', ScopeType: { Folder: { + Tooltip: 'Ordner', NotInherited: 'Zuweisung liegt auf diesem Ordner' }, Organization: { + Tooltip: 'Organisation', NotInherited: 'Zuweisung liegt auf dieser Organisation' }, Tournament: { + Tooltip: 'Turnier', NotInherited: 'Zuweisung liegt auf diesem Turnier' }, Venue: { + Tooltip: 'Spielstätte', NotInherited: 'Zuweisung liegt auf dieser Spielstätte' } }, diff --git a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html index d28ed5a3..fad52fec 100644 --- a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html +++ b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html @@ -7,7 +7,7 @@ } @else {
- + {{ target.name }} From 03cb5c9dfde33d324c99013270ad027dcf25e04a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=B6rner?= Date: Wed, 25 Jun 2025 17:14:29 +0200 Subject: [PATCH 04/14] Hide table when creating new role assignment --- src/Turnierplan.App/Client/src/app/i18n/de.ts | 5 +- .../rbac-offcanvas.component.html | 140 ++++++++++-------- .../rbac-offcanvas.component.ts | 10 +- 3 files changed, 93 insertions(+), 62 deletions(-) diff --git a/src/Turnierplan.App/Client/src/app/i18n/de.ts b/src/Turnierplan.App/Client/src/app/i18n/de.ts index def69f79..e1f9eae4 100644 --- a/src/Turnierplan.App/Client/src/app/i18n/de.ts +++ b/src/Turnierplan.App/Client/src/app/i18n/de.ts @@ -921,7 +921,10 @@ export const de = { RbacManagement: { Title: 'Zugriff verwalten', ButtonLabel: 'Verwalten', - OffcanvasTitle: 'Rollenzuweisungen bearbeiten', + OffcanvasTitle: { + Default: 'Rollenzuweisungen bearbeiten', + Creating: 'Rollenzuweisungen hinzufügen' + }, Loading: 'Rollenzuweisungen werden geladen', NewRoleAssignment: 'Neue Rollenzuweisung', RoleName: { diff --git a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html index fad52fec..5dfc7c4c 100644 --- a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html +++ b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html @@ -1,5 +1,9 @@
-
+
@if (isLoadingRoleAssignments) {
@@ -12,75 +16,91 @@ {{ target.name }} - + @if (isCreatingRoleAssignment) { + + } @else { + + }
- - - @for (group of roleAssignments | keyvalue; track group.key) { - - - + @if (isCreatingRoleAssignment) { + + } @else { +
- - -
+ + @for (group of roleAssignments | keyvalue; track group.key) { + + + - @for (assignment of group.value; track assignment.id) { - - + - + + + } } - } - -
+ + +
-
-
- @switch (assignment.principal.kind) { - @case (PrincipalKind.ApiKey) { - + @for (assignment of group.value; track assignment.id) { +
+
+
+ @switch (assignment.principal.kind) { + @case (PrincipalKind.ApiKey) { + + } + @case (PrincipalKind.User) { + + } } - @case (PrincipalKind.User) { - + + {{ assignment.principal.principalId }} + @if (canDeleteAssignment(assignment)) { + + } - } - - {{ assignment.principal.principalId }} - @if (canDeleteAssignment(assignment)) { - - - } -
- @if (assignment.isInherited) { - - } @else { -
- - + @if (assignment.isInherited) { + + } @else { +
+ + +
+ } +
+ + {{ assignment.id }} + · + + {{ assignment.createdAt | translateDate }}
- } -
- - {{ assignment.id }} - · - - {{ assignment.createdAt | translateDate }}
-
-
+ + - @if (roleAssignmentCount > 1) { -
- - {{ roleAssignmentCount }} -
+ @if (roleAssignmentCount > 1) { +
+ + {{ roleAssignmentCount }} +
+ } } }
diff --git a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts index 52f12d92..5deb8e35 100644 --- a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts +++ b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts @@ -20,8 +20,8 @@ export class RbacOffcanvasComponent implements OnDestroy { protected isLoadingRoleAssignments = false; protected roleAssignments: { [key: string]: RoleAssignmentDto[] } = {}; protected roleAssignmentCount: number = 0; - protected scopeTranslationKey: string = ''; + protected isCreatingRoleAssignment = false; private readonly errorSubject$ = new Subject(); private targetIsOrganization: boolean = false; @@ -137,4 +137,12 @@ export class RbacOffcanvasComponent implements OnDestroy { name: scopeName }); } + + protected switchCreatingRoleAssignment(target: boolean): void { + this.isCreatingRoleAssignment = target; + + if (target) { + // FIXME: Reset form + } + } } From c2f55978bb70d38c67faa818c2734be735ab09c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=B6rner?= Date: Wed, 25 Jun 2025 17:23:16 +0200 Subject: [PATCH 05/14] Revert "Hide table when creating new role assignment" This reverts commit 03cb5c9dfde33d324c99013270ad027dcf25e04a. --- src/Turnierplan.App/Client/src/app/i18n/de.ts | 5 +- .../rbac-offcanvas.component.html | 140 ++++++++---------- .../rbac-offcanvas.component.ts | 10 +- 3 files changed, 62 insertions(+), 93 deletions(-) diff --git a/src/Turnierplan.App/Client/src/app/i18n/de.ts b/src/Turnierplan.App/Client/src/app/i18n/de.ts index e1f9eae4..def69f79 100644 --- a/src/Turnierplan.App/Client/src/app/i18n/de.ts +++ b/src/Turnierplan.App/Client/src/app/i18n/de.ts @@ -921,10 +921,7 @@ export const de = { RbacManagement: { Title: 'Zugriff verwalten', ButtonLabel: 'Verwalten', - OffcanvasTitle: { - Default: 'Rollenzuweisungen bearbeiten', - Creating: 'Rollenzuweisungen hinzufügen' - }, + OffcanvasTitle: 'Rollenzuweisungen bearbeiten', Loading: 'Rollenzuweisungen werden geladen', NewRoleAssignment: 'Neue Rollenzuweisung', RoleName: { diff --git a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html index 5dfc7c4c..fad52fec 100644 --- a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html +++ b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html @@ -1,9 +1,5 @@
-
+
@if (isLoadingRoleAssignments) {
@@ -16,91 +12,75 @@ {{ target.name }} - @if (isCreatingRoleAssignment) { - - } @else { - - } +
- @if (isCreatingRoleAssignment) { - - } @else { - - - @for (group of roleAssignments | keyvalue; track group.key) { - - - +
- - -
+ + @for (group of roleAssignments | keyvalue; track group.key) { + + + - @for (assignment of group.value; track assignment.id) { - - + - - } + + + } - -
+ + +
-
-
- @switch (assignment.principal.kind) { - @case (PrincipalKind.ApiKey) { - - } - @case (PrincipalKind.User) { - - } + @for (assignment of group.value; track assignment.id) { +
+
+
+ @switch (assignment.principal.kind) { + @case (PrincipalKind.ApiKey) { + } - - {{ assignment.principal.principalId }} - @if (canDeleteAssignment(assignment)) { - - + @case (PrincipalKind.User) { + } -
- @if (assignment.isInherited) { - - } @else { -
- - -
} -
- - {{ assignment.id }} - · - - {{ assignment.createdAt | translateDate }} + + {{ assignment.principal.principalId }} + @if (canDeleteAssignment(assignment)) { + + + } +
+ @if (assignment.isInherited) { + + } @else { +
+ +
+ } +
+ + {{ assignment.id }} + · + + {{ assignment.createdAt | translateDate }}
-
+ } + + - @if (roleAssignmentCount > 1) { -
- - {{ roleAssignmentCount }} -
- } + @if (roleAssignmentCount > 1) { +
+ + {{ roleAssignmentCount }} +
} }
diff --git a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts index 5deb8e35..52f12d92 100644 --- a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts +++ b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts @@ -20,8 +20,8 @@ export class RbacOffcanvasComponent implements OnDestroy { protected isLoadingRoleAssignments = false; protected roleAssignments: { [key: string]: RoleAssignmentDto[] } = {}; protected roleAssignmentCount: number = 0; + protected scopeTranslationKey: string = ''; - protected isCreatingRoleAssignment = false; private readonly errorSubject$ = new Subject(); private targetIsOrganization: boolean = false; @@ -137,12 +137,4 @@ export class RbacOffcanvasComponent implements OnDestroy { name: scopeName }); } - - protected switchCreatingRoleAssignment(target: boolean): void { - this.isCreatingRoleAssignment = target; - - if (target) { - // FIXME: Reset form - } - } } From 90d06bdd0b31b23481c2990d3bd49985c4983425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=B6rner?= Date: Fri, 27 Jun 2025 12:55:51 +0200 Subject: [PATCH 06/14] Add new (empty) modal for adding role assignment --- .../add-role-assignment.component.html | 1 + .../add-role-assignment.component.ts | 7 +++++++ .../rbac-offcanvas/rbac-offcanvas.component.html | 6 +++++- .../rbac-offcanvas/rbac-offcanvas.component.ts | 14 +++++++++++++- .../Client/src/app/portal/portal.module.ts | 4 +++- 5 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.html create mode 100644 src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.ts diff --git a/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.html b/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.html new file mode 100644 index 00000000..837880b2 --- /dev/null +++ b/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.html @@ -0,0 +1 @@ +

add-role-assignment works!

diff --git a/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.ts b/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.ts new file mode 100644 index 00000000..86988f1a --- /dev/null +++ b/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + standalone: false, + templateUrl: './add-role-assignment.component.html' +}) +export class AddRoleAssignmentComponent {} diff --git a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html index fad52fec..1d7a64c1 100644 --- a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html +++ b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.html @@ -12,7 +12,11 @@ {{ target.name }} - +
diff --git a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts index 52f12d92..43fa476a 100644 --- a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts +++ b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts @@ -2,6 +2,9 @@ import { Component, OnDestroy } from '@angular/core'; import { finalize, Observable, Subject } from 'rxjs'; import { PrincipalKind, Role, RoleAssignmentDto, RoleAssignmentsService } from '../../../api'; import { NotificationService } from '../../../core/services/notification.service'; +import { DocumentCopyComponent } from '../document-copy/document-copy.component'; +import { AddRoleAssignmentComponent } from '../add-role-assignment/add-role-assignment.component'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; interface IRbacOffcanvasTarget { name: string; @@ -28,7 +31,8 @@ export class RbacOffcanvasComponent implements OnDestroy { constructor( private readonly roleAssignmentsService: RoleAssignmentsService, - private readonly notificationService: NotificationService + private readonly notificationService: NotificationService, + private readonly modalService: NgbModal ) {} public get error$(): Observable { @@ -137,4 +141,12 @@ export class RbacOffcanvasComponent implements OnDestroy { name: scopeName }); } + + protected showAddRoleAssignmentDialog(): void { + const ref = this.modalService.open(AddRoleAssignmentComponent, { + size: 'lg', + fullscreen: 'lg', + centered: true + }); + } } diff --git a/src/Turnierplan.App/Client/src/app/portal/portal.module.ts b/src/Turnierplan.App/Client/src/app/portal/portal.module.ts index 302df2e2..13fb9836 100644 --- a/src/Turnierplan.App/Client/src/app/portal/portal.module.ts +++ b/src/Turnierplan.App/Client/src/app/portal/portal.module.ts @@ -81,6 +81,7 @@ import { BaseChartDirective, provideCharts, withDefaultRegisterables } from 'ng2 import { QRCodeComponent } from 'angularx-qrcode'; import { RbacWidgetComponent } from './components/rbac-widget/rbac-widget.component'; import { RbacOffcanvasComponent } from './components/rbac-offcanvas/rbac-offcanvas.component'; +import { AddRoleAssignmentComponent } from './components/add-role-assignment/add-role-assignment.component'; const routes: Routes = [ { @@ -223,7 +224,8 @@ const routes: Routes = [ CreateUserComponent, BadgeComponent, RbacWidgetComponent, - RbacOffcanvasComponent + RbacOffcanvasComponent, + AddRoleAssignmentComponent ], imports: [ CommonModule, From 77b4a21f0dc452fcd12783fb2f9c3c823e262172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=B6rner?= Date: Fri, 27 Jun 2025 13:16:21 +0200 Subject: [PATCH 07/14] Add steps inside the new dialog --- src/Turnierplan.App/Client/src/app/i18n/de.ts | 13 +++++- .../add-role-assignment.component.html | 41 ++++++++++++++++++- .../add-role-assignment.component.scss | 3 ++ .../add-role-assignment.component.ts | 38 ++++++++++++++++- .../rbac-offcanvas.component.ts | 4 +- 5 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.scss diff --git a/src/Turnierplan.App/Client/src/app/i18n/de.ts b/src/Turnierplan.App/Client/src/app/i18n/de.ts index def69f79..63e2edce 100644 --- a/src/Turnierplan.App/Client/src/app/i18n/de.ts +++ b/src/Turnierplan.App/Client/src/app/i18n/de.ts @@ -961,9 +961,20 @@ export const de = { NotInherited: 'Zuweisung liegt auf dieser Spielstätte' } }, - SuccessToast: { + DeletedSuccessToast: { Title: 'Rollenzuweisung gelöscht', Message: 'Die Rollenzuweisung wurde erfolgreich gelöscht.' + }, + AddRoleAssignment: { + Title: 'Rollenzuweisung hinzufügen', + PreviousStep: 'Zurück', + NextStep: 'Weiter', + Confirm: 'Erstellen', + StepTitle: { + SelectRole: 'Rolle selektieren', + SelectPrincipal: 'Prinzipal selektieren', + Confirm: 'Prüfen und bestätigen' + } } } } diff --git a/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.html b/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.html index 837880b2..0b089a48 100644 --- a/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.html +++ b/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.html @@ -1 +1,40 @@ -

add-role-assignment works!

+ + + diff --git a/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.scss b/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.scss new file mode 100644 index 00000000..c0aa26cc --- /dev/null +++ b/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.scss @@ -0,0 +1,3 @@ +.modal-body { + height: 20em; +} diff --git a/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.ts b/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.ts index 86988f1a..3c09cc6b 100644 --- a/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.ts +++ b/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.ts @@ -1,7 +1,41 @@ import { Component } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; + +type Step = 'SelectRole' | 'SelectPrincipal' | 'Confirm'; @Component({ standalone: false, - templateUrl: './add-role-assignment.component.html' + templateUrl: './add-role-assignment.component.html', + styleUrl: './add-role-assignment.component.scss' }) -export class AddRoleAssignmentComponent {} +export class AddRoleAssignmentComponent { + protected step: Step = 'SelectRole'; + + constructor(protected readonly modal: NgbActiveModal) {} + + protected previousStep(): void { + switch (this.step) { + case 'SelectRole': + case 'SelectPrincipal': + this.step = 'SelectRole'; + break; + case 'Confirm': + this.step = 'SelectPrincipal'; + break; + } + } + + protected nextStep(): void { + switch (this.step) { + case 'SelectRole': + this.step = 'SelectPrincipal'; + break; + case 'SelectPrincipal': + case 'Confirm': + this.step = 'Confirm'; + break; + } + } + + protected confirm(): void {} +} diff --git a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts index 43fa476a..c3f6523c 100644 --- a/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts +++ b/src/Turnierplan.App/Client/src/app/portal/components/rbac-offcanvas/rbac-offcanvas.component.ts @@ -112,8 +112,8 @@ export class RbacOffcanvasComponent implements OnDestroy { this.notificationService.showNotification( 'success', - 'Portal.RbacManagement.SuccessToast.Title', - 'Portal.RbacManagement.SuccessToast.Message' + 'Portal.RbacManagement.DeletedSuccessToast.Title', + 'Portal.RbacManagement.DeletedSuccessToast.Message' ); }, error: (error) => { From 3e9918d028a5b66c1fef95a3a7d44f75b5462b37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20H=C3=B6rner?= Date: Fri, 27 Jun 2025 13:27:09 +0200 Subject: [PATCH 08/14] Implement role selection --- .../add-role-assignment.component.html | 26 ++++++++++++++++++- .../add-role-assignment.component.ts | 9 +++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.html b/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.html index 0b089a48..5861d087 100644 --- a/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.html +++ b/src/Turnierplan.App/Client/src/app/portal/components/add-role-assignment/add-role-assignment.component.html @@ -3,7 +3,7 @@
+ + @for (role of availableRoles; track role) { + + + + + } + +
+
+
+
+ +
+ } + @case ('SelectPrincipal') {} + @case ('Confirm') {} + } @switch (step) { @@ -38,60 +34,48 @@