diff --git a/alfa-client/libs/admin/settings/src/lib/admin-settings.module.ts b/alfa-client/libs/admin/settings/src/lib/admin-settings.module.ts index 40254fba8ff106cd0ff5ad7f6c9c471e5352c9e0..321e7c04c5850b85027d827f2bc43e971cdef1b1 100644 --- a/alfa-client/libs/admin/settings/src/lib/admin-settings.module.ts +++ b/alfa-client/libs/admin/settings/src/lib/admin-settings.module.ts @@ -8,15 +8,9 @@ import { RouterModule } from '@angular/router'; import KcAdminClient from '@keycloak/keycloak-admin-client'; import { ButtonWithSpinnerComponent, TextareaEditorComponent } from '@ods/component'; import { MailboxIconComponent, PersonIconComponent, TextInputComponent } from '@ods/system'; -import { - createSettingListResourceService, - SettingListResourceService, -} from './admin-settings-resource.service'; +import { createSettingListResourceService, SettingListResourceService } from './admin-settings-resource.service'; import { SettingsService } from './admin-settings.service'; -import { - ConfigurationResourceService, - createConfigurationResourceService, -} from './configuration/configuration-resource.service'; +import { ConfigurationResourceService, createConfigurationResourceService } from './configuration/configuration-resource.service'; import { ConfigurationService } from './configuration/configuration.service'; import { OrganisationseinheitContainerComponent } from './organisationseinheit/organisationseinheit-container/organisationseinheit-container.component'; import { OrganisationseinheitFormComponent } from './organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component'; @@ -24,10 +18,7 @@ import { OrganisationseinheitListComponent } from './organisationseinheit/organi import { PostfachContainerComponent } from './postfach/postfach-container/postfach-container.component'; import { PostfachFormComponent } from './postfach/postfach-container/postfach-form/postfach-form.component'; import { PostfachSignaturComponent } from './postfach/postfach-container/postfach-form/postfach-signatur/postfach-signatur.component'; -import { - createPostfachResourceService, - PostfachResourceService, -} from './postfach/postfach-resource.service'; +import { createPostfachResourceService, PostfachResourceService } from './postfach/postfach-resource.service'; import { PostfachService } from './postfach/postfach.service'; import { MoreItemButtonComponent } from './shared/more-menu/more-item-button/more-item-button.component'; import { MoreMenuComponent } from './shared/more-menu/more-menu.component'; @@ -36,7 +27,7 @@ import { PrimaryButtonComponent } from './shared/primary-button/primary-button.c import { SecondaryButtonComponent } from './shared/secondary-button/secondary-button.component'; import { SpinnerComponent } from './shared/spinner/spinner.component'; import { TextFieldComponent } from './shared/text-field/text-field.component'; -import { UserNamePipe } from './user/user.util'; +import { ToUserNamePipe } from './user/to-user-name.pipe'; import { UsersRolesComponent } from './users-roles/users-roles.component'; @NgModule({ @@ -66,14 +57,9 @@ import { UsersRolesComponent } from './users-roles/users-roles.component'; TextareaEditorComponent, MailboxIconComponent, PersonIconComponent, - UserNamePipe, - ], - exports: [ - PostfachContainerComponent, - OrganisationseinheitContainerComponent, - NavigationItemComponent, - UsersRolesComponent, + ToUserNamePipe, ], + exports: [PostfachContainerComponent, OrganisationseinheitContainerComponent, NavigationItemComponent, UsersRolesComponent], providers: [ ConfigurationService, SettingsService, diff --git a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.spec.ts b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.spec.ts index 126c1e2dbcc1bf491d15a23b982b8481996c078e..1c5f9731bdfef401363bc423391cf1c7a2ed0529 100644 --- a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.spec.ts +++ b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.spec.ts @@ -16,7 +16,7 @@ import { createOrganisationseinheit } from '../../../../test/user/user'; import { SecondaryButtonComponent } from '../../shared/secondary-button/secondary-button.component'; import { SpinnerComponent } from '../../shared/spinner/spinner.component'; import { Organisationseinheit } from '../../user/user.model'; -import { OrganisationseinheitService } from '../organisationseinheitService'; +import { OrganisationseinheitService } from '../organisationseinheit.service'; import { OrganisationseinheitContainerComponent } from './organisationseinheit-container.component'; import { OrganisationseinheitFormComponent } from './organisationseinheit-form/organisationseinheit-form.component'; import { OrganisationseinheitListComponent } from './organisationseinheit-list/organisationseinheit-list.component'; @@ -25,13 +25,9 @@ describe('OrganisationseinheitContainerComponent', () => { let component: OrganisationseinheitContainerComponent; let fixture: ComponentFixture<OrganisationseinheitContainerComponent>; - const organisationseinheitService: Mock<OrganisationseinheitService> = mock( - OrganisationseinheitService, - ); + const organisationseinheitService: Mock<OrganisationseinheitService> = mock(OrganisationseinheitService); - const dialogOpenButtonSelector: string = getDataTestIdOf( - 'organisationseinheit-open-dialog-button', - ); + const dialogOpenButtonSelector: string = getDataTestIdOf('organisationseinheit-open-dialog-button'); const spinnerSelector: string = getDataTestIdOf('organisationseinheit-spinner'); const organisationseinheitItems: Organisationseinheit[] = [createOrganisationseinheit()]; @@ -54,9 +50,7 @@ describe('OrganisationseinheitContainerComponent', () => { fixture = TestBed.createComponent(OrganisationseinheitContainerComponent); component = fixture.componentInstance; - organisationseinheitService.get = jest - .fn() - .mockReturnValue(of(createStateResource(organisationseinheitItems))); + organisationseinheitService.get = jest.fn().mockReturnValue(of(createStateResource(organisationseinheitItems))); fixture.detectChanges(); formComponent = getElementFromFixtureByType(fixture, OrganisationseinheitFormComponent); diff --git a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.ts b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.ts index b85e0c8447ec080e397018c686a0f44703e58840..c8dc13a8eda3ff1f0825c7282020040695df6ecd 100644 --- a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.ts +++ b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.ts @@ -2,7 +2,7 @@ import { StateResource } from '@alfa-client/tech-shared'; import { Component, OnInit, ViewChild } from '@angular/core'; import { Observable, of } from 'rxjs'; import { Organisationseinheit } from '../../user/user.model'; -import { OrganisationseinheitService } from '../organisationseinheitService'; +import { OrganisationseinheitService } from '../organisationseinheit.service'; import { OrganisationseinheitFormComponent } from './organisationseinheit-form/organisationseinheit-form.component'; @Component({ diff --git a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.spec.ts b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.spec.ts index 55b944fec8e2cb779b4293723f93f282f94d1d5d..fd81569ecb52fceecb829096f4e859aeb73fad36 100644 --- a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.spec.ts +++ b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.spec.ts @@ -8,12 +8,7 @@ import { } from '@alfa-client/test-utils'; import { DebugElement } from '@angular/core'; import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; -import { - AbstractControl, - FormsModule, - ReactiveFormsModule, - UntypedFormGroup, -} from '@angular/forms'; +import { AbstractControl, FormsModule, ReactiveFormsModule, UntypedFormGroup } from '@angular/forms'; import { ButtonWithSpinnerComponent } from '@ods/component'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { MockComponent, ngMocks } from 'ng-mocks'; @@ -21,18 +16,16 @@ import { of, throwError } from 'rxjs'; import { createOrganisationseinheit } from '../../../../../test/user/user'; import { TextFieldComponent } from '../../../shared/text-field/text-field.component'; import { Organisationseinheit } from '../../../user/user.model'; -import { OrganisationseinheitService } from '../../organisationseinheitService'; +import { OrganisationseinheitService } from '../../organisationseinheit.service'; import { OrganisationseinheitFormComponent } from './organisationseinheit-form.component'; -import { OrganisationseinheitFormservice } from './organisationseinheit.formservice'; +import { OrganisationseinheitFormService } from './organisationseinheit-form.service'; describe('OrganisationseinheitFormComponent', () => { let component: OrganisationseinheitFormComponent; let fixture: ComponentFixture<OrganisationseinheitFormComponent>; let form: UntypedFormGroup; - const organisationseinheitService: Mock<OrganisationseinheitService> = mock( - OrganisationseinheitService, - ); + const organisationseinheitService: Mock<OrganisationseinheitService> = mock(OrganisationseinheitService); const saveButtonSelector: string = getDataTestIdOf('organisationseinheit-save-button'); const closeButtonSelector: string = getDataTestIdOf('organisationseinheit-close-button'); @@ -64,34 +57,20 @@ describe('OrganisationseinheitFormComponent', () => { describe('form element', () => { const fields: string[][] = [ - [ - OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD, - 'Name', - 'organisationseinheit-name', - ], - [ - OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD, - 'OrganisationseinheitID', - 'organisationseinheit-id', - ], + [OrganisationseinheitFormService.ORGANISATIONSEINHEIT_NAME_FIELD, 'Name', 'organisationseinheit-name'], + [OrganisationseinheitFormService.ORGANISATIONSEINHEIT_IDS_FIELD, 'OrganisationseinheitID', 'organisationseinheit-id'], ]; - it.each(fields)( - 'should have label for field "%s" with name "%s"', - (fieldName: string, text: string, inputId: string) => { - const textFieldElement = getElementFromFixture(fixture, getDataTestIdOf(inputId)); - expect(textFieldElement.getAttribute('label')).toBe(text); - }, - ); + it.each(fields)('should have label for field "%s" with name "%s"', (fieldName: string, text: string, inputId: string) => { + const textFieldElement = getElementFromFixture(fixture, getDataTestIdOf(inputId)); + expect(textFieldElement.getAttribute('label')).toBe(text); + }); it.each(fields)('should bind form for text-field "%s"', (fieldName, text, dataTestId) => { const fieldValue: string = `some text-field ${text}`; const formControl: AbstractControl = form.get(fieldName); - const textFieldComponent: DebugElement = getDebugElementFromFixtureByCss( - fixture, - getDataTestIdOf(dataTestId), - ); + const textFieldComponent: DebugElement = getDebugElementFromFixtureByCss(fixture, getDataTestIdOf(dataTestId)); ngMocks.change(textFieldComponent, fieldValue); expect(formControl.value).toBe(fieldValue); }); @@ -101,10 +80,7 @@ describe('OrganisationseinheitFormComponent', () => { let saveButtonComponent: ButtonWithSpinnerComponent; beforeEach(() => { - saveButtonComponent = getDebugElementFromFixtureByCss( - fixture, - saveButtonSelector, - ).componentInstance; + saveButtonComponent = getDebugElementFromFixtureByCss(fixture, saveButtonSelector).componentInstance; }); it('should call submit on click', () => { diff --git a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.ts b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.ts index 9796922d5e713c9ff2bcc2964d0c70d94f9c4572..4f4976209bc7976af17a5ce954585efbcffaff15 100644 --- a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.ts +++ b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.ts @@ -2,21 +2,20 @@ import { StateResource, createStateResource } from '@alfa-client/tech-shared'; import { AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular/core'; import { Observable, of, tap } from 'rxjs'; import { Organisationseinheit } from '../../../user/user.model'; -import { OrganisationseinheitFormservice } from './organisationseinheit.formservice'; +import { OrganisationseinheitFormService } from './organisationseinheit-form.service'; @Component({ selector: 'admin-organisationseinheit-form', templateUrl: './organisationseinheit-form.component.html', - providers: [OrganisationseinheitFormservice], + providers: [OrganisationseinheitFormService], }) export class OrganisationseinheitFormComponent implements AfterViewInit { - @Input() - organisationseinheitItems: StateResource<Organisationseinheit[]> = createStateResource([]); + @Input() organisationseinheitItems: StateResource<Organisationseinheit[]> = createStateResource([]); static CREATE_LABEL: string = 'Neue Organisationseinheit anlegen'; static EDIT_LABEL: string = 'Organisationseinheit bearbeiten'; - protected readonly OrganisationseinheitFormService = OrganisationseinheitFormservice; + protected readonly OrganisationseinheitFormService = OrganisationseinheitFormService; @ViewChild('OrganisationseinheitDialog') private dialogRef: ElementRef<HTMLDialogElement>; dialog: HTMLDialogElement; @@ -25,16 +24,14 @@ export class OrganisationseinheitFormComponent implements AfterViewInit { label: string; - constructor(public formService: OrganisationseinheitFormservice) {} + constructor(public formService: OrganisationseinheitFormService) {} ngAfterViewInit(): void { this.dialog = this.dialogRef.nativeElement; } public submit() { - this.submitInProgress$ = this.formService - .submit() - .pipe(tap((progress: boolean) => this.handleProgressChange(progress))); + this.submitInProgress$ = this.formService.submit().pipe(tap((progress: boolean) => this.handleProgressChange(progress))); } handleProgressChange(progress: boolean): void { diff --git a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.ts b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.service.ts similarity index 78% rename from alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.ts rename to alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.service.ts index 3309b9a813a1158fc08e7ca007e35d9f9f90475d..fb65fa06cc6959e5df3f029f7e2894307d140d43 100644 --- a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.ts +++ b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.service.ts @@ -2,18 +2,13 @@ import { createStateResource, isNotNil, StateResource } from '@alfa-client/tech- import { Injectable, Input } from '@angular/core'; import { AbstractControl, FormControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { catchError, Observable, of } from 'rxjs'; -import { - Organisationseinheit, - OrganisationseinheitError, - OrganisationseinheitErrorType, -} from '../../../user/user.model'; +import { Organisationseinheit, OrganisationseinheitError, OrganisationseinheitErrorType } from '../../../user/user.model'; import { getOrganisationseinheitErrorMessage } from '../../../user/user.util'; -import { OrganisationseinheitService } from '../../organisationseinheitService'; +import { OrganisationseinheitService } from '../../organisationseinheit.service'; @Injectable() -export class OrganisationseinheitFormservice { - @Input() - organisationseinheitItems: StateResource<Organisationseinheit[]> = createStateResource([]); +export class OrganisationseinheitFormService { + @Input() organisationseinheitItems: StateResource<Organisationseinheit[]> = createStateResource([]); public static readonly ORGANISATIONSEINHEIT_NAME_FIELD: string = 'name'; public static readonly ORGANISATIONSEINHEIT_IDS_FIELD: string = 'organisationseinheit'; @@ -27,8 +22,8 @@ export class OrganisationseinheitFormservice { private organisationsEinheitService: OrganisationseinheitService, ) { this.form = this.formBuilder.group({ - [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD]: new FormControl(''), - [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD]: new FormControl(''), + [OrganisationseinheitFormService.ORGANISATIONSEINHEIT_NAME_FIELD]: new FormControl(''), + [OrganisationseinheitFormService.ORGANISATIONSEINHEIT_IDS_FIELD]: new FormControl(''), }); } @@ -68,7 +63,7 @@ export class OrganisationseinheitFormservice { let valid: boolean = true; if (this.getOrganisationseinheitIds().length == 0) { - this.setError(OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD, { + this.setError(OrganisationseinheitFormService.ORGANISATIONSEINHEIT_IDS_FIELD, { errorType: OrganisationseinheitErrorType.ID_MISSING, detail: '', }); @@ -79,14 +74,12 @@ export class OrganisationseinheitFormservice { } private getName(): string { - return this.getStringFromPotentiallyEmptyField( - OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD, - ); + return this.getStringFromPotentiallyEmptyField(OrganisationseinheitFormService.ORGANISATIONSEINHEIT_NAME_FIELD); } private getOrganisationseinheitIds(): string[] { return this.splitOrganisationseinheitIds( - this.form.get(OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD).value ?? '', + this.form.get(OrganisationseinheitFormService.ORGANISATIONSEINHEIT_IDS_FIELD).value ?? '', ); } @@ -103,7 +96,7 @@ export class OrganisationseinheitFormservice { error.errorType === OrganisationseinheitErrorType.NAME_CONFLICT || error.errorType === OrganisationseinheitErrorType.NAME_MISSING ) { - this.setError(OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD, error); + this.setError(OrganisationseinheitFormService.ORGANISATIONSEINHEIT_NAME_FIELD, error); } } @@ -125,9 +118,8 @@ export class OrganisationseinheitFormservice { this.reset(); this.source = organisationseinheit; this.form.patchValue({ - [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD]: organisationseinheit.name, - [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD]: - organisationseinheit.organisationseinheitIds.join(', '), + [OrganisationseinheitFormService.ORGANISATIONSEINHEIT_NAME_FIELD]: organisationseinheit.name, + [OrganisationseinheitFormService.ORGANISATIONSEINHEIT_IDS_FIELD]: organisationseinheit.organisationseinheitIds.join(', '), }); } diff --git a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.spec.ts b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.spec.ts index a58bb6a57f7882af61b8ef525f97b23f06f2580c..30b0562d0e2ab18a08381eb1bded287beb3dcd68 100644 --- a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.spec.ts +++ b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.spec.ts @@ -5,38 +5,25 @@ import { AbstractControl, FormBuilder } from '@angular/forms'; import { hot } from 'jest-marbles'; import { singleCold, singleHot } from 'libs/tech-shared/test/marbles'; import { Observable, lastValueFrom, throwError } from 'rxjs'; -import { - createOrganisationseinheit, - createOrganisationseinheitError, -} from '../../../../../test/user/user'; -import { - Organisationseinheit, - OrganisationseinheitError, - OrganisationseinheitErrorType, -} from '../../../user/user.model'; +import { createOrganisationseinheit, createOrganisationseinheitError } from '../../../../../test/user/user'; +import { Organisationseinheit, OrganisationseinheitError, OrganisationseinheitErrorType } from '../../../user/user.model'; import { getOrganisationseinheitErrorMessage } from '../../../user/user.util'; -import { OrganisationseinheitService } from '../../organisationseinheitService'; -import { OrganisationseinheitFormservice } from './organisationseinheit.formservice'; +import { OrganisationseinheitService } from '../../organisationseinheit.service'; +import { OrganisationseinheitFormService } from './organisationseinheit-form.service'; describe('OrganisationseinheitFormService', () => { - let formService: OrganisationseinheitFormservice; + let formService: OrganisationseinheitFormService; let organisationseinheit: Organisationseinheit; - const organisationseinheitService: Mock<OrganisationseinheitService> = mockResourceService( - OrganisationseinheitService, - ); + const organisationseinheitService: Mock<OrganisationseinheitService> = mockResourceService(OrganisationseinheitService); const formBuilder: FormBuilder = new FormBuilder(); beforeEach(() => { - formService = new OrganisationseinheitFormservice( - formBuilder, - useFromMock(organisationseinheitService), - ); + formService = new OrganisationseinheitFormService(formBuilder, useFromMock(organisationseinheitService)); organisationseinheit = createOrganisationseinheit(); formService.form.setValue({ - [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD]: organisationseinheit.name, - [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD]: - organisationseinheit.organisationseinheitIds.join(','), + [OrganisationseinheitFormService.ORGANISATIONSEINHEIT_NAME_FIELD]: organisationseinheit.name, + [OrganisationseinheitFormService.ORGANISATIONSEINHEIT_IDS_FIELD]: organisationseinheit.organisationseinheitIds.join(','), }); }); @@ -99,14 +86,13 @@ describe('OrganisationseinheitFormService', () => { const hasIdMissingError = () => formService.form.hasError( OrganisationseinheitErrorType.ID_MISSING, - OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD, + OrganisationseinheitFormService.ORGANISATIONSEINHEIT_IDS_FIELD, ); describe('without organisationeinheitIds', () => { beforeEach(() => { formService.form.setValue({ - [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD]: - organisationseinheit.name, - [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD]: ',', + [OrganisationseinheitFormService.ORGANISATIONSEINHEIT_NAME_FIELD]: organisationseinheit.name, + [OrganisationseinheitFormService.ORGANISATIONSEINHEIT_IDS_FIELD]: ',', }); }); @@ -185,8 +171,8 @@ describe('OrganisationseinheitFormService', () => { it('should call create organisationseinheit with empty form', () => { formService.form.setValue({ - [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD]: null, - [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD]: null, + [OrganisationseinheitFormService.ORGANISATIONSEINHEIT_NAME_FIELD]: null, + [OrganisationseinheitFormService.ORGANISATIONSEINHEIT_IDS_FIELD]: null, }); formService.create(); @@ -221,8 +207,8 @@ describe('OrganisationseinheitFormService', () => { it('should call save organisationseinheit with empty form', () => { formService.source = createOrganisationseinheit(); formService.form.setValue({ - [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD]: null, - [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD]: null, + [OrganisationseinheitFormService.ORGANISATIONSEINHEIT_NAME_FIELD]: null, + [OrganisationseinheitFormService.ORGANISATIONSEINHEIT_IDS_FIELD]: null, }); formService.save(); @@ -243,22 +229,19 @@ describe('OrganisationseinheitFormService', () => { }); describe('handle error', () => { - it.each([ - OrganisationseinheitErrorType.NAME_CONFLICT, - OrganisationseinheitErrorType.NAME_MISSING, - ])('should set error on name field on %s', (type: OrganisationseinheitErrorType) => { - const error: OrganisationseinheitError = { - ...createOrganisationseinheitError(), - errorType: type, - }; - - formService.handleError(error); - const errorMessage = formService.form.getError( - type, - OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD, - ); - expect(errorMessage).toEqual(getOrganisationseinheitErrorMessage(error)); - }); + it.each([OrganisationseinheitErrorType.NAME_CONFLICT, OrganisationseinheitErrorType.NAME_MISSING])( + 'should set error on name field on %s', + (type: OrganisationseinheitErrorType) => { + const error: OrganisationseinheitError = { + ...createOrganisationseinheitError(), + errorType: type, + }; + + formService.handleError(error); + const errorMessage = formService.form.getError(type, OrganisationseinheitFormService.ORGANISATIONSEINHEIT_NAME_FIELD); + expect(errorMessage).toEqual(getOrganisationseinheitErrorMessage(error)); + }, + ); it('should not set error on name field for unknown errors', () => { const unknownError: OrganisationseinheitError = createOrganisationseinheitError(undefined); @@ -289,33 +272,27 @@ describe('OrganisationseinheitFormService', () => { it('should set name', () => { formService.patch(organisationseinheit); - const formControl: AbstractControl = formService.form.get( - OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD, - ); + const formControl: AbstractControl = formService.form.get(OrganisationseinheitFormService.ORGANISATIONSEINHEIT_NAME_FIELD); expect(formControl.value).toEqual(organisationseinheit.name); }); it('should set organisationseinheitIds', () => { formService.patch(organisationseinheit); - const formControl: AbstractControl = formService.form.get( - OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD, - ); + const formControl: AbstractControl = formService.form.get(OrganisationseinheitFormService.ORGANISATIONSEINHEIT_IDS_FIELD); expect(formControl.value).toEqual(organisationseinheit.organisationseinheitIds.join(', ')); }); }); describe('split organisationseinheitIds by comma', () => { it('should return', () => { - const organisationseinheitIds: string[] = - formService.splitOrganisationseinheitIds('123, 555 , 666'); + const organisationseinheitIds: string[] = formService.splitOrganisationseinheitIds('123, 555 , 666'); expect(organisationseinheitIds).toEqual(['123', '555', '666']); }); it('should filter empty organisationseinheitIds', () => { - const organisationseinheitIds: string[] = - formService.splitOrganisationseinheitIds(',55,,66,'); + const organisationseinheitIds: string[] = formService.splitOrganisationseinheitIds(',55,,66,'); expect(organisationseinheitIds).toEqual(['55', '66']); }); diff --git a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheitService.spec.ts b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit.service.spec.ts similarity index 99% rename from alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheitService.spec.ts rename to alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit.service.spec.ts index 97557340dccaf5851d41a6b9bcbf55916a161ff0..4e16cd2a3421cac02ddcd38e472322fc5942e808 100644 --- a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheitService.spec.ts +++ b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit.service.spec.ts @@ -1,7 +1,7 @@ import { mock, Mock, useFromMock } from '@alfa-client/test-utils'; import { createOrganisationseinheit } from '../../../test/user/user'; import { UserRepository } from '../user/user.repository.service'; -import { OrganisationseinheitService } from './organisationseinheitService'; +import { OrganisationseinheitService } from './organisationseinheit.service'; describe('OrganisationseinheitService', () => { let service: OrganisationseinheitService; diff --git a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheitService.ts b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit.service.ts similarity index 87% rename from alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheitService.ts rename to alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit.service.ts index 4bd882e2f5a1240c58b135c0136989a725c78fba..d07d400cdb35c40955a164a99bcd66faf933b911 100644 --- a/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheitService.ts +++ b/alfa-client/libs/admin/settings/src/lib/organisationseinheit/organisationseinheit.service.ts @@ -15,14 +15,12 @@ export class OrganisationseinheitService extends KeycloakResourceService<Organis getItemsFromKeycloak(): Observable<Organisationseinheit[]> { return this.userRepository.findOrganisationseinheitItems(); } + saveInKeycloak(organisationseinheit: Organisationseinheit): Observable<void> { return this.userRepository.saveOrganisationseinheit(organisationseinheit); } - createInKeycloak(organisationseinheit: { - name: string; - organisationseinheitIds: string[]; - }): Observable<Organisationseinheit> { + createInKeycloak(organisationseinheit: { name: string; organisationseinheitIds: string[] }): Observable<Organisationseinheit> { return this.userRepository.createOrganisationseinheit(organisationseinheit); } diff --git a/alfa-client/libs/admin/settings/src/lib/user/keycloak.resource.service.spec.ts b/alfa-client/libs/admin/settings/src/lib/user/keycloak.resource.service.spec.ts index ee8961051481fb0a1f020559d4d2f5d80eefda82..c6ee2049af224f9479f6f8782c0e8e437a32a346 100644 --- a/alfa-client/libs/admin/settings/src/lib/user/keycloak.resource.service.spec.ts +++ b/alfa-client/libs/admin/settings/src/lib/user/keycloak.resource.service.spec.ts @@ -1,10 +1,7 @@ import { fakeAsync, tick } from '@angular/core/testing'; import faker from '@faker-js/faker'; import { cold } from 'jest-marbles'; -import { - StateResource, - createEmptyStateResource, -} from 'libs/tech-shared/src/lib/resource/resource.util'; +import { StateResource, createEmptyStateResource } from 'libs/tech-shared/src/lib/resource/resource.util'; import { createDummy } from 'libs/tech-shared/test/dummy'; import { singleCold } from 'libs/tech-shared/test/marbles'; import { Observable, of } from 'rxjs'; diff --git a/alfa-client/libs/admin/settings/src/lib/user/keycloak.resource.service.ts b/alfa-client/libs/admin/settings/src/lib/user/keycloak.resource.service.ts index 914d547f4a1e962860d65437709c35bf6787c7cc..bc62384b90ed390dccad35c9acb296d74ca3a1e0 100644 --- a/alfa-client/libs/admin/settings/src/lib/user/keycloak.resource.service.ts +++ b/alfa-client/libs/admin/settings/src/lib/user/keycloak.resource.service.ts @@ -1,20 +1,11 @@ -import { - createEmptyStateResource, - createStateResource, - doIfLoadingRequired, - StateResource, -} from '@alfa-client/tech-shared'; +import { createEmptyStateResource, createStateResource, doIfLoadingRequired, StateResource } from '@alfa-client/tech-shared'; import { BehaviorSubject, first, map, Observable, startWith, tap } from 'rxjs'; export abstract class KeycloakResourceService<T> { - readonly stateResource: BehaviorSubject<StateResource<T[]>> = new BehaviorSubject( - createEmptyStateResource(), - ); - - public get() { - return this.stateResource - .asObservable() - .pipe(tap((stateResource) => this.handleChanges(stateResource))); + readonly stateResource: BehaviorSubject<StateResource<T[]>> = new BehaviorSubject(createEmptyStateResource()); + + public get(): Observable<StateResource<T[]>> { + return this.stateResource.asObservable().pipe(tap((stateResource) => this.handleChanges(stateResource))); } handleChanges(stateResource: StateResource<T[]>) { diff --git a/alfa-client/libs/admin/settings/src/lib/user/to-user-name.pipe.spec.ts b/alfa-client/libs/admin/settings/src/lib/user/to-user-name.pipe.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..81012d2754951d89e18992d26fea0fd7b2248bf0 --- /dev/null +++ b/alfa-client/libs/admin/settings/src/lib/user/to-user-name.pipe.spec.ts @@ -0,0 +1,23 @@ +import { createUser } from '../../../test/user/user'; +import { ToUserNamePipe } from './to-user-name.pipe'; +import { User } from './user.model'; + +describe('UserNamePipe', () => { + it('should return user name', () => { + const user: User = { ...createUser(), firstName: 'Max', lastName: 'Mustermann' }; + const userNamePipe: ToUserNamePipe = new ToUserNamePipe(); + + const result: string = userNamePipe.transform(user); + + expect(result).toBe('Max Mustermann'); + }); + + it('should return username for user without firstName and lastName', () => { + const user: User = { ...createUser(), firstName: null, lastName: null }; + const userNamePipe: ToUserNamePipe = new ToUserNamePipe(); + + const result: string = userNamePipe.transform(user); + + expect(result).toBe(user.username); + }); +}); diff --git a/alfa-client/libs/admin/settings/src/lib/user/to-user-name.pipe.ts b/alfa-client/libs/admin/settings/src/lib/user/to-user-name.pipe.ts new file mode 100644 index 0000000000000000000000000000000000000000..4711ff9e5d78eea721342923a296976dde6a0389 --- /dev/null +++ b/alfa-client/libs/admin/settings/src/lib/user/to-user-name.pipe.ts @@ -0,0 +1,13 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { User } from './user.model'; + +@Pipe({ + name: 'toUserName', + standalone: true, +}) +export class ToUserNamePipe implements PipeTransform { + transform(user: User): string { + if (!user.firstName || !user.lastName) return user.username; + return `${user.firstName} ${user.lastName}`; + } +} diff --git a/alfa-client/libs/admin/settings/src/lib/user/user.model.ts b/alfa-client/libs/admin/settings/src/lib/user/user.model.ts index 308e945aa9b0f900ccfc135eeb98f713efc7e5e7..742ca490a50a84a8f9026204e573bcf729bf3c30 100644 --- a/alfa-client/libs/admin/settings/src/lib/user/user.model.ts +++ b/alfa-client/libs/admin/settings/src/lib/user/user.model.ts @@ -4,12 +4,6 @@ export interface Organisationseinheit { organisationseinheitIds: string[]; } -export interface OrganisationseinheitState { - organisationseinheitItems: Organisationseinheit[]; - loading: boolean; - updateRequired: boolean; -} - export enum OrganisationseinheitErrorType { NAME_CONFLICT = 'name-conflict', NAME_MISSING = 'name-missing', @@ -20,3 +14,13 @@ export interface OrganisationseinheitError { errorType: OrganisationseinheitErrorType; detail: string; } + +export interface User { + id: string; + username: string; + email: string; + firstName: string; + lastName: string; + groups?: string[]; + roles?: string[]; +} diff --git a/alfa-client/libs/admin/settings/src/lib/user/user.repository.service.ts b/alfa-client/libs/admin/settings/src/lib/user/user.repository.service.ts index e6c95427e7397272adfa1918fc560591f441d3d2..71badd909893e43cf4a4bf17aa6791b0d5e949b1 100644 --- a/alfa-client/libs/admin/settings/src/lib/user/user.repository.service.ts +++ b/alfa-client/libs/admin/settings/src/lib/user/user.repository.service.ts @@ -7,17 +7,8 @@ import RoleRepresentation from '@keycloak/keycloak-admin-client/lib/defs/roleRep import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation'; import { OAuthService } from 'angular-oauth2-oidc'; import { isNil } from 'lodash-es'; -import { - Observable, - OperatorFunction, - catchError, - forkJoin, - from, - map, - mergeMap, - throwError, -} from 'rxjs'; -import { Organisationseinheit, OrganisationseinheitError } from './user.model'; +import { Observable, OperatorFunction, catchError, forkJoin, from, map, mergeMap, throwError } from 'rxjs'; +import { Organisationseinheit, OrganisationseinheitError, User } from './user.model'; import { KEYCLOAK_CREATE_GROUPS_ERROR_STATUS } from './user.util'; @Injectable({ @@ -48,9 +39,7 @@ export class UserRepository { public findOrganisationseinheitItems(): Observable<Organisationseinheit[]> { return from(this.kcAdminClient.groups.find({ briefRepresentation: false })).pipe( map((reps: GroupRepresentation[]) => - reps.map((rep: GroupRepresentation) => - this.mapGroupRepresentationToOrganisationseinheit(rep), - ), + reps.map((rep: GroupRepresentation) => this.mapGroupRepresentationToOrganisationseinheit(rep)), ), ); } @@ -106,13 +95,28 @@ export class UserRepository { }; } - public getUsers(): Observable<UserRepresentation[]> { + public getUsers(): Observable<User[]> { return from(this.kcAdminClient.users.find()).pipe( + map((userReps: UserRepresentation[]) => this.mapUserRepresentationArrayToUserArray(userReps)), mergeMap((users) => forkJoin(users.map((users) => this.addInformationToUser(users)))), ); } - private addInformationToUser(user: UserRepresentation) { + private mapUserRepresentationArrayToUserArray(userReps: UserRepresentation[]): User[] { + return userReps.map((userRep) => { + return { + id: userRep.id, + email: userRep.email, + username: userRep.username, + firstName: userRep.firstName, + lastName: userRep.lastName, + groups: null, + roles: null, + }; + }); + } + + private addInformationToUser(user: User) { return forkJoin([this.getUserGroups(user), this.getAlfaClientRoles(user)]).pipe( map(([groups, roles]) => ({ ...user, @@ -122,17 +126,15 @@ export class UserRepository { ); } - private getUserGroups(user: UserRepresentation): Observable<string[]> { + private getUserGroups(user: User): Observable<string[]> { return from(this.kcAdminClient.users.listGroups({ id: user.id })).pipe( map((groups: GroupRepresentation[]) => groups.map((group) => group.name)), ); } - private getAlfaClientRoles(user: UserRepresentation): Observable<string[]> { + private getAlfaClientRoles(user: User): Observable<string[]> { return from(this.kcAdminClient.users.listRoleMappings({ id: user.id })).pipe( - map((clientMappings: MappingsRepresentation) => - this.mapToAlfaClientRoleNames(clientMappings), - ), + map((clientMappings: MappingsRepresentation) => this.mapToAlfaClientRoleNames(clientMappings)), ); } @@ -141,8 +143,6 @@ export class UserRepository { return []; } - return roleMappings.clientMappings['alfa'].mappings.map( - (role: RoleRepresentation) => role.name, - ); + return roleMappings.clientMappings['alfa'].mappings.map((role: RoleRepresentation) => role.name); } } diff --git a/alfa-client/libs/admin/settings/src/lib/user/user.repository.spec.ts b/alfa-client/libs/admin/settings/src/lib/user/user.repository.spec.ts index f46a0d548e0d229796703651da12a32b3e305b74..3a5e2f1130788c375e268b06561d8f4d17ac3c1a 100644 --- a/alfa-client/libs/admin/settings/src/lib/user/user.repository.spec.ts +++ b/alfa-client/libs/admin/settings/src/lib/user/user.repository.spec.ts @@ -5,7 +5,6 @@ import KcAdminClient, { NetworkError } from '@keycloak/keycloak-admin-client'; import { TokenProvider } from '@keycloak/keycloak-admin-client/lib/client'; import GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation'; import MappingsRepresentation from '@keycloak/keycloak-admin-client/lib/defs/mappingsRepresentation'; -import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation'; import { Groups } from '@keycloak/keycloak-admin-client/lib/resources/groups'; import { OAuthService } from 'angular-oauth2-oidc'; import { Observable, OperatorFunction, catchError, firstValueFrom, of, throwError } from 'rxjs'; @@ -14,13 +13,9 @@ import { createNetworkError, createOrganisationseinheit, createOrganisationseinheitError, - createUserRepresentation, + createUser, } from '../../../test/user/user'; -import { - Organisationseinheit, - OrganisationseinheitError, - OrganisationseinheitErrorType, -} from './user.model'; +import { Organisationseinheit, OrganisationseinheitError, OrganisationseinheitErrorType, User } from './user.model'; import { UserRepository } from './user.repository.service'; describe('UserRepository', () => { @@ -68,39 +63,33 @@ describe('UserRepository', () => { let expectedOrganisationseinheit: Organisationseinheit = createOrganisationseinheit(); it('should map field "id"', () => { - const organisationseinheit: Organisationseinheit = - repository.mapGroupRepresentationToOrganisationseinheit({ - id: expectedOrganisationseinheit.id, - }); + const organisationseinheit: Organisationseinheit = repository.mapGroupRepresentationToOrganisationseinheit({ + id: expectedOrganisationseinheit.id, + }); expect(organisationseinheit.id).toEqual(expectedOrganisationseinheit.id); }); it('should map field "name"', () => { - const organisationseinheit: Organisationseinheit = - repository.mapGroupRepresentationToOrganisationseinheit({ - name: expectedOrganisationseinheit.name, - }); + const organisationseinheit: Organisationseinheit = repository.mapGroupRepresentationToOrganisationseinheit({ + name: expectedOrganisationseinheit.name, + }); expect(organisationseinheit.name).toEqual(expectedOrganisationseinheit.name); }); it('should map field "organisationseinheitIds"', () => { - const organisationseinheit: Organisationseinheit = - repository.mapGroupRepresentationToOrganisationseinheit({ - attributes: { - organisationseinheitId: expectedOrganisationseinheit.organisationseinheitIds, - }, - }); + const organisationseinheit: Organisationseinheit = repository.mapGroupRepresentationToOrganisationseinheit({ + attributes: { + organisationseinheitId: expectedOrganisationseinheit.organisationseinheitIds, + }, + }); - expect(organisationseinheit.organisationseinheitIds).toEqual( - expectedOrganisationseinheit.organisationseinheitIds, - ); + expect(organisationseinheit.organisationseinheitIds).toEqual(expectedOrganisationseinheit.organisationseinheitIds); }); it('should map missing organisationseinheitIds to empty list', () => { - const organisationseinheit: Organisationseinheit = - repository.mapGroupRepresentationToOrganisationseinheit({}); + const organisationseinheit: Organisationseinheit = repository.mapGroupRepresentationToOrganisationseinheit({}); expect(organisationseinheit.organisationseinheitIds).toEqual([]); }); @@ -113,16 +102,13 @@ describe('UserRepository', () => { createOrganisationseinheit(), ]; - const groupReps: GroupRepresentation[] = - organisationseinheitItems.map(createGroupRepresentation); + const groupReps: GroupRepresentation[] = organisationseinheitItems.map(createGroupRepresentation); it('should return mapped organisationseinheit search result', async () => { const findMock: jest.Mock = jest.fn().mockReturnValue(Promise.resolve(groupReps)); mockGroupsFunc('find', findMock); - const groupsResult: Organisationseinheit[] = await firstValueFrom( - repository.findOrganisationseinheitItems(), - ); + const groupsResult: Organisationseinheit[] = await firstValueFrom(repository.findOrganisationseinheitItems()); expect(groupsResult).toEqual(groupsResult); }); @@ -170,9 +156,7 @@ describe('UserRepository', () => { it('should pipe rethrowMappedGroupsError', (done) => { const updateMock: jest.Mock = jest.fn(() => Promise.reject(networkError)); mockGroupsFunc('update', updateMock); - repository.rethrowMappedGroupsError = jest - .fn() - .mockReturnValue(catchError(() => throwError(() => error))); + repository.rethrowMappedGroupsError = jest.fn().mockReturnValue(catchError(() => throwError(() => error))); repository.saveOrganisationseinheit(saveGroup).subscribe({ error: (err) => { @@ -206,9 +190,7 @@ describe('UserRepository', () => { }); it('should return mapped organisationseinheit result', async () => { - const createMock: jest.Mock = jest.fn(() => - Promise.resolve({ id: newOrganisationseinheit.id }), - ); + const createMock: jest.Mock = jest.fn(() => Promise.resolve({ id: newOrganisationseinheit.id })); mockGroupsFunc('create', createMock); const newGroupResult: Organisationseinheit = await firstValueFrom( @@ -224,9 +206,7 @@ describe('UserRepository', () => { it('should pipe rethrowMappedGroupsError', (done) => { const createMock: jest.Mock = jest.fn(() => Promise.reject(networkError)); mockGroupsFunc('create', createMock); - repository.rethrowMappedGroupsError = jest - .fn() - .mockReturnValue(catchError(() => throwError(() => error))); + repository.rethrowMappedGroupsError = jest.fn().mockReturnValue(catchError(() => throwError(() => error))); repository .createOrganisationseinheit({ @@ -308,9 +288,7 @@ describe('UserRepository', () => { const deleteOrganisationseinheit: Organisationseinheit = createOrganisationseinheit(); it('should call kcAdminClient.groups.del', async () => { - const delMock: jest.Mock = jest.fn(() => - Promise.resolve({ id: deleteOrganisationseinheit.id }), - ); + const delMock: jest.Mock = jest.fn(() => Promise.resolve({ id: deleteOrganisationseinheit.id })); mockGroupsFunc('del', delMock); await firstValueFrom(repository.deleteOrganisationseinheit(deleteOrganisationseinheit.id)); @@ -326,17 +304,15 @@ describe('UserRepository', () => { jest.fn(() => Promise.resolve(null)), ); - const voidResult = await firstValueFrom( - repository.deleteOrganisationseinheit(deleteOrganisationseinheit.id), - ); + const voidResult = await firstValueFrom(repository.deleteOrganisationseinheit(deleteOrganisationseinheit.id)); expect(voidResult).toBeNull(); }); }); describe('getUsers', () => { - const userRep: UserRepresentation = createUserRepresentation(); - const userRepArray: UserRepresentation[] = [userRep, userRep, userRep]; + const userRep: User = createUser(); + const userRepArray: User[] = [userRep, userRep, userRep]; const group = faker.random.word(); const role = faker.random.word(); const groupRep: GroupRepresentation[] = [{ name: group }]; @@ -374,10 +350,8 @@ describe('UserRepository', () => { })); it('should return users with groups and roles', (done) => { - repository.getUsers().subscribe((users: UserRepresentation[]) => { - users.forEach((user) => - expect(user).toEqual({ ...userRep, groups: [group], roles: [role] }), - ); + repository.getUsers().subscribe((users: User[]) => { + users.forEach((user) => expect(user).toEqual({ ...userRep, groups: [group], roles: [role] })); done(); }); }); @@ -386,7 +360,7 @@ describe('UserRepository', () => { kcAdminClient.users['listGroups'] = jest.fn().mockReturnValue(Promise.resolve([])); kcAdminClient.users['listRoleMappings'] = jest.fn().mockReturnValue(Promise.resolve({})); - repository.getUsers().subscribe((users: UserRepresentation[]) => { + repository.getUsers().subscribe((users: User[]) => { users.forEach((user) => expect(user).toEqual({ ...userRep, groups: [], roles: [] })); done(); }); diff --git a/alfa-client/libs/admin/settings/src/lib/user/user.util.spec.ts b/alfa-client/libs/admin/settings/src/lib/user/user.util.spec.ts index 5bc9621ac6e0d0c199dc63eb8ba735382215fa44..f4d9cc168ecb9eaca45f28cead659716ff232845 100644 --- a/alfa-client/libs/admin/settings/src/lib/user/user.util.spec.ts +++ b/alfa-client/libs/admin/settings/src/lib/user/user.util.spec.ts @@ -1,12 +1,7 @@ -import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation'; -import { createOrganisationseinheitError } from '../../../test/user/user'; -import { OrganisationseinheitError, OrganisationseinheitErrorType } from './user.model'; -import { - KEYCLOAK_ERROR_MESSAGES, - UserNamePipe, - getOrganisationseinheitErrorMessage, - sortUsersByLastName, -} from './user.util'; +import { EMPTY_STRING } from '@alfa-client/tech-shared'; +import { createOrganisationseinheitError, createUser } from '../../../test/user/user'; +import { OrganisationseinheitError, OrganisationseinheitErrorType, User } from './user.model'; +import { KEYCLOAK_ERROR_MESSAGES, getOrganisationseinheitErrorMessage, sortUsersByLastName } from './user.util'; describe('user util', () => { describe('get organisationseinheit error message', () => { @@ -17,6 +12,7 @@ describe('user util', () => { const expectedMessage: string = KEYCLOAK_ERROR_MESSAGES[nameConflictError.errorType]; const message: string = getOrganisationseinheitErrorMessage(nameConflictError); + expect(message).toEqual(expectedMessage); }); @@ -24,37 +20,20 @@ describe('user util', () => { const nameConflictError: OrganisationseinheitError = createOrganisationseinheitError(null); const message: string = getOrganisationseinheitErrorMessage(nameConflictError); - expect(message).toEqual(''); - }); - }); - - describe('UserNamePipe', () => { - it('should return user name', () => { - const user: UserRepresentation = { firstName: 'Max', lastName: 'Mustermann' }; - const userNamePipe = new UserNamePipe(); - - const result: string = userNamePipe.transform(user); - expect(result).toBe('Max Mustermann'); - }); - - it('should return unknown user', () => { - const emptyUser: UserRepresentation = {}; - const userNamePipe = new UserNamePipe(); - const result: string = userNamePipe.transform(emptyUser); - expect(result).toBe('Unbekannter Benutzer'); + expect(message).toEqual(EMPTY_STRING); }); }); describe('sort users by last name', () => { - const users: UserRepresentation[] = [ - { id: '1', lastName: 'Müller' }, - { id: '2', lastName: 'Schmidt' }, - { id: '3', lastName: 'Anders' }, + const users: User[] = [ + { ...createUser(), lastName: 'Müller' }, + { ...createUser(), lastName: 'Schmidt' }, + { ...createUser(), lastName: 'Anders' }, ]; it('shoud sort users by last name alphabetically ', () => { - const sortedUsers = sortUsersByLastName(users); + const sortedUsers: User[] = sortUsersByLastName(users); expect(sortedUsers[0].lastName).toBe('Anders'); expect(sortedUsers[1].lastName).toBe('Müller'); diff --git a/alfa-client/libs/admin/settings/src/lib/user/user.util.ts b/alfa-client/libs/admin/settings/src/lib/user/user.util.ts index 0454c911e3639dc0810bea4720d1d4e2eeba20ad..9878f7021e501b38d8d0938228a3c2c7c1df51b9 100644 --- a/alfa-client/libs/admin/settings/src/lib/user/user.util.ts +++ b/alfa-client/libs/admin/settings/src/lib/user/user.util.ts @@ -1,12 +1,9 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation'; -import { OrganisationseinheitError, OrganisationseinheitErrorType } from './user.model'; +import { OrganisationseinheitError, OrganisationseinheitErrorType, User } from './user.model'; export const KEYCLOAK_ERROR_MESSAGES: { [type: string]: string } = { [OrganisationseinheitErrorType.NAME_CONFLICT]: 'Der Name exisitert bereits.', [OrganisationseinheitErrorType.NAME_MISSING]: 'Bitte den Namen angeben.', - [OrganisationseinheitErrorType.ID_MISSING]: - 'Bitte mindestens eine Organisationseinheit ID angeben.', + [OrganisationseinheitErrorType.ID_MISSING]: 'Bitte mindestens eine Organisationseinheit ID angeben.', }; export const KEYCLOAK_CREATE_GROUPS_ERROR_STATUS: { @@ -20,17 +17,6 @@ export function getOrganisationseinheitErrorMessage(error: OrganisationseinheitE return KEYCLOAK_ERROR_MESSAGES[error.errorType] ?? ''; } -@Pipe({ - name: 'userName', - standalone: true, -}) -export class UserNamePipe implements PipeTransform { - transform(user: UserRepresentation): string { - if (!user.firstName || !user.lastName) return 'Unbekannter Benutzer'; - return `${user.firstName} ${user.lastName}`; - } -} - -export function sortUsersByLastName(users: UserRepresentation[]): UserRepresentation[] { +export function sortUsersByLastName(users: User[]): User[] { return users.sort((a, b) => (a.lastName ?? '').localeCompare(b.lastName ?? '')); } diff --git a/alfa-client/libs/admin/settings/src/lib/users-roles/userAndRolesService.spec.ts b/alfa-client/libs/admin/settings/src/lib/users-roles/user.service.spec.ts similarity index 71% rename from alfa-client/libs/admin/settings/src/lib/users-roles/userAndRolesService.spec.ts rename to alfa-client/libs/admin/settings/src/lib/users-roles/user.service.spec.ts index 7ab34763b5bf0c04a8b06746b8b2beb718fe3c24..9bcc8936dee39e1dbc46befe401ef16b33582178 100644 --- a/alfa-client/libs/admin/settings/src/lib/users-roles/userAndRolesService.spec.ts +++ b/alfa-client/libs/admin/settings/src/lib/users-roles/user.service.spec.ts @@ -1,21 +1,21 @@ import { mock, Mock, useFromMock } from '@alfa-client/test-utils'; import { fakeAsync, tick } from '@angular/core/testing'; -import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation'; import { of } from 'rxjs'; -import { createUserRepresentation } from '../../../test/user/user'; +import { createUser } from '../../../test/user/user'; +import { User } from '../user/user.model'; import { UserRepository } from '../user/user.repository.service'; import * as UserUtil from '../user/user.util'; -import { UserAndRolesService } from './userAndRolesService'; +import { UserService } from './user.service'; describe('OrganisationseinheitService', () => { - let service: UserAndRolesService; + let service: UserService; let repository: Mock<UserRepository>; - const user: UserRepresentation = createUserRepresentation(); + const user: User = createUser(); beforeEach(() => { repository = { ...mock(UserRepository), getUsers: jest.fn().mockReturnValue(of([user])) }; - service = new UserAndRolesService(useFromMock(repository)); + service = new UserService(useFromMock(repository)); }); describe('getItemsFromKeycloak', () => { diff --git a/alfa-client/libs/admin/settings/src/lib/users-roles/userAndRolesService.ts b/alfa-client/libs/admin/settings/src/lib/users-roles/user.service.ts similarity index 63% rename from alfa-client/libs/admin/settings/src/lib/users-roles/userAndRolesService.ts rename to alfa-client/libs/admin/settings/src/lib/users-roles/user.service.ts index 2959262b22bdd1433e8c26f10644a5dd5babfb66..83c56cc41ce3f12ec58f542164a9a113c19b75ef 100644 --- a/alfa-client/libs/admin/settings/src/lib/users-roles/userAndRolesService.ts +++ b/alfa-client/libs/admin/settings/src/lib/users-roles/user.service.ts @@ -1,27 +1,27 @@ import { Injectable } from '@angular/core'; -import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation'; import { map, Observable } from 'rxjs'; import { KeycloakResourceService } from '../user/keycloak.resource.service'; +import { User } from '../user/user.model'; import { UserRepository } from '../user/user.repository.service'; import { sortUsersByLastName } from '../user/user.util'; @Injectable({ providedIn: 'root', }) -export class UserAndRolesService extends KeycloakResourceService<UserRepresentation> { +export class UserService extends KeycloakResourceService<User> { constructor(private userRepository: UserRepository) { super(); } - getItemsFromKeycloak(): Observable<UserRepresentation[]> { + getItemsFromKeycloak(): Observable<User[]> { return this.userRepository.getUsers().pipe(map(sortUsersByLastName)); } - createInKeycloak(item: Partial<UserRepresentation>): Observable<UserRepresentation> { + createInKeycloak(item: Partial<User>): Observable<User> { throw new Error('Method not implemented.'); } - saveInKeycloak(item: UserRepresentation): Observable<void> { + saveInKeycloak(item: User): Observable<void> { throw new Error('Method not implemented.'); } diff --git a/alfa-client/libs/admin/settings/src/lib/users-roles/users-roles.component.html b/alfa-client/libs/admin/settings/src/lib/users-roles/users-roles.component.html index 37716672d516d2c818c11991337b076d248d1178..e90b3e4d3bf1382045e492f844584f9a2feea5f0 100644 --- a/alfa-client/libs/admin/settings/src/lib/users-roles/users-roles.component.html +++ b/alfa-client/libs/admin/settings/src/lib/users-roles/users-roles.component.html @@ -11,7 +11,7 @@ > <div class="flex-1 basis-1/2"> <div class="mb-2 flex flex-wrap items-center gap-3"> - <h3 class="text-md font-semibold">{{ user | userName }}</h3> + <h3 class="text-md font-semibold">{{ user | toUserName }}</h3> <dl class="flex flex-wrap gap-2"> <dt class="sr-only">Rollen:</dt> <dd diff --git a/alfa-client/libs/admin/settings/src/lib/users-roles/users-roles.component.spec.ts b/alfa-client/libs/admin/settings/src/lib/users-roles/users-roles.component.spec.ts index 31100a0573983f3bf7dfc2a6054dd7fd17af8d08..2bfa21f35d1671af677738ccda00d62601964941 100644 --- a/alfa-client/libs/admin/settings/src/lib/users-roles/users-roles.component.spec.ts +++ b/alfa-client/libs/admin/settings/src/lib/users-roles/users-roles.component.spec.ts @@ -1,25 +1,26 @@ import { Mock, mock } from '@alfa-client/test-utils'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation'; import { ButtonWithSpinnerComponent } from '@ods/component'; import { MailboxIconComponent, PersonIconComponent } from '@ods/system'; import { MockComponent } from 'ng-mocks'; -import { UserAndRolesService } from './userAndRolesService'; +import { createUser } from '../../../test/user/user'; +import { User } from '../user/user.model'; +import { UserService } from './user.service'; import { Groups, UsersRolesComponent } from './users-roles.component'; describe('UsersRolesComponent', () => { let component: UsersRolesComponent; let fixture: ComponentFixture<UsersRolesComponent>; - const userAndRolesService: Mock<UserAndRolesService> = { - ...mock(UserAndRolesService), + const userAndRolesService: Mock<UserService> = { + ...mock(UserService), get: jest.fn(), }; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [UsersRolesComponent], - providers: [{ provide: UserAndRolesService, useValue: userAndRolesService }], + providers: [{ provide: UserService, useValue: userAndRolesService }], imports: [ MockComponent(ButtonWithSpinnerComponent), MockComponent(MailboxIconComponent), @@ -40,7 +41,8 @@ describe('UsersRolesComponent', () => { describe('getGroupsForUser', () => { describe('value', () => { it('should contain trimmed array', () => { - const user: UserRepresentation = { + const user: User = { + ...createUser(), groups: ['Test1', 'Test2', 'Test3', 'Test4'], }; @@ -51,7 +53,8 @@ describe('UsersRolesComponent', () => { }); describe('rest', () => { it('should contain count of rest elements', () => { - const user: UserRepresentation = { + const user: User = { + ...createUser(), groups: ['Test1', 'Test2', 'Test3', 'Test4'], }; @@ -61,7 +64,8 @@ describe('UsersRolesComponent', () => { }); it('should contain 0 if there are less groups', () => { - const user: UserRepresentation = { + const user: User = { + ...createUser(), groups: ['Test1'], }; diff --git a/alfa-client/libs/admin/settings/src/lib/users-roles/users-roles.component.ts b/alfa-client/libs/admin/settings/src/lib/users-roles/users-roles.component.ts index 5e4ba114297cfe4b4e08ec318ba57b1e28ca6300..f6ca8a63d2132ecdea05ce37b31800cd4aa7eccd 100644 --- a/alfa-client/libs/admin/settings/src/lib/users-roles/users-roles.component.ts +++ b/alfa-client/libs/admin/settings/src/lib/users-roles/users-roles.component.ts @@ -1,8 +1,8 @@ import { StateResource } from '@alfa-client/tech-shared'; import { Component } from '@angular/core'; -import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation'; import { Observable } from 'rxjs'; -import { UserAndRolesService } from './userAndRolesService'; +import { User } from '../user/user.model'; +import { UserService } from './user.service'; export const GROUPS_TO_SHOW = 3; @@ -16,13 +16,13 @@ export interface Groups { templateUrl: './users-roles.component.html', }) export class UsersRolesComponent { - users$: Observable<StateResource<UserRepresentation[]>>; + users$: Observable<StateResource<User[]>>; - constructor(private userAndRolesService: UserAndRolesService) { + constructor(private userAndRolesService: UserService) { this.users$ = this.userAndRolesService.get(); } - getGroupsForUser(user: UserRepresentation, groupsToShow: number = GROUPS_TO_SHOW): Groups { + getGroupsForUser(user: User, groupsToShow: number = GROUPS_TO_SHOW): Groups { const value = user.groups.slice(0, groupsToShow); const groupsLengthDiff = user.groups.length - groupsToShow; return { diff --git a/alfa-client/libs/admin/settings/test/user/user.ts b/alfa-client/libs/admin/settings/test/user/user.ts index 3cb477d32430c8f4018cf12c2839389891a96cb8..8e9c06e922483b856f0b179d14e476d7b81ddc83 100644 --- a/alfa-client/libs/admin/settings/test/user/user.ts +++ b/alfa-client/libs/admin/settings/test/user/user.ts @@ -1,18 +1,22 @@ import { faker } from '@faker-js/faker'; import { NetworkError } from '@keycloak/keycloak-admin-client'; import type GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation'; -import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation'; import { Organisationseinheit, OrganisationseinheitError, OrganisationseinheitErrorType, + User, } from '../../src/lib/user/user.model'; -export function createUserRepresentation(): UserRepresentation { +export function createUser(): User { return { id: faker.random.word(), + username: faker.random.word(), firstName: faker.name.firstName(), lastName: faker.name.lastName(), + email: faker.internet.email(), + roles: null, + groups: null, }; }