@yuuvis/user-management-app 1.2.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,52 +1,56 @@
1
- import { CommonModule } from '@angular/common';
2
1
  import * as i0 from '@angular/core';
3
2
  import { inject, Component, Injectable, signal, Input, linkedSignal, input, output, computed, effect, Inject, HostBinding, ViewChild } from '@angular/core';
4
- import * as i1 from '@angular/router';
5
- import { RouterModule } from '@angular/router';
6
- import * as i2 from '@yuuvis/client-core';
7
- import { TranslateService, TranslateModule, BackendService, ApiBase, Logger, NotificationService, UserService } from '@yuuvis/client-core';
3
+ import * as i3 from '@angular/router';
4
+ import { Router, ActivatedRoute, NavigationEnd, RouterModule } from '@angular/router';
5
+ import * as i1 from '@angular/material/button-toggle';
6
+ import { MatButtonToggleModule } from '@angular/material/button-toggle';
7
+ import * as i2 from '@angular/material/tooltip';
8
+ import { MatTooltipModule } from '@angular/material/tooltip';
9
+ import { filter } from 'rxjs/operators';
8
10
  import { Title } from '@angular/platform-browser';
11
+ import { TranslateService, TranslatePipe, BackendService, ApiBase, Logger, NotificationService, UserService } from '@yuuvis/client-core';
12
+ import * as i4 from '@yuuvis/material/panes';
13
+ import { YmtPanesModule } from '@yuuvis/material/panes';
14
+ import * as i5 from '@yuuvis/client-shell';
15
+ import { YuvClientShellModule } from '@yuuvis/client-shell';
9
16
  import { ShellService } from '@yuuvis/client-shell-core';
10
- import * as i2$1 from '@angular/material/button';
17
+ import * as i1$3 from '@angular/common';
18
+ import { CommonModule } from '@angular/common';
19
+ import * as i2$2 from '@angular/material/button';
11
20
  import { MatButtonModule } from '@angular/material/button';
12
21
  import { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog';
13
22
  import * as i1$2 from '@angular/material/icon';
14
23
  import { MatIconModule } from '@angular/material/icon';
15
- import * as i2$2 from '@angular/material/paginator';
24
+ import * as i2$3 from '@angular/material/paginator';
16
25
  import { MatPaginatorModule } from '@angular/material/paginator';
17
26
  import { MatSortModule } from '@angular/material/sort';
18
- import * as i3$3 from '@angular/material/table';
27
+ import * as i3$4 from '@angular/material/table';
19
28
  import { MatTableModule } from '@angular/material/table';
20
29
  import { MatTabsModule } from '@angular/material/tabs';
21
- import * as i4 from '@angular/material/tooltip';
22
- import { MatTooltipModule } from '@angular/material/tooltip';
23
30
  import { SelectionModel } from '@angular/cdk/collections';
24
- import { ConfirmService, BusyOverlayDirective, DialogComponent, ClickDoubleDirective } from '@yuuvis/client-framework/common';
31
+ import { ConfirmService, BusyOverlayDirective, DialogComponent, ClickDoubleDirective } from '@yuuvis/client-components/common';
25
32
  import { SimpleSearchComponent } from '@yuuvis/client-framework/simple-search';
26
- import * as i9 from '@yuuvis/client-framework/overflow-menu';
27
- import { YuvOverflowMenuModule } from '@yuuvis/client-framework/overflow-menu';
28
- import * as i8 from '@yuuvis/client-shell';
29
- import { YuvClientShellModule } from '@yuuvis/client-shell';
33
+ import * as i8 from '@yuuvis/client-components/overflow-menu';
34
+ import { YuvOverflowMenuModule } from '@yuuvis/client-components/overflow-menu';
30
35
  import { YmtButtonDirective, YmtIconButtonDirective } from '@yuuvis/material';
31
- import * as i6 from '@yuuvis/material/layout';
36
+ import * as i5$1 from '@yuuvis/material/layout';
32
37
  import { YmtLayoutModule } from '@yuuvis/material/layout';
33
- import * as i7$1 from '@yuuvis/material/panes';
34
- import { YmtPanesModule } from '@yuuvis/material/panes';
35
38
  import { HttpParams } from '@angular/common/http';
36
39
  import { map, switchMap, of, forkJoin } from 'rxjs';
37
40
  import { MatCheckboxModule } from '@angular/material/checkbox';
38
- import * as i3 from '@angular/material/chips';
41
+ import * as i3$1 from '@angular/material/chips';
39
42
  import { MatChipsModule } from '@angular/material/chips';
40
43
  import * as i1$1 from '@angular/forms';
41
44
  import { ReactiveFormsModule, FormBuilder, FormControl, Validators } from '@angular/forms';
42
- import * as i3$1 from '@angular/material/form-field';
45
+ import * as i2$1 from '@angular/material/form-field';
43
46
  import { MatFormFieldModule } from '@angular/material/form-field';
44
- import * as i5 from '@angular/material/input';
47
+ import * as i3$2 from '@angular/material/input';
45
48
  import { MatInputModule } from '@angular/material/input';
46
49
  import * as i7 from '@angular/material/slide-toggle';
47
50
  import { MatSlideToggleModule } from '@angular/material/slide-toggle';
48
- import * as i3$2 from '@angular/material/list';
51
+ import * as i3$3 from '@angular/material/list';
49
52
  import { MatListModule } from '@angular/material/list';
53
+ import { MatCardModule } from '@angular/material/card';
50
54
 
51
55
  const APP_ID = 'io.yuuvis.app.user-management';
52
56
  const APP_ICONS = {
@@ -58,33 +62,52 @@ const APP_ICONS = {
58
62
  actionActivateUser: 'person_check',
59
63
  actionDeactivateUser: 'person_off',
60
64
  actionDeleteUser: 'delete',
65
+ actionEditGroup: 'edit',
61
66
  };
62
67
 
63
68
  class YuvUserManagementComponent {
64
69
  #shell = inject(ShellService);
65
70
  #titleService = inject(Title);
66
71
  #translateService = inject(TranslateService);
72
+ #router = inject(Router);
73
+ #activatedRoute = inject(ActivatedRoute);
67
74
  #app = this.#shell.getApp(APP_ID);
68
75
  appName = this.#app?.title;
69
- appIcon = this.#app?.iconName;
76
+ views = [
77
+ { id: 'users', title: 'yuv.app.user-management.navigation.users.label', link: 'users', tooltip: 'yuv.app.user-management.navigation.users.tooltip' },
78
+ { id: 'groups', title: 'yuv.app.user-management.navigation.groups.label', link: 'groups', tooltip: 'yuv.app.user-management.navigation.groups.tooltip' },
79
+ ];
80
+ activeLink = this.views[0].link;
81
+ constructor() {
82
+ this.#router.events.pipe(filter(e => e instanceof NavigationEnd)).subscribe((e) => {
83
+ const view = this.views.find(v => e.urlAfterRedirects.includes('/' + v.link));
84
+ if (view)
85
+ this.activeLink = view.link;
86
+ });
87
+ }
70
88
  ngOnInit() {
71
- // Browser-Tab-Titel lokalisiert setzen
72
89
  const translatedTitle = this.appName.startsWith('yuv.')
73
90
  ? this.#translateService.instant(this.appName)
74
91
  : this.appName;
75
92
  this.#titleService.setTitle(translatedTitle);
76
93
  }
77
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: YuvUserManagementComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
78
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: YuvUserManagementComponent, isStandalone: true, selector: "ymusrmgmt-root", ngImport: i0, template: "<section class=\"usrmgmt-main__content\" [attr.aria-label]=\"'yuv.app.user-management.content.aria.label' | translate\">\n <router-outlet></router-outlet>\n</section>\n\n<router-outlet name=\"modal\"></router-outlet>\n", styles: [":host{display:flex;flex-flow:column;height:100%}:host .usrmgmt-main__content{flex:1;overflow-y:hidden}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] });
94
+ navigate(link) {
95
+ this.#router.navigate([link], { relativeTo: this.#activatedRoute });
96
+ }
97
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: YuvUserManagementComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
98
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: YuvUserManagementComponent, isStandalone: true, selector: "ymusrmgmt-root", ngImport: i0, template: "<ng-template yuvAppHeaderSlot=\"actions\">\n <mat-button-toggle-group [value]=\"activeLink\" (change)=\"navigate($event.value)\" hideSingleSelectionIndicator>\n @for (view of views; track view.id) {\n <mat-button-toggle [value]=\"view.link\" [matTooltip]=\"view.tooltip | translate\">{{ view.title | translate }}</mat-button-toggle>\n }\n </mat-button-toggle-group>\n</ng-template>\n\n<ymt-pane class=\"usrmgmt-main__content\" [attr.aria-label]=\"'yuv.app.user-management.content.aria.label' | translate\">\n <ymt-pane-body>\n <router-outlet></router-outlet>\n </ymt-pane-body>\n</ymt-pane>\n\n<router-outlet name=\"modal\"></router-outlet>\n", styles: [":host{display:flex;flex-flow:column;height:100%}:host .usrmgmt-main__content{flex:1;overflow-y:hidden;margin:1rem}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i1.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i1.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i3.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "ngmodule", type: YmtPanesModule }, { kind: "component", type: i4.YmtPaneComponent, selector: "ymt-pane", inputs: ["topBarActions", "busy", "noAnimation", "plain"] }, { kind: "component", type: i4.YmtPaneBodyComponent, selector: "ymt-pane-body" }, { kind: "ngmodule", type: YuvClientShellModule }, { kind: "directive", type: i5.YuvAppHeaderSlotDirective, selector: "ng-template[yuvAppHeaderSlot]", inputs: ["yuvAppHeaderSlot"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
79
99
  }
80
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: YuvUserManagementComponent, decorators: [{
100
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: YuvUserManagementComponent, decorators: [{
81
101
  type: Component,
82
102
  args: [{ selector: 'ymusrmgmt-root', standalone: true, imports: [
83
- CommonModule,
103
+ MatButtonToggleModule,
104
+ MatTooltipModule,
84
105
  RouterModule,
85
- TranslateModule,
86
- ], template: "<section class=\"usrmgmt-main__content\" [attr.aria-label]=\"'yuv.app.user-management.content.aria.label' | translate\">\n <router-outlet></router-outlet>\n</section>\n\n<router-outlet name=\"modal\"></router-outlet>\n", styles: [":host{display:flex;flex-flow:column;height:100%}:host .usrmgmt-main__content{flex:1;overflow-y:hidden}\n"] }]
87
- }] });
106
+ TranslatePipe,
107
+ YmtPanesModule,
108
+ YuvClientShellModule,
109
+ ], template: "<ng-template yuvAppHeaderSlot=\"actions\">\n <mat-button-toggle-group [value]=\"activeLink\" (change)=\"navigate($event.value)\" hideSingleSelectionIndicator>\n @for (view of views; track view.id) {\n <mat-button-toggle [value]=\"view.link\" [matTooltip]=\"view.tooltip | translate\">{{ view.title | translate }}</mat-button-toggle>\n }\n </mat-button-toggle-group>\n</ng-template>\n\n<ymt-pane class=\"usrmgmt-main__content\" [attr.aria-label]=\"'yuv.app.user-management.content.aria.label' | translate\">\n <ymt-pane-body>\n <router-outlet></router-outlet>\n </ymt-pane-body>\n</ymt-pane>\n\n<router-outlet name=\"modal\"></router-outlet>\n", styles: [":host{display:flex;flex-flow:column;height:100%}:host .usrmgmt-main__content{flex:1;overflow-y:hidden;margin:1rem}\n"] }]
110
+ }], ctorParameters: () => [] });
88
111
 
89
112
  class YuvUserManagementService {
90
113
  static DEFAULT_PAGE_SIZE = 15;
@@ -100,6 +123,15 @@ class YuvUserManagementService {
100
123
  return this.#backendService
101
124
  .get(`/tenant-management/api/idm/users?${filterParams}`, ApiBase.none);
102
125
  }
126
+ fetchGroups(page = 0, search) {
127
+ const filterParams = new HttpParams()
128
+ .set('page', page)
129
+ .set('size', YuvUserManagementService.DEFAULT_PAGE_SIZE)
130
+ .set('sort', 'name%2Casc')
131
+ .set('search', search || '');
132
+ return this.#backendService
133
+ .get(`/tenant-management/api/idm/groups?${filterParams}`, ApiBase.none);
134
+ }
103
135
  fetchAllRoles() {
104
136
  return this.#backendService
105
137
  .get(`/tenant-management/api/idm/roles`, ApiBase.none)
@@ -113,7 +145,7 @@ class YuvUserManagementService {
113
145
  .post(`/tenant-management/api/idm/users?${createParams}`, createUserRequest, ApiBase.none, { responseType: 'text' })
114
146
  .pipe(map((createdUserId) => createdUserId));
115
147
  }
116
- editUser(userId, updateUserRequest) {
148
+ updateUser(userId, updateUserRequest) {
117
149
  return this.#backendService
118
150
  .put(`/tenant-management/api/idm/users/${userId}`, updateUserRequest, ApiBase.none);
119
151
  }
@@ -134,6 +166,32 @@ class YuvUserManagementService {
134
166
  return of(false);
135
167
  }));
136
168
  }
169
+ createGroup(createGroupRequest) {
170
+ const createParams = new HttpParams();
171
+ return this.#backendService
172
+ .post(`/tenant-management/api/idm/groups?${createParams}`, createGroupRequest, ApiBase.none, { responseType: 'text' })
173
+ .pipe(map((createdGroupId) => createdGroupId));
174
+ }
175
+ updateGroup(groupId, updateGroupRequest) {
176
+ return this.#backendService
177
+ .put(`/tenant-management/api/idm/groups/${groupId}`, updateGroupRequest, ApiBase.none);
178
+ }
179
+ deleteGroup(group) {
180
+ return this.#confirmService
181
+ .confirm({
182
+ title: this.#translateService.instant('yuv.app.user-management.groups.action.delete.label'),
183
+ message: this.#translateService.instant('yuv.app.user-management.groups.action.delete.confirm.message', { name: group.name }),
184
+ })
185
+ .pipe(switchMap((confirmed) => {
186
+ if (confirmed) {
187
+ return this.#backendService
188
+ .delete(`/tenant-management/api/idm/groups/${group.id}`, ApiBase.none)
189
+ .pipe(map(() => true));
190
+ }
191
+ else
192
+ return of(false);
193
+ }));
194
+ }
137
195
  getUserDetails(id) {
138
196
  const queryParams = new HttpParams()
139
197
  .set('briefRepresentation', false);
@@ -152,10 +210,16 @@ class YuvUserManagementService {
152
210
  })));
153
211
  return combined$;
154
212
  }
155
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: YuvUserManagementService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
156
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: YuvUserManagementService, providedIn: 'root' });
213
+ getGroupDetails(id) {
214
+ const queryParams = new HttpParams()
215
+ .set('briefRepresentation', false);
216
+ return this.#backendService
217
+ .get(`/tenant-management/api/idm/groups/${id}?${queryParams}`, ApiBase.none);
218
+ }
219
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: YuvUserManagementService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
220
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: YuvUserManagementService, providedIn: 'root' });
157
221
  }
158
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: YuvUserManagementService, decorators: [{
222
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: YuvUserManagementService, decorators: [{
159
223
  type: Injectable,
160
224
  args: [{
161
225
  providedIn: 'root',
@@ -165,7 +229,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
165
229
  class UserDetailsComponent {
166
230
  userService;
167
231
  formBuilder;
168
- userDetails = signal(undefined);
232
+ userDetails = signal(undefined, ...(ngDevMode ? [{ debugName: "userDetails" }] : /* istanbul ignore next */ []));
169
233
  userDetailsForm;
170
234
  currentUserId;
171
235
  set userId(value) {
@@ -208,10 +272,10 @@ class UserDetailsComponent {
208
272
  enabled: [{ value: false, disabled: true }]
209
273
  });
210
274
  }
211
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: UserDetailsComponent, deps: [{ token: YuvUserManagementService }, { token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
212
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: UserDetailsComponent, isStandalone: true, selector: "ymusrmgmt-user-details", inputs: { userId: "userId" }, ngImport: i0, template: "@let currentUserDetails = userDetails();\n@if (currentUserDetails) {\n <form [formGroup]=\"userDetailsForm\" class=\"user-details-form\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{('yuv.app.user-management.users.object.property.id' | translate)}}</mat-label>\n <input matInput formControlName=\"id\" readonly>\n </mat-form-field>\n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.users.object.property.username' | translate)}}</mat-label>\n <input matInput formControlName=\"username\" readonly>\n <mat-icon matPrefix>account_box</mat-icon>\n </mat-form-field>\n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.users.object.property.email' | translate)}}</mat-label>\n <input matInput formControlName=\"email\" readonly>\n <mat-icon matPrefix>email</mat-icon>\n </mat-form-field> \n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.users.object.property.firstname' | translate)}}</mat-label>\n <input matInput formControlName=\"firstName\" readonly>\n </mat-form-field>\n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.users.object.property.lastname' | translate)}}</mat-label>\n <input matInput formControlName=\"lastName\" readonly>\n </mat-form-field>\n <mat-form-field class=\"groups-field\">\n <mat-label>{{('yuv.app.user-management.users.object.property.groups' | translate)}}</mat-label>\n <mat-chip-grid #groupChipGrid>\n @if (currentUserDetails.groups) {\n @for (group of currentUserDetails.groups.sort(); track group) {\n <mat-chip-row [editable]=\"false\"><div class=\"chip\">{{group}}</div></mat-chip-row>\n }\n }\n <input [matChipInputFor]=\"groupChipGrid\" readonly/>\n </mat-chip-grid>\n </mat-form-field>\n <mat-form-field class=\"roles-field\">\n <mat-label>{{('yuv.app.user-management.users.object.property.roles' | translate)}}</mat-label>\n <mat-chip-grid #roleChipGrid>\n @if (currentUserDetails.effectiveRoles) {\n @for (role of currentUserDetails.effectiveRoles; track role) {\n <mat-chip-row [editable]=\"false\" [disabled]=\"currentUserDetails.roles.indexOf(role) === -1\"><div class=\"chip\">{{role}}</div></mat-chip-row>\n }\n }\n <input [matChipInputFor]=\"roleChipGrid\" readonly/>\n </mat-chip-grid>\n </mat-form-field>\n <mat-slide-toggle formControlName=\"enabled\">\n {{ userDetailsForm.get('enabled')?.value ? ('yuv.app.user-management.users.object.property.enabled' | translate) :\n ('yuv.app.user-management.users.object.property.disabled' | translate) }}\n </mat-slide-toggle> \n </form>\n}", styles: [":host{height:100%;overflow:hidden;display:flex;flex-flow:column}:host .user-details-form{flex:1;overflow-y:auto;display:grid;align-items:start;align-content:start;gap:var(--ymt-spacing-m);padding:1rem}:host .user-details-form mat-chip-row{overflow:hidden}:host .user-details-form .groups-field mat-chip-grid,:host .user-details-form .roles-field mat-chip-grid{max-height:300px;overflow-y:auto;display:block}\n"], dependencies: [{ kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i3.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i3.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "component", type: i3.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$1.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] });
275
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UserDetailsComponent, deps: [{ token: YuvUserManagementService }, { token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
276
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UserDetailsComponent, isStandalone: true, selector: "ymusrmgmt-user-details", inputs: { userId: "userId" }, ngImport: i0, template: "@let currentUserDetails = userDetails();\n@if (currentUserDetails) {\n <form [formGroup]=\"userDetailsForm\" class=\"user-details-form\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{('yuv.app.user-management.users.object.property.id' | translate)}}</mat-label>\n <input matInput formControlName=\"id\" readonly>\n </mat-form-field>\n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.users.object.property.username' | translate)}}</mat-label>\n <input matInput formControlName=\"username\" readonly>\n <mat-icon matPrefix>account_box</mat-icon>\n </mat-form-field>\n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.users.object.property.email' | translate)}}</mat-label>\n <input matInput formControlName=\"email\" readonly>\n <mat-icon matPrefix>email</mat-icon>\n </mat-form-field> \n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.users.object.property.firstname' | translate)}}</mat-label>\n <input matInput formControlName=\"firstName\" readonly>\n </mat-form-field>\n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.users.object.property.lastname' | translate)}}</mat-label>\n <input matInput formControlName=\"lastName\" readonly>\n </mat-form-field>\n <mat-form-field class=\"groups-field\">\n <mat-label>{{('yuv.app.user-management.users.object.property.groups' | translate)}}</mat-label>\n <mat-chip-grid #groupChipGrid>\n @if (currentUserDetails.groups) {\n @for (group of currentUserDetails.groups.sort(); track group) {\n <mat-chip-row [editable]=\"false\"><div class=\"chip\">{{group}}</div></mat-chip-row>\n }\n }\n <input [matChipInputFor]=\"groupChipGrid\" readonly/>\n </mat-chip-grid>\n </mat-form-field>\n <mat-form-field class=\"roles-field\">\n <mat-label>{{('yuv.app.user-management.users.object.property.roles' | translate)}}</mat-label>\n <mat-chip-grid #roleChipGrid>\n @if (currentUserDetails.effectiveRoles) {\n @for (role of currentUserDetails.effectiveRoles; track role) {\n <mat-chip-row [editable]=\"false\" [disabled]=\"currentUserDetails.roles.indexOf(role) === -1\"><div class=\"chip\">{{role}}</div></mat-chip-row>\n }\n }\n <input [matChipInputFor]=\"roleChipGrid\" readonly/>\n </mat-chip-grid>\n </mat-form-field>\n <mat-slide-toggle formControlName=\"enabled\">\n {{ userDetailsForm.get('enabled')?.value ? ('yuv.app.user-management.users.object.property.enabled' | translate) :\n ('yuv.app.user-management.users.object.property.disabled' | translate) }}\n </mat-slide-toggle> \n </form>\n}", styles: [":host{height:100%;overflow:hidden;display:flex;flex-flow:column}:host .user-details-form{flex:1;overflow-y:auto;display:grid;align-items:start;align-content:start;gap:var(--ymt-spacing-m);padding:1rem}:host .user-details-form mat-chip-row{overflow:hidden}:host .user-details-form .groups-field mat-chip-grid,:host .user-details-form .roles-field mat-chip-grid{max-height:300px;overflow-y:auto;display:block}\n"], dependencies: [{ kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i3$1.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i3$1.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "component", type: i3$1.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
213
277
  }
214
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: UserDetailsComponent, decorators: [{
278
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UserDetailsComponent, decorators: [{
215
279
  type: Component,
216
280
  args: [{ selector: 'ymusrmgmt-user-details', imports: [
217
281
  MatChipsModule,
@@ -221,17 +285,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
221
285
  MatCheckboxModule,
222
286
  MatSlideToggleModule,
223
287
  ReactiveFormsModule,
224
- TranslateModule
288
+ TranslatePipe
225
289
  ], template: "@let currentUserDetails = userDetails();\n@if (currentUserDetails) {\n <form [formGroup]=\"userDetailsForm\" class=\"user-details-form\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{('yuv.app.user-management.users.object.property.id' | translate)}}</mat-label>\n <input matInput formControlName=\"id\" readonly>\n </mat-form-field>\n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.users.object.property.username' | translate)}}</mat-label>\n <input matInput formControlName=\"username\" readonly>\n <mat-icon matPrefix>account_box</mat-icon>\n </mat-form-field>\n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.users.object.property.email' | translate)}}</mat-label>\n <input matInput formControlName=\"email\" readonly>\n <mat-icon matPrefix>email</mat-icon>\n </mat-form-field> \n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.users.object.property.firstname' | translate)}}</mat-label>\n <input matInput formControlName=\"firstName\" readonly>\n </mat-form-field>\n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.users.object.property.lastname' | translate)}}</mat-label>\n <input matInput formControlName=\"lastName\" readonly>\n </mat-form-field>\n <mat-form-field class=\"groups-field\">\n <mat-label>{{('yuv.app.user-management.users.object.property.groups' | translate)}}</mat-label>\n <mat-chip-grid #groupChipGrid>\n @if (currentUserDetails.groups) {\n @for (group of currentUserDetails.groups.sort(); track group) {\n <mat-chip-row [editable]=\"false\"><div class=\"chip\">{{group}}</div></mat-chip-row>\n }\n }\n <input [matChipInputFor]=\"groupChipGrid\" readonly/>\n </mat-chip-grid>\n </mat-form-field>\n <mat-form-field class=\"roles-field\">\n <mat-label>{{('yuv.app.user-management.users.object.property.roles' | translate)}}</mat-label>\n <mat-chip-grid #roleChipGrid>\n @if (currentUserDetails.effectiveRoles) {\n @for (role of currentUserDetails.effectiveRoles; track role) {\n <mat-chip-row [editable]=\"false\" [disabled]=\"currentUserDetails.roles.indexOf(role) === -1\"><div class=\"chip\">{{role}}</div></mat-chip-row>\n }\n }\n <input [matChipInputFor]=\"roleChipGrid\" readonly/>\n </mat-chip-grid>\n </mat-form-field>\n <mat-slide-toggle formControlName=\"enabled\">\n {{ userDetailsForm.get('enabled')?.value ? ('yuv.app.user-management.users.object.property.enabled' | translate) :\n ('yuv.app.user-management.users.object.property.disabled' | translate) }}\n </mat-slide-toggle> \n </form>\n}", styles: [":host{height:100%;overflow:hidden;display:flex;flex-flow:column}:host .user-details-form{flex:1;overflow-y:auto;display:grid;align-items:start;align-content:start;gap:var(--ymt-spacing-m);padding:1rem}:host .user-details-form mat-chip-row{overflow:hidden}:host .user-details-form .groups-field mat-chip-grid,:host .user-details-form .roles-field mat-chip-grid{max-height:300px;overflow-y:auto;display:block}\n"] }]
226
290
  }], ctorParameters: () => [{ type: YuvUserManagementService }, { type: i1$1.FormBuilder }], propDecorators: { userId: [{
227
291
  type: Input
228
292
  }] } });
229
293
 
230
- const components$1 = [BusyOverlayDirective, YmtButtonDirective, DialogComponent];
231
- const modules$1 = [
294
+ const components$3 = [BusyOverlayDirective, YmtButtonDirective, DialogComponent];
295
+ const modules$3 = [
232
296
  CommonModule,
233
297
  ReactiveFormsModule,
234
- TranslateModule,
298
+ TranslatePipe,
235
299
  MatFormFieldModule,
236
300
  MatSlideToggleModule,
237
301
  MatInputModule
@@ -242,8 +306,8 @@ class CreateUserComponent {
242
306
  #dialogRef = inject((MatDialogRef));
243
307
  #translateService = inject(TranslateService);
244
308
  #logger = inject(Logger);
245
- busy = signal(false);
246
- error = signal(undefined);
309
+ busy = signal(false, ...(ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []));
310
+ error = signal(undefined, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
247
311
  username = new FormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(255), Validators.pattern('^[a-zA-Z0-9._-]*$')]);
248
312
  email = new FormControl('', [Validators.required, Validators.email]);
249
313
  firstname = new FormControl('', [Validators.minLength(1), Validators.maxLength(255), Validators.pattern("^[^#!<>&/%=;*§$()[\\]{}]*$")]);
@@ -256,13 +320,11 @@ class CreateUserComponent {
256
320
  lastname: this.lastname,
257
321
  enabled: this.enabled
258
322
  });
259
- changedInput = signal(undefined);
260
- disabledSubmit = linkedSignal({
261
- source: this.changedInput,
323
+ changedInput = signal(undefined, ...(ngDevMode ? [{ debugName: "changedInput" }] : /* istanbul ignore next */ []));
324
+ disabledSubmit = linkedSignal({ ...(ngDevMode ? { debugName: "disabledSubmit" } : /* istanbul ignore next */ {}), source: this.changedInput,
262
325
  computation: () => {
263
326
  return this.busy() || this.form.invalid;
264
- }
265
- });
327
+ } });
266
328
  createUser() {
267
329
  let createdUserId;
268
330
  const createParams = this.form.value;
@@ -317,26 +379,26 @@ class CreateUserComponent {
317
379
  this.changedInput.set(value);
318
380
  });
319
381
  }
320
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: CreateUserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
321
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: CreateUserComponent, isStandalone: true, selector: "ymusrmgmt-create-user", host: { properties: { "class.busy": "!busy()" } }, ngImport: i0, template: "<yuv-dialog [yuvBusyOverlay]=\"busy()\" [headertitel]=\"'yuv.app.user-management.users.action.create.label' | translate\">\n <main class=\"yuv-dialog-content\">\n <form [formGroup]=\"form\">\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.username\" | translate }}</mat-label>\n <input matInput [formControl]=\"username\" type=\"text\"/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.email\" | translate}}</mat-label>\n <input matInput [formControl]=\"email\" type=\"text\"/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.firstname\" | translate}}</mat-label>\n <input matInput [formControl]=\"firstname\" type=\"text\"/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.lastname\" | translate}}</mat-label>\n <input matInput [formControl]=\"lastname\" type=\"text\"/>\n </mat-form-field>\n <div class=\"yuv-form-field\" id=\"enabledPropDiv\">\n <mat-slide-toggle formControlName=\"enabled\">\n {{ form.get('enabled')?.value ? ('yuv.app.user-management.users.object.property.enabled' | translate) : ('yuv.app.user-management.users.object.property.disabled' | translate) }}\n </mat-slide-toggle>\n </div>\n @if (error()) {\n <p class=\"error\">{{ error() }}</p>\n }\n </form>\n </main>\n <footer>\n <button ymtButton=\"secondary\" [disabled]=\"busy()\" (click)=\"close()\">\n {{ \"yuv.app.user-management.users.action.button.cancel\" | translate }}\n </button>\n <button ymtButton=\"primary\" [disabled]=\"disabledSubmit()\" (click)=\"createUser()\">\n {{ 'yuv.app.user-management.users.action.button.create' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host{display:block;position:relative}:host main form{padding:var(--ymt-spacing-m)}:host main form .yuv-form-field{width:100%;margin:var(--ymt-spacing-xs) 0}:host main form .error{color:var(--ymt-on-danger-container);background-color:var(--ymt-danger-container);padding:var(--ymt-spacing-m);border-radius:var(--ymt-corner-xs)}:host main form #enabledPropDiv{display:flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay", "yuvBusyOverlayConfig", "yuvBusyError"], outputs: ["yuvBusyErrorDismiss"] }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }, { kind: "component", type: DialogComponent, selector: "yuv-dialog", inputs: ["headertitle", "headertitel"] }] });
382
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: CreateUserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
383
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: CreateUserComponent, isStandalone: true, selector: "ymusrmgmt-create-user", host: { properties: { "class.busy": "!busy()" } }, ngImport: i0, template: "<yuv-dialog [yuvBusyOverlay]=\"busy()\" [headertitel]=\"'yuv.app.user-management.users.action.create.label' | translate\">\n <main class=\"yuv-dialog-content\">\n <form [formGroup]=\"form\">\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.username\" | translate }}</mat-label>\n <input matInput [formControl]=\"username\" type=\"text\"/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.email\" | translate}}</mat-label>\n <input matInput [formControl]=\"email\" type=\"text\"/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.firstname\" | translate}}</mat-label>\n <input matInput [formControl]=\"firstname\" type=\"text\"/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.lastname\" | translate}}</mat-label>\n <input matInput [formControl]=\"lastname\" type=\"text\"/>\n </mat-form-field>\n <div class=\"yuv-form-field\" id=\"enabledPropDiv\">\n <mat-slide-toggle formControlName=\"enabled\">\n {{ form.get('enabled')?.value ? ('yuv.app.user-management.users.object.property.enabled' | translate) : ('yuv.app.user-management.users.object.property.disabled' | translate) }}\n </mat-slide-toggle>\n </div>\n @if (error()) {\n <p class=\"error\">{{ error() }}</p>\n }\n </form>\n </main>\n <footer>\n <button ymtButton=\"secondary\" [disabled]=\"busy()\" (click)=\"close()\">\n {{ \"yuv.app.user-management.users.action.button.cancel\" | translate }}\n </button>\n <button ymtButton=\"primary\" [disabled]=\"disabledSubmit()\" (click)=\"createUser()\">\n {{ 'yuv.app.user-management.users.action.button.create' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host{display:block;position:relative}:host main form{padding:var(--ymt-spacing-m)}:host main form .yuv-form-field{width:100%;margin:var(--ymt-spacing-xs) 0}:host main form .error{color:var(--ymt-on-danger-container);background-color:var(--ymt-danger-container);padding:var(--ymt-spacing-m);border-radius:var(--ymt-corner-xs)}:host main form #enabledPropDiv{display:flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay", "yuvBusyOverlayConfig", "yuvBusyError"], outputs: ["yuvBusyErrorDismiss"] }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }, { kind: "component", type: DialogComponent, selector: "yuv-dialog", inputs: ["headertitle", "headertitel"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
322
384
  }
323
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: CreateUserComponent, decorators: [{
385
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: CreateUserComponent, decorators: [{
324
386
  type: Component,
325
- args: [{ selector: 'ymusrmgmt-create-user', standalone: true, imports: [...modules$1, ...components$1], host: {
387
+ args: [{ selector: 'ymusrmgmt-create-user', standalone: true, imports: [...modules$3, ...components$3], host: {
326
388
  '[class.busy]': '!busy()',
327
389
  }, template: "<yuv-dialog [yuvBusyOverlay]=\"busy()\" [headertitel]=\"'yuv.app.user-management.users.action.create.label' | translate\">\n <main class=\"yuv-dialog-content\">\n <form [formGroup]=\"form\">\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.username\" | translate }}</mat-label>\n <input matInput [formControl]=\"username\" type=\"text\"/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.email\" | translate}}</mat-label>\n <input matInput [formControl]=\"email\" type=\"text\"/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.firstname\" | translate}}</mat-label>\n <input matInput [formControl]=\"firstname\" type=\"text\"/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.lastname\" | translate}}</mat-label>\n <input matInput [formControl]=\"lastname\" type=\"text\"/>\n </mat-form-field>\n <div class=\"yuv-form-field\" id=\"enabledPropDiv\">\n <mat-slide-toggle formControlName=\"enabled\">\n {{ form.get('enabled')?.value ? ('yuv.app.user-management.users.object.property.enabled' | translate) : ('yuv.app.user-management.users.object.property.disabled' | translate) }}\n </mat-slide-toggle>\n </div>\n @if (error()) {\n <p class=\"error\">{{ error() }}</p>\n }\n </form>\n </main>\n <footer>\n <button ymtButton=\"secondary\" [disabled]=\"busy()\" (click)=\"close()\">\n {{ \"yuv.app.user-management.users.action.button.cancel\" | translate }}\n </button>\n <button ymtButton=\"primary\" [disabled]=\"disabledSubmit()\" (click)=\"createUser()\">\n {{ 'yuv.app.user-management.users.action.button.create' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host{display:block;position:relative}:host main form{padding:var(--ymt-spacing-m)}:host main form .yuv-form-field{width:100%;margin:var(--ymt-spacing-xs) 0}:host main form .error{color:var(--ymt-on-danger-container);background-color:var(--ymt-danger-container);padding:var(--ymt-spacing-m);border-radius:var(--ymt-corner-xs)}:host main form #enabledPropDiv{display:flex;justify-content:center;align-items:center}\n"] }]
328
390
  }] });
329
391
 
330
392
  class EditUserRolesComponent {
331
- allRoles = input.required();
332
- assignedRoles = input.required();
393
+ allRoles = input.required(...(ngDevMode ? [{ debugName: "allRoles" }] : /* istanbul ignore next */ []));
394
+ assignedRoles = input.required(...(ngDevMode ? [{ debugName: "assignedRoles" }] : /* istanbul ignore next */ []));
333
395
  rolesChange = output();
334
- availableRoles = signal([]);
335
- userRoles = signal([]);
336
- selectedAvailable = signal([]);
337
- selectedAssigned = signal([]);
338
- canAssign = computed(() => this.selectedAvailable().length > 0);
339
- canRemove = computed(() => this.selectedAssigned().length > 0);
396
+ availableRoles = signal([], ...(ngDevMode ? [{ debugName: "availableRoles" }] : /* istanbul ignore next */ []));
397
+ userRoles = signal([], ...(ngDevMode ? [{ debugName: "userRoles" }] : /* istanbul ignore next */ []));
398
+ selectedAvailable = signal([], ...(ngDevMode ? [{ debugName: "selectedAvailable" }] : /* istanbul ignore next */ []));
399
+ selectedAssigned = signal([], ...(ngDevMode ? [{ debugName: "selectedAssigned" }] : /* istanbul ignore next */ []));
400
+ canAssign = computed(() => this.selectedAvailable().length > 0, ...(ngDevMode ? [{ debugName: "canAssign" }] : /* istanbul ignore next */ []));
401
+ canRemove = computed(() => this.selectedAssigned().length > 0, ...(ngDevMode ? [{ debugName: "canRemove" }] : /* istanbul ignore next */ []));
340
402
  constructor() {
341
403
  // Initialize internal state when inputs change
342
404
  effect(() => {
@@ -408,25 +470,25 @@ class EditUserRolesComponent {
408
470
  isAssignedSelected(role) {
409
471
  return this.selectedAssigned().includes(role);
410
472
  }
411
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: EditUserRolesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
412
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: EditUserRolesComponent, isStandalone: true, selector: "ymusrmgmt-edit-user-roles", inputs: { allRoles: { classPropertyName: "allRoles", publicName: "allRoles", isSignal: true, isRequired: true, transformFunction: null }, assignedRoles: { classPropertyName: "assignedRoles", publicName: "assignedRoles", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { rolesChange: "rolesChange" }, ngImport: i0, template: "<div class=\"role-selector\">\n <!-- Available Roles (Left) -->\n <div class=\"role-list-container\">\n <div class=\"role-list-header\">\n {{ 'yuv.app.user-management.users.roles.available' | translate }}\n </div>\n <mat-selection-list class=\"role-list\" #availableList hideSingleSelectionIndicator=\"true\">\n @for (role of availableRoles(); track role) {\n <mat-list-option \n [value]=\"role\" \n [selected]=\"isAvailableSelected(role)\"\n (click)=\"toggleAvailableRole(role)\">\n {{ role }}\n </mat-list-option>\n }\n @empty {\n <div class=\"empty-message\">\n {{ 'yuv.app.user-management.users.roles.noAvailable' | translate }}\n </div>\n }\n </mat-selection-list>\n </div>\n\n <!-- Control Buttons (Center) -->\n <div class=\"control-buttons\">\n <button \n mat-icon-button \n [disabled]=\"availableRoles().length === 0\"\n (click)=\"assignAllRoles()\"\n [title]=\"'yuv.app.user-management.users.roles.assignAll' | translate\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n <button \n mat-icon-button \n [disabled]=\"!canAssign()\"\n (click)=\"assignRoles()\"\n [title]=\"'yuv.app.user-management.users.roles.assign' | translate\">\n <mat-icon>chevron_right</mat-icon>\n </button>\n <button \n mat-icon-button \n [disabled]=\"!canRemove()\"\n (click)=\"removeRoles()\"\n [title]=\"'yuv.app.user-management.users.roles.remove' | translate\">\n <mat-icon>chevron_left</mat-icon>\n </button>\n <button \n mat-icon-button \n [disabled]=\"userRoles().length === 0\"\n (click)=\"removeAllRoles()\"\n [title]=\"'yuv.app.user-management.users.roles.removeAll' | translate\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n </div>\n\n <!-- Assigned Roles (Right) -->\n <div class=\"role-list-container\">\n <div class=\"role-list-header\">\n {{ 'yuv.app.user-management.users.roles.assigned' | translate }}\n </div>\n <mat-selection-list class=\"role-list\" #assignedList hideSingleSelectionIndicator=\"true\">\n @for (role of userRoles(); track role) {\n <mat-list-option \n [value]=\"role\" \n [selected]=\"isAssignedSelected(role)\"\n (click)=\"toggleAssignedRole(role)\">\n {{ role }}\n </mat-list-option>\n }\n @empty {\n <div class=\"empty-message\">\n {{ 'yuv.app.user-management.users.roles.noAssigned' | translate }}\n </div>\n }\n </mat-selection-list>\n </div>\n</div>\n", styles: [".role-selector{display:flex;gap:var(--ymt-spacing-m);align-items:stretch;min-height:300px;padding:var(--ymt-spacing-xs) 0}.role-list-container{flex:1;display:flex;flex-direction:column;border:var(--ymt-outline-width) solid var(--ymt-outline-variant);border-radius:var(--ymt-corner-xs);overflow:hidden;background-color:var(--ymt-surface-container-lowest);max-height:300px}.role-list-header{padding:var(--ymt-spacing-s) var(--ymt-spacing-m);background-color:var(--ymt-surface-container-high);color:var(--ymt-on-surface);font:var(--ymt-font-title-smallest);border-bottom:var(--ymt-outline-width) solid var(--ymt-outline-variant)}.role-list{flex:1;overflow-y:auto;min-height:0}.role-list ::ng-deep .mat-mdc-list-option{font:var(--ymt-font-body-subtle);min-height:var(--ymt-sizing-2xl)}.role-list ::ng-deep .mdc-list-item__primary-text{font:var(--ymt-font-body-subtle)}.role-list ::ng-deep .mdc-checkbox{display:none}.role-list ::ng-deep .mat-mdc-list-option[aria-selected=true]{background-color:var(--ymt-selection-background)!important}.role-list ::ng-deep .mat-mdc-list-option[aria-selected=true] .mdc-list-item__primary-text{color:var(--ymt-on-selection-background);font-weight:500}.role-list ::ng-deep .mat-mdc-list-option:hover:not([aria-selected=true]){background-color:var(--ymt-hover-background)}.control-buttons{display:flex;flex-direction:column;justify-content:center;gap:var(--ymt-spacing-xs)}.empty-message{padding:var(--ymt-spacing-m);text-align:center;color:var(--ymt-text-color-subtle);font:var(--ymt-font-body-subtle)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i3$2.MatSelectionList, selector: "mat-selection-list", inputs: ["color", "compareWith", "multiple", "hideSingleSelectionIndicator", "disabled"], outputs: ["selectionChange"], exportAs: ["matSelectionList"] }, { kind: "component", type: i3$2.MatListOption, selector: "mat-list-option", inputs: ["togglePosition", "checkboxPosition", "color", "value", "selected"], outputs: ["selectedChange"], exportAs: ["matListOption"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] });
473
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EditUserRolesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
474
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: EditUserRolesComponent, isStandalone: true, selector: "ymusrmgmt-edit-user-roles", inputs: { allRoles: { classPropertyName: "allRoles", publicName: "allRoles", isSignal: true, isRequired: true, transformFunction: null }, assignedRoles: { classPropertyName: "assignedRoles", publicName: "assignedRoles", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { rolesChange: "rolesChange" }, ngImport: i0, template: "<div class=\"role-selector\">\n <!-- Available Roles (Left) -->\n <div class=\"role-list-container\">\n <div class=\"role-list-header\">\n {{ 'yuv.app.user-management.users.roles.available' | translate }}\n </div>\n <mat-selection-list class=\"role-list\" #availableList hideSingleSelectionIndicator=\"true\">\n @for (role of availableRoles(); track role) {\n <mat-list-option \n [value]=\"role\" \n [selected]=\"isAvailableSelected(role)\"\n (click)=\"toggleAvailableRole(role)\">\n {{ role }}\n </mat-list-option>\n }\n @empty {\n <div class=\"empty-message\">\n {{ 'yuv.app.user-management.users.roles.noAvailable' | translate }}\n </div>\n }\n </mat-selection-list>\n </div>\n\n <!-- Control Buttons (Center) -->\n <div class=\"control-buttons\">\n <button \n mat-icon-button \n [disabled]=\"availableRoles().length === 0\"\n (click)=\"assignAllRoles()\"\n [title]=\"'yuv.app.user-management.users.roles.assignAll' | translate\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n <button \n mat-icon-button \n [disabled]=\"!canAssign()\"\n (click)=\"assignRoles()\"\n [title]=\"'yuv.app.user-management.users.roles.assign' | translate\">\n <mat-icon>chevron_right</mat-icon>\n </button>\n <button \n mat-icon-button \n [disabled]=\"!canRemove()\"\n (click)=\"removeRoles()\"\n [title]=\"'yuv.app.user-management.users.roles.remove' | translate\">\n <mat-icon>chevron_left</mat-icon>\n </button>\n <button \n mat-icon-button \n [disabled]=\"userRoles().length === 0\"\n (click)=\"removeAllRoles()\"\n [title]=\"'yuv.app.user-management.users.roles.removeAll' | translate\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n </div>\n\n <!-- Assigned Roles (Right) -->\n <div class=\"role-list-container\">\n <div class=\"role-list-header\">\n {{ 'yuv.app.user-management.users.roles.assigned' | translate }}\n </div>\n <mat-selection-list class=\"role-list\" #assignedList hideSingleSelectionIndicator=\"true\">\n @for (role of userRoles(); track role) {\n <mat-list-option \n [value]=\"role\" \n [selected]=\"isAssignedSelected(role)\"\n (click)=\"toggleAssignedRole(role)\">\n {{ role }}\n </mat-list-option>\n }\n @empty {\n <div class=\"empty-message\">\n {{ 'yuv.app.user-management.users.roles.noAssigned' | translate }}\n </div>\n }\n </mat-selection-list>\n </div>\n</div>\n", styles: [".role-selector{display:flex;gap:var(--ymt-spacing-m);align-items:stretch;min-height:300px;padding:var(--ymt-spacing-xs) 0}.role-list-container{flex:1;display:flex;flex-direction:column;border:var(--ymt-outline-width) solid var(--ymt-outline-variant);border-radius:var(--ymt-corner-xs);overflow:hidden;background-color:var(--ymt-surface-container-lowest);max-height:300px}.role-list-header{padding:var(--ymt-spacing-s) var(--ymt-spacing-m);background-color:var(--ymt-surface-container-high);color:var(--ymt-on-surface);font:var(--ymt-font-title-smallest);border-bottom:var(--ymt-outline-width) solid var(--ymt-outline-variant)}.role-list{flex:1;overflow-y:auto;min-height:0}.role-list ::ng-deep .mat-mdc-list-option{font:var(--ymt-font-body-subtle);min-height:var(--ymt-sizing-2xl)}.role-list ::ng-deep .mdc-list-item__primary-text{font:var(--ymt-font-body-subtle)}.role-list ::ng-deep .mdc-checkbox{display:none}.role-list ::ng-deep .mat-mdc-list-option[aria-selected=true]{background-color:var(--ymt-selection-background)!important}.role-list ::ng-deep .mat-mdc-list-option[aria-selected=true] .mdc-list-item__primary-text{color:var(--ymt-on-selection-background);font-weight:500}.role-list ::ng-deep .mat-mdc-list-option:hover:not([aria-selected=true]){background-color:var(--ymt-hover-background)}.control-buttons{display:flex;flex-direction:column;justify-content:center;gap:var(--ymt-spacing-xs)}.empty-message{padding:var(--ymt-spacing-m);text-align:center;color:var(--ymt-text-color-subtle);font:var(--ymt-font-body-subtle)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i3$3.MatSelectionList, selector: "mat-selection-list", inputs: ["color", "compareWith", "multiple", "hideSingleSelectionIndicator", "disabled"], outputs: ["selectionChange"], exportAs: ["matSelectionList"] }, { kind: "component", type: i3$3.MatListOption, selector: "mat-list-option", inputs: ["togglePosition", "checkboxPosition", "color", "value", "selected"], outputs: ["selectedChange"], exportAs: ["matListOption"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
413
475
  }
414
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: EditUserRolesComponent, decorators: [{
476
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EditUserRolesComponent, decorators: [{
415
477
  type: Component,
416
478
  args: [{ selector: 'ymusrmgmt-edit-user-roles', imports: [
417
479
  CommonModule,
418
480
  MatIconModule,
419
481
  MatButtonModule,
420
482
  MatListModule,
421
- TranslateModule,
483
+ TranslatePipe,
422
484
  ], standalone: true, template: "<div class=\"role-selector\">\n <!-- Available Roles (Left) -->\n <div class=\"role-list-container\">\n <div class=\"role-list-header\">\n {{ 'yuv.app.user-management.users.roles.available' | translate }}\n </div>\n <mat-selection-list class=\"role-list\" #availableList hideSingleSelectionIndicator=\"true\">\n @for (role of availableRoles(); track role) {\n <mat-list-option \n [value]=\"role\" \n [selected]=\"isAvailableSelected(role)\"\n (click)=\"toggleAvailableRole(role)\">\n {{ role }}\n </mat-list-option>\n }\n @empty {\n <div class=\"empty-message\">\n {{ 'yuv.app.user-management.users.roles.noAvailable' | translate }}\n </div>\n }\n </mat-selection-list>\n </div>\n\n <!-- Control Buttons (Center) -->\n <div class=\"control-buttons\">\n <button \n mat-icon-button \n [disabled]=\"availableRoles().length === 0\"\n (click)=\"assignAllRoles()\"\n [title]=\"'yuv.app.user-management.users.roles.assignAll' | translate\">\n <mat-icon>keyboard_double_arrow_right</mat-icon>\n </button>\n <button \n mat-icon-button \n [disabled]=\"!canAssign()\"\n (click)=\"assignRoles()\"\n [title]=\"'yuv.app.user-management.users.roles.assign' | translate\">\n <mat-icon>chevron_right</mat-icon>\n </button>\n <button \n mat-icon-button \n [disabled]=\"!canRemove()\"\n (click)=\"removeRoles()\"\n [title]=\"'yuv.app.user-management.users.roles.remove' | translate\">\n <mat-icon>chevron_left</mat-icon>\n </button>\n <button \n mat-icon-button \n [disabled]=\"userRoles().length === 0\"\n (click)=\"removeAllRoles()\"\n [title]=\"'yuv.app.user-management.users.roles.removeAll' | translate\">\n <mat-icon>keyboard_double_arrow_left</mat-icon>\n </button>\n </div>\n\n <!-- Assigned Roles (Right) -->\n <div class=\"role-list-container\">\n <div class=\"role-list-header\">\n {{ 'yuv.app.user-management.users.roles.assigned' | translate }}\n </div>\n <mat-selection-list class=\"role-list\" #assignedList hideSingleSelectionIndicator=\"true\">\n @for (role of userRoles(); track role) {\n <mat-list-option \n [value]=\"role\" \n [selected]=\"isAssignedSelected(role)\"\n (click)=\"toggleAssignedRole(role)\">\n {{ role }}\n </mat-list-option>\n }\n @empty {\n <div class=\"empty-message\">\n {{ 'yuv.app.user-management.users.roles.noAssigned' | translate }}\n </div>\n }\n </mat-selection-list>\n </div>\n</div>\n", styles: [".role-selector{display:flex;gap:var(--ymt-spacing-m);align-items:stretch;min-height:300px;padding:var(--ymt-spacing-xs) 0}.role-list-container{flex:1;display:flex;flex-direction:column;border:var(--ymt-outline-width) solid var(--ymt-outline-variant);border-radius:var(--ymt-corner-xs);overflow:hidden;background-color:var(--ymt-surface-container-lowest);max-height:300px}.role-list-header{padding:var(--ymt-spacing-s) var(--ymt-spacing-m);background-color:var(--ymt-surface-container-high);color:var(--ymt-on-surface);font:var(--ymt-font-title-smallest);border-bottom:var(--ymt-outline-width) solid var(--ymt-outline-variant)}.role-list{flex:1;overflow-y:auto;min-height:0}.role-list ::ng-deep .mat-mdc-list-option{font:var(--ymt-font-body-subtle);min-height:var(--ymt-sizing-2xl)}.role-list ::ng-deep .mdc-list-item__primary-text{font:var(--ymt-font-body-subtle)}.role-list ::ng-deep .mdc-checkbox{display:none}.role-list ::ng-deep .mat-mdc-list-option[aria-selected=true]{background-color:var(--ymt-selection-background)!important}.role-list ::ng-deep .mat-mdc-list-option[aria-selected=true] .mdc-list-item__primary-text{color:var(--ymt-on-selection-background);font-weight:500}.role-list ::ng-deep .mat-mdc-list-option:hover:not([aria-selected=true]){background-color:var(--ymt-hover-background)}.control-buttons{display:flex;flex-direction:column;justify-content:center;gap:var(--ymt-spacing-xs)}.empty-message{padding:var(--ymt-spacing-m);text-align:center;color:var(--ymt-text-color-subtle);font:var(--ymt-font-body-subtle)}\n"] }]
423
- }], ctorParameters: () => [] });
485
+ }], ctorParameters: () => [], propDecorators: { allRoles: [{ type: i0.Input, args: [{ isSignal: true, alias: "allRoles", required: true }] }], assignedRoles: [{ type: i0.Input, args: [{ isSignal: true, alias: "assignedRoles", required: true }] }], rolesChange: [{ type: i0.Output, args: ["rolesChange"] }] } });
424
486
 
425
- const components = [BusyOverlayDirective, YmtButtonDirective, DialogComponent, EditUserRolesComponent];
426
- const modules = [
487
+ const components$2 = [BusyOverlayDirective, YmtButtonDirective, DialogComponent, EditUserRolesComponent];
488
+ const modules$2 = [
427
489
  CommonModule,
428
490
  ReactiveFormsModule,
429
- TranslateModule,
491
+ TranslatePipe,
430
492
  MatFormFieldModule,
431
493
  MatInputModule,
432
494
  ];
@@ -437,10 +499,10 @@ class EditUserComponent {
437
499
  #dialogRef = inject((MatDialogRef));
438
500
  #translateService = inject(TranslateService);
439
501
  #logger = inject(Logger);
440
- busy = signal(false);
441
- error = signal(undefined);
442
- allAvailableRoles = signal([]);
443
- userRoles = signal([]);
502
+ busy = signal(false, ...(ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []));
503
+ error = signal(undefined, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
504
+ allAvailableRoles = signal([], ...(ngDevMode ? [{ debugName: "allAvailableRoles" }] : /* istanbul ignore next */ []));
505
+ userRoles = signal([], ...(ngDevMode ? [{ debugName: "userRoles" }] : /* istanbul ignore next */ []));
444
506
  username = new FormControl('');
445
507
  email = new FormControl('', [Validators.required, Validators.email]);
446
508
  firstName = new FormControl('', [Validators.minLength(1), Validators.maxLength(255), Validators.pattern("^[^#!<>&/%=;*§$()[\\]{}]*$")]);
@@ -453,13 +515,11 @@ class EditUserComponent {
453
515
  lastName: this.lastName,
454
516
  roles: this.roles
455
517
  });
456
- changedInput = signal(undefined);
457
- disabledSubmit = linkedSignal({
458
- source: this.changedInput,
518
+ changedInput = signal(undefined, ...(ngDevMode ? [{ debugName: "changedInput" }] : /* istanbul ignore next */ []));
519
+ disabledSubmit = linkedSignal({ ...(ngDevMode ? { debugName: "disabledSubmit" } : /* istanbul ignore next */ {}), source: this.changedInput,
459
520
  computation: () => {
460
521
  return this.busy() || this.form.invalid || !this.isDataChanged();
461
- }
462
- });
522
+ } });
463
523
  constructor(data) {
464
524
  this.data = data;
465
525
  this.form.patchValue({
@@ -500,7 +560,7 @@ class EditUserComponent {
500
560
  this.form.patchValue({ roles: roles });
501
561
  this.roles.markAsTouched(); // Mark as touched to trigger validation display
502
562
  }
503
- editUser() {
563
+ updateUser() {
504
564
  const editParams = this.form.value;
505
565
  this.busy.set(true);
506
566
  this.error.set(undefined);
@@ -511,7 +571,7 @@ class EditUserComponent {
511
571
  roles: editParams.roles
512
572
  };
513
573
  this.#userManagementService
514
- .editUser(this.data.user.id, updateUserRequest)
574
+ .updateUser(this.data.user.id, updateUserRequest)
515
575
  .subscribe({
516
576
  error: (e) => {
517
577
  switch (e.status) {
@@ -534,14 +594,14 @@ class EditUserComponent {
534
594
  close() {
535
595
  this.#dialogRef.close();
536
596
  }
537
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: EditUserComponent, deps: [{ token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
538
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: EditUserComponent, isStandalone: true, selector: "ymusrmgmt-edit-user", host: { properties: { "class.busy": "!busy()" } }, ngImport: i0, template: "<yuv-dialog [yuvBusyOverlay]=\"busy()\" [headertitel]=\"'yuv.app.user-management.users.action.edit.label' | translate\">\n <main class=\"yuv-dialog-content\">\n <form [formGroup]=\"form\">\n <mat-form-field class=\"yuv-form-field readonly-field\">\n <mat-label class=\"readonly-label\">{{\"yuv.app.user-management.users.object.property.username\" | translate }}</mat-label>\n <input matInput [formControl]=\"username\" type=\"text\" [attr.tabindex]=\"-1\" readonly/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.email\" | translate}}</mat-label>\n <input matInput [formControl]=\"email\" type=\"text\" #emailField/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.firstname\" | translate}}</mat-label>\n <input matInput [formControl]=\"firstName\" type=\"text\"/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.lastname\" | translate}}</mat-label>\n <input matInput [formControl]=\"lastName\" type=\"text\"/>\n </mat-form-field>\n \n <div class=\"roles-section\" [class.has-error]=\"roles.invalid && roles.touched\">\n <ymusrmgmt-edit-user-roles\n [allRoles]=\"allAvailableRoles()\"\n [assignedRoles]=\"userRoles()\"\n (rolesChange)=\"onRolesChange($event)\">\n </ymusrmgmt-edit-user-roles>\n </div>\n \n @if (error()) {\n <p class=\"error\">{{ error() }}</p>\n }\n </form>\n </main>\n <footer>\n <button ymtButton=\"secondary\" [disabled]=\"busy()\" (click)=\"close()\">\n {{ \"yuv.app.user-management.users.action.button.cancel\" | translate }}\n </button>\n <button ymtButton=\"primary\" [disabled]=\"disabledSubmit()\" (click)=\"editUser()\">\n {{ 'yuv.app.user-management.users.action.button.save' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host{display:block;position:relative}:host main form{padding:var(--ymt-spacing-m)}:host main form .yuv-form-field{width:100%;margin:var(--ymt-spacing-xs) 0}:host main form .readonly-field{opacity:.5;pointer-events:none}:host main form .readonly-label{pointer-events:none}:host main form .error{color:var(--ymt-on-danger-container);background-color:var(--ymt-danger-container);padding:var(--ymt-spacing-m);border-radius:var(--ymt-corner-xs)}:host main form .roles-section{margin:var(--ymt-spacing-m) 0}:host main form .roles-section .roles-label{display:block;font-size:12px;font-weight:400;color:#0009;margin-bottom:var(--ymt-spacing-xs)}:host main form .roles-section.has-error .roles-label{color:var(--ymt-danger)}:host main form .roles-section.has-error ymusrmgmt-edit-user-roles{border:2px solid var(--ymt-danger);border-radius:var(--ymt-corner-xs);display:block}:host main form .roles-section .roles-error{color:var(--ymt-danger);font-size:12px;margin-top:var(--ymt-spacing-xs);padding-left:var(--ymt-spacing-m)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay", "yuvBusyOverlayConfig", "yuvBusyError"], outputs: ["yuvBusyErrorDismiss"] }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }, { kind: "component", type: DialogComponent, selector: "yuv-dialog", inputs: ["headertitle", "headertitel"] }, { kind: "component", type: EditUserRolesComponent, selector: "ymusrmgmt-edit-user-roles", inputs: ["allRoles", "assignedRoles"], outputs: ["rolesChange"] }] });
597
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EditUserComponent, deps: [{ token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
598
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: EditUserComponent, isStandalone: true, selector: "ymusrmgmt-edit-user", host: { properties: { "class.busy": "!busy()" } }, ngImport: i0, template: "<yuv-dialog [yuvBusyOverlay]=\"busy()\" [headertitel]=\"'yuv.app.user-management.users.action.edit.label' | translate\">\n <main class=\"yuv-dialog-content\">\n <form [formGroup]=\"form\">\n <mat-form-field class=\"yuv-form-field readonly-field\">\n <mat-label class=\"readonly-label\">{{\"yuv.app.user-management.users.object.property.username\" | translate }}</mat-label>\n <input matInput [formControl]=\"username\" type=\"text\" [attr.tabindex]=\"-1\" readonly/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.email\" | translate}}</mat-label>\n <input matInput [formControl]=\"email\" type=\"text\" #emailField/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.firstname\" | translate}}</mat-label>\n <input matInput [formControl]=\"firstName\" type=\"text\"/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.lastname\" | translate}}</mat-label>\n <input matInput [formControl]=\"lastName\" type=\"text\"/>\n </mat-form-field>\n \n <div class=\"roles-section\" [class.has-error]=\"roles.invalid && roles.touched\">\n <ymusrmgmt-edit-user-roles\n [allRoles]=\"allAvailableRoles()\"\n [assignedRoles]=\"userRoles()\"\n (rolesChange)=\"onRolesChange($event)\">\n </ymusrmgmt-edit-user-roles>\n </div>\n \n @if (error()) {\n <p class=\"error\">{{ error() }}</p>\n }\n </form>\n </main>\n <footer>\n <button ymtButton=\"secondary\" [disabled]=\"busy()\" (click)=\"close()\">\n {{ \"yuv.app.user-management.users.action.button.cancel\" | translate }}\n </button>\n <button ymtButton=\"primary\" [disabled]=\"disabledSubmit()\" (click)=\"updateUser()\">\n {{ 'yuv.app.user-management.users.action.button.save' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host{display:block;position:relative}:host main form{padding:var(--ymt-spacing-m)}:host main form .yuv-form-field{width:100%;margin:var(--ymt-spacing-xs) 0}:host main form .readonly-field{opacity:.5;pointer-events:none}:host main form .readonly-label{pointer-events:none}:host main form .error{color:var(--ymt-on-danger-container);background-color:var(--ymt-danger-container);padding:var(--ymt-spacing-m);border-radius:var(--ymt-corner-xs)}:host main form .roles-section{margin:var(--ymt-spacing-m) 0}:host main form .roles-section .roles-label{display:block;font-size:12px;font-weight:400;color:#0009;margin-bottom:var(--ymt-spacing-xs)}:host main form .roles-section.has-error .roles-label{color:var(--ymt-danger)}:host main form .roles-section.has-error ymusrmgmt-edit-user-roles{border:2px solid var(--ymt-danger);border-radius:var(--ymt-corner-xs);display:block}:host main form .roles-section .roles-error{color:var(--ymt-danger);font-size:12px;margin-top:var(--ymt-spacing-xs);padding-left:var(--ymt-spacing-m)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay", "yuvBusyOverlayConfig", "yuvBusyError"], outputs: ["yuvBusyErrorDismiss"] }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }, { kind: "component", type: DialogComponent, selector: "yuv-dialog", inputs: ["headertitle", "headertitel"] }, { kind: "component", type: EditUserRolesComponent, selector: "ymusrmgmt-edit-user-roles", inputs: ["allRoles", "assignedRoles"], outputs: ["rolesChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
539
599
  }
540
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: EditUserComponent, decorators: [{
600
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EditUserComponent, decorators: [{
541
601
  type: Component,
542
- args: [{ selector: 'ymusrmgmt-edit-user', standalone: true, imports: [...modules, ...components], host: {
602
+ args: [{ selector: 'ymusrmgmt-edit-user', standalone: true, imports: [...modules$2, ...components$2], host: {
543
603
  '[class.busy]': '!busy()',
544
- }, template: "<yuv-dialog [yuvBusyOverlay]=\"busy()\" [headertitel]=\"'yuv.app.user-management.users.action.edit.label' | translate\">\n <main class=\"yuv-dialog-content\">\n <form [formGroup]=\"form\">\n <mat-form-field class=\"yuv-form-field readonly-field\">\n <mat-label class=\"readonly-label\">{{\"yuv.app.user-management.users.object.property.username\" | translate }}</mat-label>\n <input matInput [formControl]=\"username\" type=\"text\" [attr.tabindex]=\"-1\" readonly/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.email\" | translate}}</mat-label>\n <input matInput [formControl]=\"email\" type=\"text\" #emailField/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.firstname\" | translate}}</mat-label>\n <input matInput [formControl]=\"firstName\" type=\"text\"/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.lastname\" | translate}}</mat-label>\n <input matInput [formControl]=\"lastName\" type=\"text\"/>\n </mat-form-field>\n \n <div class=\"roles-section\" [class.has-error]=\"roles.invalid && roles.touched\">\n <ymusrmgmt-edit-user-roles\n [allRoles]=\"allAvailableRoles()\"\n [assignedRoles]=\"userRoles()\"\n (rolesChange)=\"onRolesChange($event)\">\n </ymusrmgmt-edit-user-roles>\n </div>\n \n @if (error()) {\n <p class=\"error\">{{ error() }}</p>\n }\n </form>\n </main>\n <footer>\n <button ymtButton=\"secondary\" [disabled]=\"busy()\" (click)=\"close()\">\n {{ \"yuv.app.user-management.users.action.button.cancel\" | translate }}\n </button>\n <button ymtButton=\"primary\" [disabled]=\"disabledSubmit()\" (click)=\"editUser()\">\n {{ 'yuv.app.user-management.users.action.button.save' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host{display:block;position:relative}:host main form{padding:var(--ymt-spacing-m)}:host main form .yuv-form-field{width:100%;margin:var(--ymt-spacing-xs) 0}:host main form .readonly-field{opacity:.5;pointer-events:none}:host main form .readonly-label{pointer-events:none}:host main form .error{color:var(--ymt-on-danger-container);background-color:var(--ymt-danger-container);padding:var(--ymt-spacing-m);border-radius:var(--ymt-corner-xs)}:host main form .roles-section{margin:var(--ymt-spacing-m) 0}:host main form .roles-section .roles-label{display:block;font-size:12px;font-weight:400;color:#0009;margin-bottom:var(--ymt-spacing-xs)}:host main form .roles-section.has-error .roles-label{color:var(--ymt-danger)}:host main form .roles-section.has-error ymusrmgmt-edit-user-roles{border:2px solid var(--ymt-danger);border-radius:var(--ymt-corner-xs);display:block}:host main form .roles-section .roles-error{color:var(--ymt-danger);font-size:12px;margin-top:var(--ymt-spacing-xs);padding-left:var(--ymt-spacing-m)}\n"] }]
604
+ }, template: "<yuv-dialog [yuvBusyOverlay]=\"busy()\" [headertitel]=\"'yuv.app.user-management.users.action.edit.label' | translate\">\n <main class=\"yuv-dialog-content\">\n <form [formGroup]=\"form\">\n <mat-form-field class=\"yuv-form-field readonly-field\">\n <mat-label class=\"readonly-label\">{{\"yuv.app.user-management.users.object.property.username\" | translate }}</mat-label>\n <input matInput [formControl]=\"username\" type=\"text\" [attr.tabindex]=\"-1\" readonly/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.email\" | translate}}</mat-label>\n <input matInput [formControl]=\"email\" type=\"text\" #emailField/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.firstname\" | translate}}</mat-label>\n <input matInput [formControl]=\"firstName\" type=\"text\"/>\n </mat-form-field>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.users.object.property.lastname\" | translate}}</mat-label>\n <input matInput [formControl]=\"lastName\" type=\"text\"/>\n </mat-form-field>\n \n <div class=\"roles-section\" [class.has-error]=\"roles.invalid && roles.touched\">\n <ymusrmgmt-edit-user-roles\n [allRoles]=\"allAvailableRoles()\"\n [assignedRoles]=\"userRoles()\"\n (rolesChange)=\"onRolesChange($event)\">\n </ymusrmgmt-edit-user-roles>\n </div>\n \n @if (error()) {\n <p class=\"error\">{{ error() }}</p>\n }\n </form>\n </main>\n <footer>\n <button ymtButton=\"secondary\" [disabled]=\"busy()\" (click)=\"close()\">\n {{ \"yuv.app.user-management.users.action.button.cancel\" | translate }}\n </button>\n <button ymtButton=\"primary\" [disabled]=\"disabledSubmit()\" (click)=\"updateUser()\">\n {{ 'yuv.app.user-management.users.action.button.save' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host{display:block;position:relative}:host main form{padding:var(--ymt-spacing-m)}:host main form .yuv-form-field{width:100%;margin:var(--ymt-spacing-xs) 0}:host main form .readonly-field{opacity:.5;pointer-events:none}:host main form .readonly-label{pointer-events:none}:host main form .error{color:var(--ymt-on-danger-container);background-color:var(--ymt-danger-container);padding:var(--ymt-spacing-m);border-radius:var(--ymt-corner-xs)}:host main form .roles-section{margin:var(--ymt-spacing-m) 0}:host main form .roles-section .roles-label{display:block;font-size:12px;font-weight:400;color:#0009;margin-bottom:var(--ymt-spacing-xs)}:host main form .roles-section.has-error .roles-label{color:var(--ymt-danger)}:host main form .roles-section.has-error ymusrmgmt-edit-user-roles{border:2px solid var(--ymt-danger);border-radius:var(--ymt-corner-xs);display:block}:host main form .roles-section .roles-error{color:var(--ymt-danger);font-size:12px;margin-top:var(--ymt-spacing-xs);padding-left:var(--ymt-spacing-m)}\n"] }]
545
605
  }], ctorParameters: () => [{ type: undefined, decorators: [{
546
606
  type: Inject,
547
607
  args: [MAT_DIALOG_DATA]
@@ -557,15 +617,15 @@ class YuvUsersPageComponent {
557
617
  #userService = inject(UserService);
558
618
  #confirmService = inject(ConfirmService);
559
619
  userDetailsComponent;
560
- pagination;
561
- busy = signal(false);
620
+ pagination = { total: 0, pages: 0, page: 0 };
621
+ busy = signal(false, ...(ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []));
562
622
  actions = [];
563
623
  displayedColumns = ['state', 'name', 'firstName', 'lastName', 'email', 'id'];
564
624
  icons = {
565
625
  ...APP_ICONS,
566
626
  };
567
- dataSource = signal([]);
568
- selection = signal(new SelectionModel(false, undefined));
627
+ dataSource = signal([], ...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
628
+ selection = signal(new SelectionModel(false, undefined), ...(ngDevMode ? [{ debugName: "selection" }] : /* istanbul ignore next */ []));
569
629
  detailsActive = true;
570
630
  layoutOptions = {
571
631
  resizable: true,
@@ -657,7 +717,7 @@ class YuvUsersPageComponent {
657
717
  const updateUserRequest = { enabled };
658
718
  const performUpdate = () => {
659
719
  this.busy.set(true);
660
- this.#userManagementService.editUser(selected.id, updateUserRequest).subscribe({
720
+ this.#userManagementService.updateUser(selected.id, updateUserRequest).subscribe({
661
721
  error: (e) => {
662
722
  this.#notificationService.error(this.#translateService.instant(`yuv.app.user-management.users.action.${action}.error`, { username: selected.username }));
663
723
  this.#logger.error(`Failed to ${action} user with id ${selected.id}`, e);
@@ -755,12 +815,11 @@ class YuvUsersPageComponent {
755
815
  next: (response) => {
756
816
  console.log(`fetched users: ${response}`);
757
817
  this.dataSource.set(response.objects);
758
- this.pagination = (response.totalNumItems > YuvUserManagementService.DEFAULT_PAGE_SIZE)
759
- ? {
760
- total: response.totalNumItems,
761
- pages: Math.ceil(response.totalNumItems / YuvUserManagementService.DEFAULT_PAGE_SIZE),
762
- page: page
763
- } : undefined;
818
+ this.pagination = {
819
+ total: response.totalNumItems,
820
+ pages: Math.ceil(response.totalNumItems / YuvUserManagementService.DEFAULT_PAGE_SIZE),
821
+ page: page
822
+ };
764
823
  },
765
824
  error: (e) => {
766
825
  this.#logger.error('Failed to fetch users', e);
@@ -783,10 +842,10 @@ class YuvUsersPageComponent {
783
842
  },
784
843
  });
785
844
  }
786
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: YuvUsersPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
787
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: YuvUsersPageComponent, isStandalone: true, selector: "ymusrmgmt-users", host: { properties: { "class.busy": "!busy()", "class.pagination": "this.pagination" } }, viewQueries: [{ propertyName: "userDetailsComponent", first: true, predicate: UserDetailsComponent, descendants: true }], ngImport: i0, template: "<ng-template yuvAppHeaderSlot=\"actions\">\n <button ymtButton=\"primary\" (click)=\"createNewUser()\" [matTooltip]=\"'yuv.app.user-management.users.action.create.description' | translate\">\n <mat-icon>{{icons.actionCreateNewUser}}</mat-icon>{{'yuv.app.user-management.users.action.create.label' | translate }}\n </button>\n</ng-template>\n\n<ng-template yuvAppHeaderSlot=\"search\">\n <yuv-simple-search (queryChange)=\"onQueryChange($event)\"></yuv-simple-search>\n</ng-template>\n\n<ymt-master-details-layout [yuvBusyOverlay]=\"busy()\" [(detailsActive)]=\"detailsActive\" [options]=\"layoutOptions\" [layoutSettingsID]=\"layoutSettingsID\">\n <ng-template ymtLayoutPane role=\"master\" [topBarActions]=\"masterPaneActions\">\n <ymt-pane-body>\n <mat-table [dataSource]=\"dataSource()\" class=\"user-table mat-elevation-z8\" row>\n <ng-container matColumnDef=\"state\">\n <mat-header-cell *matHeaderCellDef />\n <mat-cell *matCellDef=\"let element\"><mat-icon>{{ element.enabled ? icons.stateActive : icons.stateInactive\n }}</mat-icon></mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"name\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.username' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.username}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"firstName\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.firstname' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.firstName}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"lastName\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.lastname' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.lastName}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"email\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.email' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.email}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"id\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.id' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.id}} </mat-cell>\n </ng-container>\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row \n *matRowDef=\"let row; columns: displayedColumns;\" \n (click.single)=\"select(row)\" \n [class.selected-row]=\"this.isSelected(row)\" class=\"user-row\">\n </mat-row>\n </mat-table>\n </ymt-pane-body>\n </ng-template>\n <ng-template ymtLayoutPane role=\"details\">\n @let selectedUser = selection().selected.at(0);\n <ymt-pane-header [icon]=\"'person'\" [title]=\"'yuv.app.user-management.users.details.title' | translate\" [subtitle]=\"selectedUser?.id || ('yuv.app.user-management.users.details.empty' | translate)\" [actions]=\"listActions\"></ymt-pane-header>\n <ymt-pane-body>\n <ymusrmgmt-user-details [userId]=\"selectedUser?.id\" />\n </ymt-pane-body>\n </ng-template>\n</ymt-master-details-layout>\n\n<ng-template #masterPaneActions>\n @if (pagination) {\n <mat-paginator class=\"paginator\" [length]=\"pagination.total\" [pageSize]=\"getPageSize()\" aria-label=\"Select page\" (page)=\"onChangePage($event)\" hidePageSize></mat-paginator>\n }\n <button ymt-icon-button (click)=\"refresh(true)\" [matTooltip]=\"'yuv.app.user-management.users.navigation.refresh.tooltip' | translate\"><mat-icon>{{icons.refresh}}</mat-icon></button>\n</ng-template>\n\n<ng-template #listActions>\n <yuv-overflow-menu [menuItems]=\"actions\"></yuv-overflow-menu>\n</ng-template>", styles: [":host{--mat-table-row-item-outline-color: var(--ymt-outline-variant);height:100%;overflow:hidden;display:flex;flex-flow:column}:host ymt-master-details-layout{height:100%;padding:1rem}:host .user-table{overflow:auto;height:100%}:host .user-row:hover{background-color:var(--ymt-hover-background)}:host .selected-row{background-color:var(--ymt-selection-background)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i2$2.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i3$3.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i3$3.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i3$3.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i3$3.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i3$3.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i3$3.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i3$3.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i3$3.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i3$3.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i3$3.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "component", type: SimpleSearchComponent, selector: "yuv-simple-search", inputs: ["query"], outputs: ["querySubmit", "clearInput", "targetSelectionChanged", "queryChange", "typeAggregation"] }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay", "yuvBusyOverlayConfig", "yuvBusyError"], outputs: ["yuvBusyErrorDismiss"] }, { kind: "directive", type: ClickDoubleDirective, selector: "[click.single],[click.double]", inputs: ["debounceTime"], outputs: ["click.double", "click.single"] }, { kind: "component", type: UserDetailsComponent, selector: "ymusrmgmt-user-details", inputs: ["userId"] }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }, { kind: "directive", type: YmtIconButtonDirective, selector: "button[ymtIconButton],button[ymt-icon-button],a[ymtIconButton],a[ymt-icon-button]", inputs: ["disabled", "disableRipple", "aria-disabled", "disabledInteractive", "icon-button-size"] }, { kind: "ngmodule", type: YmtLayoutModule }, { kind: "component", type: i6.MasterDetailsLayoutComponent, selector: "ymt-master-details-layout", inputs: ["layoutSettingsID", "options", "direction", "gutterSize", "detailsActive"], outputs: ["detailsActiveChange"] }, { kind: "directive", type: i6.YmtLayoutPaneDirective, selector: "[ymtLayoutPane]", inputs: ["role", "topBarActions"] }, { kind: "ngmodule", type: YmtPanesModule }, { kind: "component", type: i7$1.YmtPaneHeaderComponent, selector: "ymt-pane-header", inputs: ["title", "icon", "subtitle", "actions", "badges"] }, { kind: "component", type: i7$1.YmtPaneBodyComponent, selector: "ymt-pane-body" }, { kind: "ngmodule", type: YuvClientShellModule }, { kind: "directive", type: i8.YuvAppHeaderSlotDirective, selector: "ng-template[yuvAppHeaderSlot]", inputs: ["yuvAppHeaderSlot"] }, { kind: "ngmodule", type: YuvOverflowMenuModule }, { kind: "component", type: i9.OverflowMenuComponent, selector: "yuv-overflow-menu", inputs: ["overflowIcon", "groupLabels", "menuItems", "vertical"] }] });
845
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: YuvUsersPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
846
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.12", type: YuvUsersPageComponent, isStandalone: true, selector: "ymusrmgmt-users", host: { properties: { "class.busy": "!busy()", "class.pagination": "this.pagination" } }, viewQueries: [{ propertyName: "userDetailsComponent", first: true, predicate: UserDetailsComponent, descendants: true }], ngImport: i0, template: "<ng-template yuvAppHeaderSlot=\"search\">\n <yuv-simple-search (queryChange)=\"onQueryChange($event)\"></yuv-simple-search>\n</ng-template>\n\n<ymt-master-details-layout [yuvBusyOverlay]=\"busy()\" [(detailsActive)]=\"detailsActive\" [options]=\"layoutOptions\" [layoutSettingsID]=\"layoutSettingsID\">\n <ng-template ymtLayoutPane role=\"master\" [topBarActions]=\"masterPaneActions\">\n <ymt-pane-body>\n <mat-table [dataSource]=\"dataSource()\" class=\"user-table mat-elevation-z8\" row>\n <ng-container matColumnDef=\"state\">\n <mat-header-cell *matHeaderCellDef />\n <mat-cell *matCellDef=\"let element\"><mat-icon>{{ element.enabled ? icons.stateActive : icons.stateInactive\n }}</mat-icon></mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"name\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.username' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.username}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"firstName\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.firstname' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.firstName}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"lastName\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.lastname' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.lastName}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"email\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.email' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.email}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"id\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.id' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.id}} </mat-cell>\n </ng-container>\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row \n *matRowDef=\"let row; columns: displayedColumns;\" \n (click.single)=\"select(row)\" \n [class.selected-row]=\"this.isSelected(row)\" class=\"user-row\">\n </mat-row>\n </mat-table>\n </ymt-pane-body>\n </ng-template>\n <ng-template ymtLayoutPane role=\"details\">\n @let selectedUser = selection().selected.at(0);\n <ymt-pane-header [icon]=\"'person'\" [title]=\"'yuv.app.user-management.users.details.title' | translate\" [subtitle]=\"selectedUser?.id || ('yuv.app.user-management.users.details.empty' | translate)\" [actions]=\"listActions\"></ymt-pane-header>\n <ymt-pane-body>\n <ymusrmgmt-user-details [userId]=\"selectedUser?.id\" />\n </ymt-pane-body>\n </ng-template>\n</ymt-master-details-layout>\n\n<ng-template #masterPaneActions>\n <button ymtButton=\"primary\" (click)=\"createNewUser()\" [matTooltip]=\"'yuv.app.user-management.users.action.create.description' | translate\">\n <mat-icon>person_add</mat-icon>{{'yuv.app.user-management.users.action.create.label' | translate }}\n </button>\n <mat-paginator class=\"paginator\" [length]=\"pagination.total\" [pageIndex]=\"pagination.page\" [pageSize]=\"getPageSize()\" aria-label=\"Select page\" (page)=\"onChangePage($event)\" hidePageSize></mat-paginator>\n <button ymt-icon-button (click)=\"refresh(true)\" [matTooltip]=\"'yuv.app.user-management.users.navigation.refresh.tooltip' | translate\"><mat-icon>{{icons.refresh}}</mat-icon></button>\n</ng-template>\n\n<ng-template #listActions>\n <yuv-overflow-menu [menuItems]=\"actions\"></yuv-overflow-menu>\n</ng-template>", styles: [":host{--mat-table-row-item-outline-color: var(--ymt-outline-variant);height:100%;overflow:hidden;display:flex;flex-flow:column}:host ymt-master-details-layout{height:100%;padding:1rem}:host .paginator{flex:1;background:transparent}:host .user-table{overflow:auto;height:100%}:host .user-row:hover{background-color:var(--ymt-hover-background)}:host .selected-row{background-color:var(--ymt-selection-background)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i2$3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i3$4.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i3$4.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i3$4.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i3$4.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i3$4.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i3$4.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i3$4.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i3$4.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i3$4.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i3$4.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: RouterModule }, { kind: "component", type: SimpleSearchComponent, selector: "yuv-simple-search", inputs: ["query"], outputs: ["querySubmit", "clearInput", "targetSelectionChanged", "queryChange", "typeAggregation"] }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay", "yuvBusyOverlayConfig", "yuvBusyError"], outputs: ["yuvBusyErrorDismiss"] }, { kind: "directive", type: ClickDoubleDirective, selector: "[click.single],[click.double]", inputs: ["debounceTime"], outputs: ["click.double", "click.single"] }, { kind: "component", type: UserDetailsComponent, selector: "ymusrmgmt-user-details", inputs: ["userId"] }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }, { kind: "directive", type: YmtIconButtonDirective, selector: "button[ymtIconButton],button[ymt-icon-button],a[ymtIconButton],a[ymt-icon-button]", inputs: ["disabled", "disableRipple", "aria-disabled", "disabledInteractive", "icon-button-size"] }, { kind: "ngmodule", type: YmtLayoutModule }, { kind: "component", type: i5$1.MasterDetailsLayoutComponent, selector: "ymt-master-details-layout", inputs: ["layoutSettingsID", "options", "direction", "gutterSize", "detailsActive"], outputs: ["detailsActiveChange"] }, { kind: "directive", type: i5$1.YmtLayoutPaneDirective, selector: "[ymtLayoutPane]", inputs: ["role", "topBarActions"] }, { kind: "ngmodule", type: YmtPanesModule }, { kind: "component", type: i4.YmtPaneHeaderComponent, selector: "ymt-pane-header", inputs: ["title", "icon", "subtitle", "actions", "badges"] }, { kind: "component", type: i4.YmtPaneBodyComponent, selector: "ymt-pane-body" }, { kind: "ngmodule", type: YuvClientShellModule }, { kind: "directive", type: i5.YuvAppHeaderSlotDirective, selector: "ng-template[yuvAppHeaderSlot]", inputs: ["yuvAppHeaderSlot"] }, { kind: "ngmodule", type: YuvOverflowMenuModule }, { kind: "component", type: i8.OverflowMenuComponent, selector: "yuv-overflow-menu", inputs: ["overflowIcon", "groupLabels", "menuItems", "vertical"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
788
847
  }
789
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: YuvUsersPageComponent, decorators: [{
848
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: YuvUsersPageComponent, decorators: [{
790
849
  type: Component,
791
850
  args: [{ selector: 'ymusrmgmt-users', standalone: true, imports: [
792
851
  CommonModule,
@@ -798,7 +857,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
798
857
  MatTabsModule,
799
858
  MatTooltipModule,
800
859
  RouterModule,
801
- TranslateModule,
860
+ TranslatePipe,
802
861
  SimpleSearchComponent,
803
862
  BusyOverlayDirective,
804
863
  ClickDoubleDirective,
@@ -811,7 +870,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
811
870
  YuvOverflowMenuModule,
812
871
  ], host: {
813
872
  '[class.busy]': '!busy()',
814
- }, template: "<ng-template yuvAppHeaderSlot=\"actions\">\n <button ymtButton=\"primary\" (click)=\"createNewUser()\" [matTooltip]=\"'yuv.app.user-management.users.action.create.description' | translate\">\n <mat-icon>{{icons.actionCreateNewUser}}</mat-icon>{{'yuv.app.user-management.users.action.create.label' | translate }}\n </button>\n</ng-template>\n\n<ng-template yuvAppHeaderSlot=\"search\">\n <yuv-simple-search (queryChange)=\"onQueryChange($event)\"></yuv-simple-search>\n</ng-template>\n\n<ymt-master-details-layout [yuvBusyOverlay]=\"busy()\" [(detailsActive)]=\"detailsActive\" [options]=\"layoutOptions\" [layoutSettingsID]=\"layoutSettingsID\">\n <ng-template ymtLayoutPane role=\"master\" [topBarActions]=\"masterPaneActions\">\n <ymt-pane-body>\n <mat-table [dataSource]=\"dataSource()\" class=\"user-table mat-elevation-z8\" row>\n <ng-container matColumnDef=\"state\">\n <mat-header-cell *matHeaderCellDef />\n <mat-cell *matCellDef=\"let element\"><mat-icon>{{ element.enabled ? icons.stateActive : icons.stateInactive\n }}</mat-icon></mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"name\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.username' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.username}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"firstName\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.firstname' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.firstName}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"lastName\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.lastname' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.lastName}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"email\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.email' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.email}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"id\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.id' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.id}} </mat-cell>\n </ng-container>\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row \n *matRowDef=\"let row; columns: displayedColumns;\" \n (click.single)=\"select(row)\" \n [class.selected-row]=\"this.isSelected(row)\" class=\"user-row\">\n </mat-row>\n </mat-table>\n </ymt-pane-body>\n </ng-template>\n <ng-template ymtLayoutPane role=\"details\">\n @let selectedUser = selection().selected.at(0);\n <ymt-pane-header [icon]=\"'person'\" [title]=\"'yuv.app.user-management.users.details.title' | translate\" [subtitle]=\"selectedUser?.id || ('yuv.app.user-management.users.details.empty' | translate)\" [actions]=\"listActions\"></ymt-pane-header>\n <ymt-pane-body>\n <ymusrmgmt-user-details [userId]=\"selectedUser?.id\" />\n </ymt-pane-body>\n </ng-template>\n</ymt-master-details-layout>\n\n<ng-template #masterPaneActions>\n @if (pagination) {\n <mat-paginator class=\"paginator\" [length]=\"pagination.total\" [pageSize]=\"getPageSize()\" aria-label=\"Select page\" (page)=\"onChangePage($event)\" hidePageSize></mat-paginator>\n }\n <button ymt-icon-button (click)=\"refresh(true)\" [matTooltip]=\"'yuv.app.user-management.users.navigation.refresh.tooltip' | translate\"><mat-icon>{{icons.refresh}}</mat-icon></button>\n</ng-template>\n\n<ng-template #listActions>\n <yuv-overflow-menu [menuItems]=\"actions\"></yuv-overflow-menu>\n</ng-template>", styles: [":host{--mat-table-row-item-outline-color: var(--ymt-outline-variant);height:100%;overflow:hidden;display:flex;flex-flow:column}:host ymt-master-details-layout{height:100%;padding:1rem}:host .user-table{overflow:auto;height:100%}:host .user-row:hover{background-color:var(--ymt-hover-background)}:host .selected-row{background-color:var(--ymt-selection-background)!important}\n"] }]
873
+ }, template: "<ng-template yuvAppHeaderSlot=\"search\">\n <yuv-simple-search (queryChange)=\"onQueryChange($event)\"></yuv-simple-search>\n</ng-template>\n\n<ymt-master-details-layout [yuvBusyOverlay]=\"busy()\" [(detailsActive)]=\"detailsActive\" [options]=\"layoutOptions\" [layoutSettingsID]=\"layoutSettingsID\">\n <ng-template ymtLayoutPane role=\"master\" [topBarActions]=\"masterPaneActions\">\n <ymt-pane-body>\n <mat-table [dataSource]=\"dataSource()\" class=\"user-table mat-elevation-z8\" row>\n <ng-container matColumnDef=\"state\">\n <mat-header-cell *matHeaderCellDef />\n <mat-cell *matCellDef=\"let element\"><mat-icon>{{ element.enabled ? icons.stateActive : icons.stateInactive\n }}</mat-icon></mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"name\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.username' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.username}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"firstName\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.firstname' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.firstName}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"lastName\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.lastname' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.lastName}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"email\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.email' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.email}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"id\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.users.object.property.id' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.id}} </mat-cell>\n </ng-container>\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row \n *matRowDef=\"let row; columns: displayedColumns;\" \n (click.single)=\"select(row)\" \n [class.selected-row]=\"this.isSelected(row)\" class=\"user-row\">\n </mat-row>\n </mat-table>\n </ymt-pane-body>\n </ng-template>\n <ng-template ymtLayoutPane role=\"details\">\n @let selectedUser = selection().selected.at(0);\n <ymt-pane-header [icon]=\"'person'\" [title]=\"'yuv.app.user-management.users.details.title' | translate\" [subtitle]=\"selectedUser?.id || ('yuv.app.user-management.users.details.empty' | translate)\" [actions]=\"listActions\"></ymt-pane-header>\n <ymt-pane-body>\n <ymusrmgmt-user-details [userId]=\"selectedUser?.id\" />\n </ymt-pane-body>\n </ng-template>\n</ymt-master-details-layout>\n\n<ng-template #masterPaneActions>\n <button ymtButton=\"primary\" (click)=\"createNewUser()\" [matTooltip]=\"'yuv.app.user-management.users.action.create.description' | translate\">\n <mat-icon>person_add</mat-icon>{{'yuv.app.user-management.users.action.create.label' | translate }}\n </button>\n <mat-paginator class=\"paginator\" [length]=\"pagination.total\" [pageIndex]=\"pagination.page\" [pageSize]=\"getPageSize()\" aria-label=\"Select page\" (page)=\"onChangePage($event)\" hidePageSize></mat-paginator>\n <button ymt-icon-button (click)=\"refresh(true)\" [matTooltip]=\"'yuv.app.user-management.users.navigation.refresh.tooltip' | translate\"><mat-icon>{{icons.refresh}}</mat-icon></button>\n</ng-template>\n\n<ng-template #listActions>\n <yuv-overflow-menu [menuItems]=\"actions\"></yuv-overflow-menu>\n</ng-template>", styles: [":host{--mat-table-row-item-outline-color: var(--ymt-outline-variant);height:100%;overflow:hidden;display:flex;flex-flow:column}:host ymt-master-details-layout{height:100%;padding:1rem}:host .paginator{flex:1;background:transparent}:host .user-table{overflow:auto;height:100%}:host .user-row:hover{background-color:var(--ymt-hover-background)}:host .selected-row{background-color:var(--ymt-selection-background)!important}\n"] }]
815
874
  }], propDecorators: { userDetailsComponent: [{
816
875
  type: ViewChild,
817
876
  args: [UserDetailsComponent]
@@ -820,12 +879,496 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
820
879
  args: ['class.pagination']
821
880
  }] } });
822
881
 
882
+ const components$1 = [BusyOverlayDirective, YmtButtonDirective, DialogComponent, EditUserRolesComponent];
883
+ const modules$1 = [
884
+ CommonModule,
885
+ ReactiveFormsModule,
886
+ TranslatePipe,
887
+ MatFormFieldModule,
888
+ MatSlideToggleModule,
889
+ MatInputModule
890
+ ];
891
+ class CreateGroupComponent {
892
+ #fb = inject(FormBuilder);
893
+ #userManagementService = inject(YuvUserManagementService);
894
+ #dialogRef = inject((MatDialogRef));
895
+ #translateService = inject(TranslateService);
896
+ #logger = inject(Logger);
897
+ busy = signal(false, ...(ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []));
898
+ error = signal(undefined, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
899
+ allAvailableRoles = signal([], ...(ngDevMode ? [{ debugName: "allAvailableRoles" }] : /* istanbul ignore next */ []));
900
+ allUsers = signal([], ...(ngDevMode ? [{ debugName: "allUsers" }] : /* istanbul ignore next */ []));
901
+ groupRoles = signal([], ...(ngDevMode ? [{ debugName: "groupRoles" }] : /* istanbul ignore next */ []));
902
+ groupMembers = signal([], ...(ngDevMode ? [{ debugName: "groupMembers" }] : /* istanbul ignore next */ []));
903
+ name = new FormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(255), Validators.pattern('^[a-zA-Z0-9._-]*$')]);
904
+ roles = new FormControl([]);
905
+ form = this.#fb.group({
906
+ name: this.name,
907
+ roles: this.roles,
908
+ });
909
+ changedInput = signal(undefined, ...(ngDevMode ? [{ debugName: "changedInput" }] : /* istanbul ignore next */ []));
910
+ disabledSubmit = linkedSignal({ ...(ngDevMode ? { debugName: "disabledSubmit" } : /* istanbul ignore next */ {}), source: this.changedInput,
911
+ computation: () => {
912
+ return this.busy() || this.form.invalid;
913
+ } });
914
+ constructor() {
915
+ this.#userManagementService.fetchAllRoles().subscribe({
916
+ next: (roles) => {
917
+ this.allAvailableRoles.set(roles);
918
+ },
919
+ error: (e) => {
920
+ this.#logger.error('Failed to fetch roles', e);
921
+ }
922
+ });
923
+ }
924
+ createGroup() {
925
+ let createdGroupId;
926
+ const createParams = this.form.value;
927
+ this.busy.set(true);
928
+ this.error.set(undefined);
929
+ const createGroupRequest = {
930
+ name: createParams.name,
931
+ roles: createParams.roles,
932
+ members: []
933
+ };
934
+ this.#userManagementService
935
+ .createGroup(createGroupRequest)
936
+ .subscribe({
937
+ error: (e) => {
938
+ switch (e.status) {
939
+ case 409: {
940
+ const errorMsg = JSON.parse(e.error).message;
941
+ if (errorMsg === "Group exists with same username") {
942
+ this.error.set(this.#translateService.instant("yuv.app.user-management.groups.action.create.error.groupExists"));
943
+ }
944
+ else {
945
+ this.error.set(this.#translateService.instant("yuv.app.user-management.groups.action.create.error.unknown"));
946
+ }
947
+ break;
948
+ }
949
+ default:
950
+ this.error.set(this.#translateService.instant("yuv.app.user-management.groups.action.create.error.unknown"));
951
+ }
952
+ this.#logger.error(`Failed to create user with username ${createGroupRequest.name}`, e);
953
+ this.busy.set(false);
954
+ },
955
+ next: (userId) => {
956
+ createdGroupId = userId;
957
+ },
958
+ complete: () => {
959
+ this.busy.set(false);
960
+ this.#dialogRef.close(createdGroupId);
961
+ },
962
+ });
963
+ }
964
+ close() {
965
+ this.#dialogRef.close();
966
+ }
967
+ ngAfterViewInit() {
968
+ this.form.valueChanges.subscribe((value) => {
969
+ this.changedInput.set(value);
970
+ });
971
+ }
972
+ onRolesChange(roles) {
973
+ this.groupRoles.set(roles);
974
+ this.form.patchValue({ roles: roles });
975
+ this.roles.markAsTouched(); // Mark as touched to trigger validation display
976
+ }
977
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: CreateGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
978
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: CreateGroupComponent, isStandalone: true, selector: "ymusrmgmt-create-group", host: { properties: { "class.busy": "!busy()" } }, ngImport: i0, template: "<yuv-dialog [yuvBusyOverlay]=\"busy()\" [headertitel]=\"'yuv.app.user-management.groups.action.create.label' | translate\">\n <main class=\"yuv-dialog-content\">\n <form [formGroup]=\"form\">\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.groups.object.property.name\" | translate }}</mat-label>\n <input matInput [formControl]=\"name\" type=\"text\"/>\n </mat-form-field>\n <div class=\"roles-section\" [class.has-error]=\"roles.invalid && roles.touched\">\n <ymusrmgmt-edit-user-roles\n [allRoles]=\"allAvailableRoles()\"\n [assignedRoles]=\"groupRoles()\"\n (rolesChange)=\"onRolesChange($event)\">\n </ymusrmgmt-edit-user-roles>\n </div>\n @if (error()) {\n <p class=\"error\">{{ error() }}</p>\n }\n </form>\n </main>\n <footer>\n <button ymtButton=\"secondary\" [disabled]=\"busy()\" (click)=\"close()\">\n {{ \"yuv.app.user-management.groups.action.button.cancel\" | translate }}\n </button>\n <button ymtButton=\"primary\" [disabled]=\"disabledSubmit()\" (click)=\"createGroup()\">\n {{ 'yuv.app.user-management.groups.action.button.create' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host{display:block;position:relative}:host main form{padding:var(--ymt-spacing-m)}:host main form .yuv-form-field{width:100%;margin:var(--ymt-spacing-xs) 0}:host main form .error{color:var(--ymt-on-danger-container);background-color:var(--ymt-danger-container);padding:var(--ymt-spacing-m);border-radius:var(--ymt-corner-xs)}:host main form #enabledPropDiv{display:flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay", "yuvBusyOverlayConfig", "yuvBusyError"], outputs: ["yuvBusyErrorDismiss"] }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }, { kind: "component", type: DialogComponent, selector: "yuv-dialog", inputs: ["headertitle", "headertitel"] }, { kind: "component", type: EditUserRolesComponent, selector: "ymusrmgmt-edit-user-roles", inputs: ["allRoles", "assignedRoles"], outputs: ["rolesChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
979
+ }
980
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: CreateGroupComponent, decorators: [{
981
+ type: Component,
982
+ args: [{ selector: 'ymusrmgmt-create-group', standalone: true, imports: [...modules$1, ...components$1], host: {
983
+ '[class.busy]': '!busy()',
984
+ }, template: "<yuv-dialog [yuvBusyOverlay]=\"busy()\" [headertitel]=\"'yuv.app.user-management.groups.action.create.label' | translate\">\n <main class=\"yuv-dialog-content\">\n <form [formGroup]=\"form\">\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{\"yuv.app.user-management.groups.object.property.name\" | translate }}</mat-label>\n <input matInput [formControl]=\"name\" type=\"text\"/>\n </mat-form-field>\n <div class=\"roles-section\" [class.has-error]=\"roles.invalid && roles.touched\">\n <ymusrmgmt-edit-user-roles\n [allRoles]=\"allAvailableRoles()\"\n [assignedRoles]=\"groupRoles()\"\n (rolesChange)=\"onRolesChange($event)\">\n </ymusrmgmt-edit-user-roles>\n </div>\n @if (error()) {\n <p class=\"error\">{{ error() }}</p>\n }\n </form>\n </main>\n <footer>\n <button ymtButton=\"secondary\" [disabled]=\"busy()\" (click)=\"close()\">\n {{ \"yuv.app.user-management.groups.action.button.cancel\" | translate }}\n </button>\n <button ymtButton=\"primary\" [disabled]=\"disabledSubmit()\" (click)=\"createGroup()\">\n {{ 'yuv.app.user-management.groups.action.button.create' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host{display:block;position:relative}:host main form{padding:var(--ymt-spacing-m)}:host main form .yuv-form-field{width:100%;margin:var(--ymt-spacing-xs) 0}:host main form .error{color:var(--ymt-on-danger-container);background-color:var(--ymt-danger-container);padding:var(--ymt-spacing-m);border-radius:var(--ymt-corner-xs)}:host main form #enabledPropDiv{display:flex;justify-content:center;align-items:center}\n"] }]
985
+ }], ctorParameters: () => [] });
986
+
987
+ class GroupDetailsComponent {
988
+ userService;
989
+ formBuilder;
990
+ groupDetails = signal(undefined, ...(ngDevMode ? [{ debugName: "groupDetails" }] : /* istanbul ignore next */ []));
991
+ groupDetailsForm;
992
+ currentGroupId;
993
+ set groupId(value) {
994
+ this.currentGroupId = value;
995
+ this.loadGroupDetails();
996
+ }
997
+ loadGroupDetails() {
998
+ if (this.currentGroupId) {
999
+ this.userService.getGroupDetails(this.currentGroupId).subscribe(group => {
1000
+ this.groupDetails.set(group);
1001
+ this.groupDetailsForm.patchValue({
1002
+ id: group.id,
1003
+ name: group.name
1004
+ });
1005
+ });
1006
+ }
1007
+ else {
1008
+ this.groupDetails.set(undefined);
1009
+ }
1010
+ }
1011
+ /**
1012
+ * Refresh the user details by reloading the data from the server
1013
+ */
1014
+ refresh() {
1015
+ this.loadGroupDetails();
1016
+ }
1017
+ constructor(userService, formBuilder) {
1018
+ this.userService = userService;
1019
+ this.formBuilder = formBuilder;
1020
+ this.groupDetailsForm = this.formBuilder.group({
1021
+ id: [{ value: '' }],
1022
+ name: [{ value: '' }]
1023
+ });
1024
+ }
1025
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: GroupDetailsComponent, deps: [{ token: YuvUserManagementService }, { token: i1$1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
1026
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: GroupDetailsComponent, isStandalone: true, selector: "ymusrmgmt-group-details", inputs: { groupId: "groupId" }, ngImport: i0, template: " \n@let currentGroupDetails = groupDetails();\n@if (currentGroupDetails) {\n <form [formGroup]=\"groupDetailsForm\" class=\"group-details-form\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{('yuv.app.user-management.groups.object.property.id' | translate)}}</mat-label>\n <input matInput formControlName=\"id\" readonly>\n </mat-form-field>\n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.groups.object.property.name' | translate)}}</mat-label>\n <input matInput formControlName=\"name\" readonly>\n </mat-form-field>\n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.groups.object.property.roles' | translate)}}</mat-label>\n <mat-chip-grid #roleChipGrid>\n @if (currentGroupDetails.roles) {\n @for (role of currentGroupDetails.roles.sort(); track role) {\n <mat-chip-row [editable]=\"false\" [disabled]=\"currentGroupDetails.roles.indexOf(role) === -1\"><div class=\"chip\">{{role}}</div></mat-chip-row>\n }\n }\n <input [matChipInputFor]=\"roleChipGrid\" readonly/>\n </mat-chip-grid>\n </mat-form-field> \n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.groups.object.property.members' | translate)}}</mat-label>\n <mat-chip-grid #memberChipGrid>\n @if (currentGroupDetails.members) {\n @for (member of currentGroupDetails.members.sort(); track member) {\n <mat-chip-row [editable]=\"false\"><div class=\"chip\">{{member}}</div></mat-chip-row>\n }\n }\n <input [matChipInputFor]=\"memberChipGrid\" readonly/>\n </mat-chip-grid>\n </mat-form-field> \n </form>\n} @else {\n <p>{{('yuv.app.user-management.groups.details.empty' | translate)}}</p>\n}\n", styles: [":host{height:100%;overflow:hidden;display:flex;flex-flow:column}:host .group-details-form{flex:1;overflow-y:auto;display:grid;align-items:start;align-content:start;gap:var(--ymt-spacing-m);padding:1rem}:host .group-details-form mat-chip-row{overflow:hidden}:host .group-details-form .roles-field mat-chip-grid{max-height:300px;overflow-y:auto;display:block}\n"], dependencies: [{ kind: "ngmodule", type: MatCardModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i3$1.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i3$1.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "component", type: i3$1.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1027
+ }
1028
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: GroupDetailsComponent, decorators: [{
1029
+ type: Component,
1030
+ args: [{ selector: 'ymusrmgmt-group-details', imports: [
1031
+ MatCardModule,
1032
+ MatChipsModule,
1033
+ MatFormFieldModule,
1034
+ MatInputModule,
1035
+ MatIconModule,
1036
+ MatCheckboxModule,
1037
+ MatSlideToggleModule,
1038
+ MatTabsModule,
1039
+ ReactiveFormsModule,
1040
+ TranslatePipe
1041
+ ], template: " \n@let currentGroupDetails = groupDetails();\n@if (currentGroupDetails) {\n <form [formGroup]=\"groupDetailsForm\" class=\"group-details-form\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{('yuv.app.user-management.groups.object.property.id' | translate)}}</mat-label>\n <input matInput formControlName=\"id\" readonly>\n </mat-form-field>\n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.groups.object.property.name' | translate)}}</mat-label>\n <input matInput formControlName=\"name\" readonly>\n </mat-form-field>\n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.groups.object.property.roles' | translate)}}</mat-label>\n <mat-chip-grid #roleChipGrid>\n @if (currentGroupDetails.roles) {\n @for (role of currentGroupDetails.roles.sort(); track role) {\n <mat-chip-row [editable]=\"false\" [disabled]=\"currentGroupDetails.roles.indexOf(role) === -1\"><div class=\"chip\">{{role}}</div></mat-chip-row>\n }\n }\n <input [matChipInputFor]=\"roleChipGrid\" readonly/>\n </mat-chip-grid>\n </mat-form-field> \n <mat-form-field>\n <mat-label>{{('yuv.app.user-management.groups.object.property.members' | translate)}}</mat-label>\n <mat-chip-grid #memberChipGrid>\n @if (currentGroupDetails.members) {\n @for (member of currentGroupDetails.members.sort(); track member) {\n <mat-chip-row [editable]=\"false\"><div class=\"chip\">{{member}}</div></mat-chip-row>\n }\n }\n <input [matChipInputFor]=\"memberChipGrid\" readonly/>\n </mat-chip-grid>\n </mat-form-field> \n </form>\n} @else {\n <p>{{('yuv.app.user-management.groups.details.empty' | translate)}}</p>\n}\n", styles: [":host{height:100%;overflow:hidden;display:flex;flex-flow:column}:host .group-details-form{flex:1;overflow-y:auto;display:grid;align-items:start;align-content:start;gap:var(--ymt-spacing-m);padding:1rem}:host .group-details-form mat-chip-row{overflow:hidden}:host .group-details-form .roles-field mat-chip-grid{max-height:300px;overflow-y:auto;display:block}\n"] }]
1042
+ }], ctorParameters: () => [{ type: YuvUserManagementService }, { type: i1$1.FormBuilder }], propDecorators: { groupId: [{
1043
+ type: Input
1044
+ }] } });
1045
+
1046
+ const components = [BusyOverlayDirective, YmtButtonDirective, DialogComponent, EditUserRolesComponent];
1047
+ const modules = [
1048
+ CommonModule,
1049
+ ReactiveFormsModule,
1050
+ TranslatePipe,
1051
+ MatFormFieldModule,
1052
+ MatInputModule,
1053
+ MatChipsModule,
1054
+ ];
1055
+ class EditGroupComponent {
1056
+ data;
1057
+ #fb = inject(FormBuilder);
1058
+ #userManagementService = inject(YuvUserManagementService);
1059
+ #dialogRef = inject((MatDialogRef));
1060
+ #translateService = inject(TranslateService);
1061
+ #logger = inject(Logger);
1062
+ busy = signal(false, ...(ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []));
1063
+ error = signal(undefined, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
1064
+ allAvailableRoles = signal([], ...(ngDevMode ? [{ debugName: "allAvailableRoles" }] : /* istanbul ignore next */ []));
1065
+ allUsers = signal([], ...(ngDevMode ? [{ debugName: "allUsers" }] : /* istanbul ignore next */ []));
1066
+ groupRoles = signal([], ...(ngDevMode ? [{ debugName: "groupRoles" }] : /* istanbul ignore next */ []));
1067
+ groupMembers = signal([], ...(ngDevMode ? [{ debugName: "groupMembers" }] : /* istanbul ignore next */ []));
1068
+ name = new FormControl('');
1069
+ roles = new FormControl([]);
1070
+ members = new FormControl([]);
1071
+ userControl = new FormControl('');
1072
+ form = this.#fb.group({
1073
+ name: this.name,
1074
+ roles: this.roles,
1075
+ members: this.members
1076
+ });
1077
+ changedInput = signal(undefined, ...(ngDevMode ? [{ debugName: "changedInput" }] : /* istanbul ignore next */ []));
1078
+ disabledSubmit = linkedSignal({ ...(ngDevMode ? { debugName: "disabledSubmit" } : /* istanbul ignore next */ {}), source: this.changedInput,
1079
+ computation: () => {
1080
+ return this.busy() || this.form.invalid || !this.isDataChanged();
1081
+ } });
1082
+ constructor(data) {
1083
+ this.data = data;
1084
+ this.form.patchValue({
1085
+ name: this.data.group.name,
1086
+ roles: this.data.group.roles,
1087
+ members: this.data.group.members
1088
+ });
1089
+ this.members.valueChanges.subscribe((v) => { this.#logger.info("members changed: " + v); });
1090
+ this.groupRoles.set(this.data.group.roles || []);
1091
+ this.groupMembers.set(this.data.group.members || []);
1092
+ this.members.disable();
1093
+ // Fetch all available roles
1094
+ this.#userManagementService.fetchAllRoles().subscribe({
1095
+ next: (roles) => {
1096
+ this.allAvailableRoles.set(roles.sort());
1097
+ },
1098
+ error: (e) => {
1099
+ this.#logger.error('Failed to fetch roles', e);
1100
+ }
1101
+ });
1102
+ }
1103
+ ngAfterViewInit() {
1104
+ this.form.valueChanges.subscribe((value) => {
1105
+ this.changedInput.set(value);
1106
+ });
1107
+ }
1108
+ isDataChanged() {
1109
+ const isDataUnchanged = Object.keys(this.form.value).every((key) => this.isEquals(key));
1110
+ return !isDataUnchanged;
1111
+ }
1112
+ isEquals(key) {
1113
+ const oldVal = this.data.group?.[key];
1114
+ const newVal = this.form.get(key)?.value;
1115
+ return oldVal === newVal;
1116
+ }
1117
+ onRolesChange(roles) {
1118
+ this.groupRoles.set(roles);
1119
+ this.form.patchValue({ roles: roles });
1120
+ this.roles.markAsTouched(); // Mark as touched to trigger validation display
1121
+ }
1122
+ onMembersChange(members) {
1123
+ this.groupMembers.set(members);
1124
+ this.form.patchValue({ members: members });
1125
+ this.roles.markAsTouched(); // Mark as touched to trigger validation display
1126
+ }
1127
+ updateGroup() {
1128
+ const editParams = this.form.getRawValue();
1129
+ this.busy.set(true);
1130
+ this.error.set(undefined);
1131
+ const updateGroupRequest = {
1132
+ name: editParams.name,
1133
+ roles: editParams.roles,
1134
+ members: editParams.members
1135
+ };
1136
+ this.#userManagementService
1137
+ .updateGroup(this.data.group.id, updateGroupRequest)
1138
+ .subscribe({
1139
+ error: (e) => {
1140
+ switch (e.status) {
1141
+ default:
1142
+ this.error.set(this.#translateService.instant("yuv.app.user-management.groups.action.edit.error.unknown"));
1143
+ }
1144
+ this.#logger.error(`Failed to update group with id ${this.data.group.id}`, e);
1145
+ this.busy.set(false);
1146
+ },
1147
+ complete: () => {
1148
+ this.busy.set(false);
1149
+ this.#dialogRef.close(this.data.group.id);
1150
+ },
1151
+ });
1152
+ }
1153
+ close() {
1154
+ this.#dialogRef.close();
1155
+ }
1156
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EditGroupComponent, deps: [{ token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
1157
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: EditGroupComponent, isStandalone: true, selector: "ymusrmgmt-edit-group", host: { properties: { "class.busy": "!busy()" } }, ngImport: i0, template: "<yuv-dialog [yuvBusyOverlay]=\"busy()\" [headertitel]=\"'yuv.app.user-management.groups.action.edit.label' | translate\">\n <main class=\"yuv-dialog-content\">\n <form [formGroup]=\"form\">\n <mat-form-field class=\"yuv-form-field readonly-field\">\n <mat-label class=\"readonly-label\">{{\"yuv.app.user-management.groups.object.property.name\" | translate }}</mat-label>\n <input matInput [formControl]=\"name\" type=\"text\" [attr.tabindex]=\"-1\" readonly/>\n </mat-form-field>\n <div class=\"roles-section\" [class.has-error]=\"roles.invalid && roles.touched\">\n <ymusrmgmt-edit-user-roles\n [allRoles]=\"allAvailableRoles()\"\n [assignedRoles]=\"groupRoles()\"\n (rolesChange)=\"onRolesChange($event)\">\n </ymusrmgmt-edit-user-roles>\n </div>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{'yuv.app.user-management.groups.object.property.members' | translate}}</mat-label>\n <mat-chip-grid #memberChipGrid>\n @for (member of groupMembers(); track member) {\n <mat-chip-row [editable]=\"false\"><div class=\"chip\">{{member}}</div></mat-chip-row>\n }\n <input [matChipInputFor]=\"memberChipGrid\" readonly/>\n </mat-chip-grid>\n </mat-form-field>\n @if (error()) {\n <p class=\"error\">{{ error() }}</p>\n }\n </form>\n </main>\n <footer>\n <button ymtButton=\"secondary\" [disabled]=\"busy()\" (click)=\"close()\">\n {{ \"yuv.app.user-management.users.action.button.cancel\" | translate }}\n </button>\n <button ymtButton=\"primary\" [disabled]=\"disabledSubmit()\" (click)=\"updateGroup()\">\n {{ 'yuv.app.user-management.users.action.button.save' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host{display:block;position:relative}:host main form{padding:var(--ymt-spacing-m)}:host main form .yuv-form-field{width:100%;margin:var(--ymt-spacing-xs) 0}:host main form .readonly-field{opacity:.5;pointer-events:none}:host main form .readonly-label{pointer-events:none}:host main form .error{color:var(--ymt-on-danger-container);background-color:var(--ymt-danger-container);padding:var(--ymt-spacing-m);border-radius:var(--ymt-corner-xs)}:host main form .roles-section{margin:var(--ymt-spacing-m) 0}:host main form .roles-section .roles-label{display:block;font-size:12px;font-weight:400;color:#0009;margin-bottom:var(--ymt-spacing-xs)}:host main form .roles-section.has-error .roles-label{color:var(--ymt-danger)}:host main form .roles-section.has-error ymusrmgmt-edit-user-roles{border:2px solid var(--ymt-danger);border-radius:var(--ymt-corner-xs);display:block}:host main form .roles-section .roles-error{color:var(--ymt-danger);font-size:12px;margin-top:var(--ymt-spacing-xs);padding-left:var(--ymt-spacing-m)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i3$1.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i3$1.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "component", type: i3$1.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay", "yuvBusyOverlayConfig", "yuvBusyError"], outputs: ["yuvBusyErrorDismiss"] }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }, { kind: "component", type: DialogComponent, selector: "yuv-dialog", inputs: ["headertitle", "headertitel"] }, { kind: "component", type: EditUserRolesComponent, selector: "ymusrmgmt-edit-user-roles", inputs: ["allRoles", "assignedRoles"], outputs: ["rolesChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1158
+ }
1159
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EditGroupComponent, decorators: [{
1160
+ type: Component,
1161
+ args: [{ selector: 'ymusrmgmt-edit-group', standalone: true, imports: [...modules, ...components], host: {
1162
+ '[class.busy]': '!busy()',
1163
+ }, template: "<yuv-dialog [yuvBusyOverlay]=\"busy()\" [headertitel]=\"'yuv.app.user-management.groups.action.edit.label' | translate\">\n <main class=\"yuv-dialog-content\">\n <form [formGroup]=\"form\">\n <mat-form-field class=\"yuv-form-field readonly-field\">\n <mat-label class=\"readonly-label\">{{\"yuv.app.user-management.groups.object.property.name\" | translate }}</mat-label>\n <input matInput [formControl]=\"name\" type=\"text\" [attr.tabindex]=\"-1\" readonly/>\n </mat-form-field>\n <div class=\"roles-section\" [class.has-error]=\"roles.invalid && roles.touched\">\n <ymusrmgmt-edit-user-roles\n [allRoles]=\"allAvailableRoles()\"\n [assignedRoles]=\"groupRoles()\"\n (rolesChange)=\"onRolesChange($event)\">\n </ymusrmgmt-edit-user-roles>\n </div>\n <mat-form-field class=\"yuv-form-field\">\n <mat-label>{{'yuv.app.user-management.groups.object.property.members' | translate}}</mat-label>\n <mat-chip-grid #memberChipGrid>\n @for (member of groupMembers(); track member) {\n <mat-chip-row [editable]=\"false\"><div class=\"chip\">{{member}}</div></mat-chip-row>\n }\n <input [matChipInputFor]=\"memberChipGrid\" readonly/>\n </mat-chip-grid>\n </mat-form-field>\n @if (error()) {\n <p class=\"error\">{{ error() }}</p>\n }\n </form>\n </main>\n <footer>\n <button ymtButton=\"secondary\" [disabled]=\"busy()\" (click)=\"close()\">\n {{ \"yuv.app.user-management.users.action.button.cancel\" | translate }}\n </button>\n <button ymtButton=\"primary\" [disabled]=\"disabledSubmit()\" (click)=\"updateGroup()\">\n {{ 'yuv.app.user-management.users.action.button.save' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host{display:block;position:relative}:host main form{padding:var(--ymt-spacing-m)}:host main form .yuv-form-field{width:100%;margin:var(--ymt-spacing-xs) 0}:host main form .readonly-field{opacity:.5;pointer-events:none}:host main form .readonly-label{pointer-events:none}:host main form .error{color:var(--ymt-on-danger-container);background-color:var(--ymt-danger-container);padding:var(--ymt-spacing-m);border-radius:var(--ymt-corner-xs)}:host main form .roles-section{margin:var(--ymt-spacing-m) 0}:host main form .roles-section .roles-label{display:block;font-size:12px;font-weight:400;color:#0009;margin-bottom:var(--ymt-spacing-xs)}:host main form .roles-section.has-error .roles-label{color:var(--ymt-danger)}:host main form .roles-section.has-error ymusrmgmt-edit-user-roles{border:2px solid var(--ymt-danger);border-radius:var(--ymt-corner-xs);display:block}:host main form .roles-section .roles-error{color:var(--ymt-danger);font-size:12px;margin-top:var(--ymt-spacing-xs);padding-left:var(--ymt-spacing-m)}\n"] }]
1164
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
1165
+ type: Inject,
1166
+ args: [MAT_DIALOG_DATA]
1167
+ }] }] });
1168
+
1169
+ class YuvGroupsPageComponent {
1170
+ layoutSettingsID = APP_ID + '#root.layout.settings';
1171
+ #logger = inject(Logger);
1172
+ #userManagementService = inject(YuvUserManagementService);
1173
+ #translateService = inject(TranslateService);
1174
+ #dialog = inject(MatDialog);
1175
+ #notificationService = inject(NotificationService);
1176
+ #userService = inject(UserService);
1177
+ #confirmService = inject(ConfirmService);
1178
+ groupDetailsComponent;
1179
+ actions = [];
1180
+ pagination = { total: 0, pages: 0, page: 0 };
1181
+ busy = signal(false, ...(ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []));
1182
+ displayedColumns = ['name', 'description', 'id'];
1183
+ icons = {
1184
+ ...APP_ICONS,
1185
+ };
1186
+ dataSource = signal([], ...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
1187
+ selection = signal(new SelectionModel(false, undefined), ...(ngDevMode ? [{ debugName: "selection" }] : /* istanbul ignore next */ []));
1188
+ enableDetails = signal(false, ...(ngDevMode ? [{ debugName: "enableDetails" }] : /* istanbul ignore next */ []));
1189
+ layoutOptions = {
1190
+ resizable: true,
1191
+ detailsSize: 25,
1192
+ detailsMinSize: 25,
1193
+ detailsMaxSize: 75
1194
+ };
1195
+ #query = { term: '' };
1196
+ #updateActions(selectedGroup) {
1197
+ if (!selectedGroup) {
1198
+ this.actions = [];
1199
+ return;
1200
+ }
1201
+ const editAction = {
1202
+ id: 'yuv.app.groups.action.edit',
1203
+ icon: APP_ICONS.actionEditGroup,
1204
+ label: this.#translateService.instant('yuv.app.user-management.groups.action.edit.label'),
1205
+ callback: () => this.editSelectedGroup(),
1206
+ };
1207
+ this.actions = [editAction];
1208
+ }
1209
+ createNewGroup() {
1210
+ this.#logger.debug('Create new group ...');
1211
+ this.#dialog.open(CreateGroupComponent, {
1212
+ width: '400px',
1213
+ maxWidth: '90vw',
1214
+ }).afterClosed().subscribe((createdGroupId) => {
1215
+ if (createdGroupId) {
1216
+ this.#logger.debug("New group created with ID: " + createdGroupId);
1217
+ this.#notificationService.success(this.#translateService.instant('yuv.app.user-management.group.action.create.success'));
1218
+ this.refresh();
1219
+ }
1220
+ });
1221
+ }
1222
+ editSelectedGroup() {
1223
+ const selected = this.selection().hasValue() ? this.selection().selected[0] : undefined;
1224
+ if (selected) {
1225
+ this.#logger.debug(`Edit selected user with id '${selected.id}'...`);
1226
+ this.#dialog.open(EditGroupComponent, {
1227
+ width: '600px',
1228
+ maxWidth: '90vw',
1229
+ data: {
1230
+ group: this.groupDetailsComponent.groupDetails()
1231
+ },
1232
+ }).afterClosed().subscribe((editedGroupId) => {
1233
+ if (editedGroupId) {
1234
+ this.#logger.debug("Group edited with ID: " + editedGroupId);
1235
+ this.#notificationService.success(this.#translateService.instant('yuv.app.user-management.groups.action.edit.success', { name: selected.name }));
1236
+ this.refresh();
1237
+ }
1238
+ });
1239
+ }
1240
+ }
1241
+ deleteSelectedGroup() {
1242
+ const selected = this.selection().hasValue() ? this.selection().selected[0] : undefined;
1243
+ if (selected) {
1244
+ this.#logger.debug(`Delete selected group with id '${selected.id}'...`);
1245
+ this.#userManagementService.deleteGroup(selected).subscribe({
1246
+ next: (result) => {
1247
+ if (result) {
1248
+ this.#notificationService.success(this.#translateService.instant('yuv.app.user-management.groups.action.delete.success', { name: selected.name }));
1249
+ this.deselect();
1250
+ const currentPage = this.pagination?.page || 0;
1251
+ const targetPage = (currentPage > 0 && this.dataSource().length === 1) ? currentPage - 1 : currentPage;
1252
+ this.#loadGroupList(targetPage);
1253
+ }
1254
+ },
1255
+ error: (e) => {
1256
+ this.#logger.error(`Failed to delete group with id '${selected.id}'`, e);
1257
+ this.#notificationService.error(this.#translateService.instant('yuv.app.user-management.groups.action.delete.error', { name: selected.name }));
1258
+ }
1259
+ });
1260
+ }
1261
+ }
1262
+ select(row) {
1263
+ if (this.selection().isSelected(row)) {
1264
+ this.deselect();
1265
+ }
1266
+ else {
1267
+ this.selection().select(row);
1268
+ this.#updateActions(row);
1269
+ }
1270
+ this.enableDetails.set(true);
1271
+ }
1272
+ deselect() {
1273
+ this.selection().clear();
1274
+ this.#updateActions(undefined);
1275
+ }
1276
+ isSelected(row) {
1277
+ return this.selection().selected?.some(item => item.id === row.id);
1278
+ }
1279
+ refresh() {
1280
+ this.#loadGroupList(this.pagination?.page || 0);
1281
+ }
1282
+ refreshGroupDetails() {
1283
+ if (this.groupDetailsComponent) {
1284
+ this.groupDetailsComponent.refresh();
1285
+ }
1286
+ }
1287
+ getPageSize() {
1288
+ return YuvUserManagementService.DEFAULT_PAGE_SIZE;
1289
+ }
1290
+ onChangePage($event) {
1291
+ const { pageIndex } = $event;
1292
+ this.#loadGroupList(pageIndex);
1293
+ }
1294
+ onQueryChange(q) {
1295
+ this.#query.term = q.term || '';
1296
+ this.#loadGroupList(0);
1297
+ }
1298
+ ngOnInit() {
1299
+ this.#loadGroupList(0);
1300
+ }
1301
+ #loadGroupList(page) {
1302
+ this.busy.set(true);
1303
+ this.#userManagementService.fetchGroups(page, this.#query.term).subscribe({
1304
+ next: (response) => {
1305
+ console.log(`fetched groups: ${response}`);
1306
+ this.dataSource.set(response.objects);
1307
+ this.pagination = {
1308
+ total: response.totalNumItems,
1309
+ pages: Math.ceil(response.totalNumItems / YuvUserManagementService.DEFAULT_PAGE_SIZE),
1310
+ page: page
1311
+ };
1312
+ },
1313
+ error: (e) => {
1314
+ this.#logger.error('Failed to fetch groups', e);
1315
+ this.busy.set(false);
1316
+ },
1317
+ complete: () => {
1318
+ const selected = this.selection().hasValue() ? this.selection().selected[0] : undefined;
1319
+ if (selected && this.dataSource().some(g => g.id === selected.id)) {
1320
+ const updatedSelected = this.dataSource().find(g => g.id === selected.id);
1321
+ this.select(updatedSelected);
1322
+ this.refreshGroupDetails();
1323
+ }
1324
+ else {
1325
+ this.select(this.dataSource()[0]);
1326
+ }
1327
+ this.busy.set(false);
1328
+ },
1329
+ });
1330
+ }
1331
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: YuvGroupsPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1332
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.12", type: YuvGroupsPageComponent, isStandalone: true, selector: "ymusrmgmt-groups", host: { properties: { "class.busy": "!busy()", "class.pagination": "this.pagination" } }, viewQueries: [{ propertyName: "groupDetailsComponent", first: true, predicate: GroupDetailsComponent, descendants: true }], ngImport: i0, template: "<ng-template yuvAppHeaderSlot=\"search\">\n</ng-template>\n\n<ymt-master-details-layout [yuvBusyOverlay]=\"busy()\"\n [gutterSize]=\"16\"\n [options]=\"layoutOptions\"\n [layoutSettingsID]=\"layoutSettingsID\">\n <ng-template ymtLayoutPane role=\"master\" [topBarActions]=\"masterPaneActions\">\n <ng-container *ngTemplateOutlet=\"masterPaneContent\"></ng-container>\n </ng-template>\n <ng-template ymtLayoutPane role=\"details\">\n <ng-container *ngTemplateOutlet=\"detailsPaneContent\"></ng-container>\n </ng-template>\n</ymt-master-details-layout>\n\n<ng-template #masterPaneActions>\n <mat-paginator class=\"paginator\" [length]=\"pagination.total\" [pageIndex]=\"pagination.page\" [pageSize]=\"getPageSize()\" aria-label=\"Select page\" (page)=\"onChangePage($event)\" hidePageSize></mat-paginator>\n <button ymt-icon-button (click)=\"refresh()\" [matTooltip]=\"'yuv.app.user-management.groups.navigation.refresh.tooltip' | translate\"><mat-icon>{{icons.refresh}}</mat-icon></button>\n</ng-template>\n\n<ng-template #listActions>\n <yuv-overflow-menu [menuItems]=\"actions\"></yuv-overflow-menu>\n</ng-template>\n\n<ng-template #masterPaneContent>\n <ymt-pane-body>\n <mat-table [dataSource]=\"dataSource()\" class=\"group-table mat-elevation-z8\" row>\n <ng-container matColumnDef=\"state\">\n <mat-header-cell *matHeaderCellDef />\n <mat-cell *matCellDef=\"let element\"><mat-icon>{{ element.enabled ? icons.stateActive : icons.stateInactive\n }}</mat-icon></mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"name\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.groups.object.property.name' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.name}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"description\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.groups.object.property.description' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.description}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"id\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.groups.object.property.id' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.id}} </mat-cell>\n </ng-container>\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row \n *matRowDef=\"let row; columns: displayedColumns;\" \n (click.single)=\"select(row)\" \n [class.selected-row]=\"this.isSelected(row)\" class=\"group-row\">\n </mat-row>\n </mat-table>\n </ymt-pane-body>\n</ng-template>\n\n<ng-template #detailsPaneContent>\n <ymt-pane-header [icon]=\"'group'\" [title]=\"'yuv.app.user-management.groups.details.title' | translate\" [subtitle]=\"selection().selected.at(0)?.id || ('yuv.app.user-management.groups.details.empty' | translate)\" [actions]=\"listActions\"></ymt-pane-header>\n <ymt-pane-body>\n <ymusrmgmt-group-details #groupDetails [groupId]=\"selection().selected.at(0)?.id\" />\n </ymt-pane-body>\n</ng-template>", styles: [":host{--mat-table-row-item-outline-color: var(--ymt-outline-variant);height:100%;overflow:hidden;display:flex;flex-flow:column}:host ymt-master-details-layout{height:100%;padding:1rem}:host .paginator{flex:1;background:transparent}:host .group-table{overflow:auto;height:100%}:host .group-row:hover{background-color:var(--ymt-hover-background)}:host .selected-row{background-color:var(--ymt-selection-background)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i3$4.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i3$4.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i3$4.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i3$4.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i3$4.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i3$4.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i3$4.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i3$4.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i3$4.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i3$4.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i2$3.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay", "yuvBusyOverlayConfig", "yuvBusyError"], outputs: ["yuvBusyErrorDismiss"] }, { kind: "directive", type: ClickDoubleDirective, selector: "[click.single],[click.double]", inputs: ["debounceTime"], outputs: ["click.double", "click.single"] }, { kind: "component", type: GroupDetailsComponent, selector: "ymusrmgmt-group-details", inputs: ["groupId"] }, { kind: "directive", type: YmtIconButtonDirective, selector: "button[ymtIconButton],button[ymt-icon-button],a[ymtIconButton],a[ymt-icon-button]", inputs: ["disabled", "disableRipple", "aria-disabled", "disabledInteractive", "icon-button-size"] }, { kind: "ngmodule", type: YmtLayoutModule }, { kind: "component", type: i5$1.MasterDetailsLayoutComponent, selector: "ymt-master-details-layout", inputs: ["layoutSettingsID", "options", "direction", "gutterSize", "detailsActive"], outputs: ["detailsActiveChange"] }, { kind: "directive", type: i5$1.YmtLayoutPaneDirective, selector: "[ymtLayoutPane]", inputs: ["role", "topBarActions"] }, { kind: "ngmodule", type: YmtPanesModule }, { kind: "component", type: i4.YmtPaneHeaderComponent, selector: "ymt-pane-header", inputs: ["title", "icon", "subtitle", "actions", "badges"] }, { kind: "component", type: i4.YmtPaneBodyComponent, selector: "ymt-pane-body" }, { kind: "ngmodule", type: YuvClientShellModule }, { kind: "directive", type: i5.YuvAppHeaderSlotDirective, selector: "ng-template[yuvAppHeaderSlot]", inputs: ["yuvAppHeaderSlot"] }, { kind: "ngmodule", type: YuvOverflowMenuModule }, { kind: "component", type: i8.OverflowMenuComponent, selector: "yuv-overflow-menu", inputs: ["overflowIcon", "groupLabels", "menuItems", "vertical"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1333
+ }
1334
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: YuvGroupsPageComponent, decorators: [{
1335
+ type: Component,
1336
+ args: [{ selector: 'ymusrmgmt-groups', standalone: true, imports: [
1337
+ CommonModule,
1338
+ MatButtonModule,
1339
+ MatIconModule,
1340
+ MatTooltipModule,
1341
+ MatTableModule,
1342
+ MatPaginatorModule,
1343
+ MatSortModule,
1344
+ RouterModule,
1345
+ TranslatePipe,
1346
+ BusyOverlayDirective,
1347
+ ClickDoubleDirective,
1348
+ GroupDetailsComponent,
1349
+ YmtIconButtonDirective,
1350
+ YmtLayoutModule,
1351
+ YmtPanesModule,
1352
+ YuvClientShellModule,
1353
+ YuvOverflowMenuModule,
1354
+ ], host: {
1355
+ '[class.busy]': '!busy()',
1356
+ }, template: "<ng-template yuvAppHeaderSlot=\"search\">\n</ng-template>\n\n<ymt-master-details-layout [yuvBusyOverlay]=\"busy()\"\n [gutterSize]=\"16\"\n [options]=\"layoutOptions\"\n [layoutSettingsID]=\"layoutSettingsID\">\n <ng-template ymtLayoutPane role=\"master\" [topBarActions]=\"masterPaneActions\">\n <ng-container *ngTemplateOutlet=\"masterPaneContent\"></ng-container>\n </ng-template>\n <ng-template ymtLayoutPane role=\"details\">\n <ng-container *ngTemplateOutlet=\"detailsPaneContent\"></ng-container>\n </ng-template>\n</ymt-master-details-layout>\n\n<ng-template #masterPaneActions>\n <mat-paginator class=\"paginator\" [length]=\"pagination.total\" [pageIndex]=\"pagination.page\" [pageSize]=\"getPageSize()\" aria-label=\"Select page\" (page)=\"onChangePage($event)\" hidePageSize></mat-paginator>\n <button ymt-icon-button (click)=\"refresh()\" [matTooltip]=\"'yuv.app.user-management.groups.navigation.refresh.tooltip' | translate\"><mat-icon>{{icons.refresh}}</mat-icon></button>\n</ng-template>\n\n<ng-template #listActions>\n <yuv-overflow-menu [menuItems]=\"actions\"></yuv-overflow-menu>\n</ng-template>\n\n<ng-template #masterPaneContent>\n <ymt-pane-body>\n <mat-table [dataSource]=\"dataSource()\" class=\"group-table mat-elevation-z8\" row>\n <ng-container matColumnDef=\"state\">\n <mat-header-cell *matHeaderCellDef />\n <mat-cell *matCellDef=\"let element\"><mat-icon>{{ element.enabled ? icons.stateActive : icons.stateInactive\n }}</mat-icon></mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"name\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.groups.object.property.name' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.name}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"description\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.groups.object.property.description' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.description}} </mat-cell>\n </ng-container>\n <ng-container matColumnDef=\"id\">\n <mat-header-cell *matHeaderCellDef>{{'yuv.app.user-management.groups.object.property.id' | translate\n }}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\"> {{element.id}} </mat-cell>\n </ng-container>\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row \n *matRowDef=\"let row; columns: displayedColumns;\" \n (click.single)=\"select(row)\" \n [class.selected-row]=\"this.isSelected(row)\" class=\"group-row\">\n </mat-row>\n </mat-table>\n </ymt-pane-body>\n</ng-template>\n\n<ng-template #detailsPaneContent>\n <ymt-pane-header [icon]=\"'group'\" [title]=\"'yuv.app.user-management.groups.details.title' | translate\" [subtitle]=\"selection().selected.at(0)?.id || ('yuv.app.user-management.groups.details.empty' | translate)\" [actions]=\"listActions\"></ymt-pane-header>\n <ymt-pane-body>\n <ymusrmgmt-group-details #groupDetails [groupId]=\"selection().selected.at(0)?.id\" />\n </ymt-pane-body>\n</ng-template>", styles: [":host{--mat-table-row-item-outline-color: var(--ymt-outline-variant);height:100%;overflow:hidden;display:flex;flex-flow:column}:host ymt-master-details-layout{height:100%;padding:1rem}:host .paginator{flex:1;background:transparent}:host .group-table{overflow:auto;height:100%}:host .group-row:hover{background-color:var(--ymt-hover-background)}:host .selected-row{background-color:var(--ymt-selection-background)!important}\n"] }]
1357
+ }], propDecorators: { groupDetailsComponent: [{
1358
+ type: ViewChild,
1359
+ args: [GroupDetailsComponent]
1360
+ }], pagination: [{
1361
+ type: HostBinding,
1362
+ args: ['class.pagination']
1363
+ }] } });
1364
+
823
1365
  const YuvUserManagementRoutes = [
824
1366
  {
825
1367
  path: '',
826
1368
  component: YuvUserManagementComponent,
827
1369
  children: [
828
1370
  { path: 'users', component: YuvUsersPageComponent },
1371
+ { path: 'groups', component: YuvGroupsPageComponent },
829
1372
  { path: '', redirectTo: 'users', pathMatch: 'full' }
830
1373
  ]
831
1374
  }