diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.html b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.html index a4f280c45a5a00bb5fd10a0bb23f05f2a1e41113..9569f67d6ee739e66de75549bb80e57920697782 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.html +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.html @@ -1,19 +1 @@ -<goofy-client-icon-button-with-spinner icon="settings" toolTip="Einstellungen" data-test-id="user-settings-button" - [matMenuTriggerFor]="settingsMenu"> -</goofy-client-icon-button-with-spinner> - -<mat-menu #settingsMenu="matMenu"> - <div class="menu-container" (click)="$event.stopPropagation()"> - <ng-container *ngIf="apiRoot$ | async as apiRoot"> - <goofy-client-user-settings-email-benachrichtigung data-test-id="user-settings-email-benachrichtigung" - *ngIf="apiRoot.resource | hasLink: apiRootLinkRel.CURRENT_USER" - [userSettings]="userSettings$ | async" - (valueChanged)="changeNotificationsSendFor($event)" - ></goofy-client-user-settings-email-benachrichtigung> - </ng-container> - <goofy-client-user-settings-darkmode data-test-id="user-settings-dark-mode" - [darkMode$]="darkMode$" - (darkModeEmitter)="changeColorMode($event)" - ></goofy-client-user-settings-darkmode> - </div> -</mat-menu> +<goofy-client-user-settings [apiRoot]="apiRoot$ | async"></goofy-client-user-settings> \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.scss b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.scss index e15dab43b6e1199516db6bca6fe3c9ad2574d47e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.scss +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.scss @@ -1,8 +0,0 @@ -.menu-container { - margin: 12px 16px; -} - -goofy-client-icon-button-with-spinner, -mat-slide-toggle { - display: block; -} diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.spec.ts b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.spec.ts index cbafa31eb4d7d5e774f683ae3ddb70a9d0e20889..23766c0ad8aa261f8aeb46dadd036c8e6307b40e 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.spec.ts +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.spec.ts @@ -1,59 +1,23 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { MatButtonModule } from '@angular/material/button'; -import { MatMenuModule } from '@angular/material/menu'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { ApiRootFacade, ApiRootLinkRel } from '@goofy-client/api-root-shared'; -import { AppService } from '@goofy-client/app-shared'; -import { createStateResource, HasLinkPipe } from '@goofy-client/tech-shared'; -import { getElementFromDomRoot, getElementFromFixture, mock } from '@goofy-client/test-utils'; -import { IconButtonWithSpinnerComponent } from '@goofy-client/ui'; -import { UserSettingsService } from '@goofy-client/user-settings-shared'; -import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; -import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; -import { NotificationsSendFor } from 'libs/user-settings-shared/src/lib/user-settings.model'; +import { ApiRootFacade } from '@goofy-client/api-root-shared'; +import { Mock, mock } from '@goofy-client/test-utils'; import { MockComponent } from 'ng-mocks'; -import { BehaviorSubject, of } from 'rxjs'; +import { UserSettingsComponent } from '../user-settings/user-settings.component'; import { UserSettingsContainerComponent } from './user-settings-container.component'; -import { UserSettingsDarkmodeComponent } from './user-settings-darkmode/user-settings-darkmode.component'; -import { UserSettingsEmailBenachrichtigungComponent } from './user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component'; describe('UserSettingsContainerComponent', () => { let component: UserSettingsContainerComponent; let fixture: ComponentFixture<UserSettingsContainerComponent>; - let menuButtonElement; - const darkModeSubj: BehaviorSubject<boolean> = new BehaviorSubject(false); - const appService = { ...mock(AppService), getDarkMode: () => darkModeSubj }; - const userSettingsService = { ...mock(UserSettingsService), setUserSettings: jest.fn() }; - const apiRootFacade = { ...mock(ApiRootFacade), getApiRoot: jest.fn() }; - - const menuButton = getDataTestIdOf('user-settings-button'); - const emailBenachrichtigung: string = getDataTestIdOf('user-settings-email-benachrichtigung'); - const darkMode: string = getDataTestIdOf('user-settings-dark-mode'); + const apiRootFacade: Mock<ApiRootFacade> = { ...mock(ApiRootFacade), getApiRoot: jest.fn() }; beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule, - MatButtonModule, - MatMenuModule - ], declarations: [ - HasLinkPipe, UserSettingsContainerComponent, - MockComponent(UserSettingsDarkmodeComponent), - MockComponent(UserSettingsEmailBenachrichtigungComponent), - MockComponent(IconButtonWithSpinnerComponent) + MockComponent(UserSettingsComponent) ], providers: [ - { - provide: AppService, - useValue: appService, - }, - { - provide: UserSettingsService, - useValue: userSettingsService - }, { provide: ApiRootFacade, useValue: apiRootFacade @@ -66,69 +30,18 @@ describe('UserSettingsContainerComponent', () => { fixture = TestBed.createComponent(UserSettingsContainerComponent); component = fixture.componentInstance; fixture.autoDetectChanges(true); - menuButtonElement = getElementFromFixture(fixture, menuButton); }); it('should create', () => { expect(component).toBeTruthy(); }); - describe('change color mode', () => { - - it('should call app service', () => { - component.changeColorMode(true); - - expect(appService.setDarkMode).toHaveBeenCalledWith(true); - }) - }) + describe('ngOnInit', () => { - describe('Toggle for "notifications send for"', () => { - it('should call apiRootFacade to get apiRoot', () => { + it('should call apiRoot facade', () => { component.ngOnInit(); expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); }) - - it('should show if link exists', () => { - component.apiRoot$ = of(createStateResource(createApiRootResource([ApiRootLinkRel.CURRENT_USER]))); - - menuButtonElement.click(); - const element = getElementFromDomRoot(fixture, emailBenachrichtigung); - - expect(element).toBeInTheDocument(); - }) - - it('should hide if link not exists', () => { - component.apiRoot$ = of(createStateResource(createApiRootResource())); - - menuButtonElement.click(); - const element = getElementFromDomRoot(fixture, emailBenachrichtigung); - - expect(element).not.toBeInTheDocument(); - }) - }) - - describe('change notifications send for', () => { - - it('should call service with ALL', () => { - component.changeNotificationsSendFor(true); - - expect(userSettingsService.setUserSettings).toHaveBeenCalledWith({ notificationsSendFor: NotificationsSendFor.ALL }); - }) - - it('should call service with NONE', () => { - component.changeNotificationsSendFor(false); - - expect(userSettingsService.setUserSettings).toHaveBeenCalledWith({ notificationsSendFor: NotificationsSendFor.NONE }); - }) - }) - - describe('Toggle for "Dark mode"', () => { - it('should be visible', () => { - menuButtonElement.click(); - const element = getElementFromDomRoot(fixture, darkMode); - - expect(element).toBeInstanceOf(HTMLElement); - }) }) }); diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.ts b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.ts index 0bae193a62aae487febc81907cb1a543ef572080..fece5a34c85f38306d70528c2eb864337b9caa21 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.ts +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.ts @@ -1,10 +1,6 @@ -import { DOCUMENT } from '@angular/common'; -import { Component, Inject, OnInit, Renderer2 } from '@angular/core'; -import { ApiRootFacade, ApiRootLinkRel, ApiRootResource } from '@goofy-client/api-root-shared'; -import { AppService, localStorageDark } from '@goofy-client/app-shared'; +import { Component, OnInit } from '@angular/core'; +import { ApiRootFacade, ApiRootResource } from '@goofy-client/api-root-shared'; import { createEmptyStateResource, StateResource } from '@goofy-client/tech-shared'; -import { UserSettingsService } from '@goofy-client/user-settings-shared'; -import { NotificationsSendFor, UserSettings, UserSettingsResource } from 'libs/user-settings-shared/src/lib/user-settings.model'; import { Observable, of } from 'rxjs'; @Component({ @@ -13,55 +9,12 @@ import { Observable, of } from 'rxjs'; styleUrls: ['./user-settings-container.component.scss'], }) export class UserSettingsContainerComponent implements OnInit { - darkMode$: Observable<boolean> = of(true); - userSettings$: Observable<StateResource<UserSettingsResource>>; - apiRoot$: Observable<StateResource<ApiRootResource>> = of(createEmptyStateResource<ApiRootResource>()); - - readonly apiRootLinkRel = ApiRootLinkRel; - constructor( - private renderer: Renderer2, - private appService: AppService, - private userSettingsService: UserSettingsService, - private apiRootFacade: ApiRootFacade, - @Inject(DOCUMENT) private document: Document - ) { - this.darkMode$ = this.appService.getDarkMode(); + apiRoot$: Observable<StateResource<ApiRootResource>> = of(createEmptyStateResource<ApiRootResource>()); - this.subscribeToDarkMode(); - } + constructor(private apiRootFacade: ApiRootFacade) { } ngOnInit(): void { - this.userSettings$ = this.userSettingsService.getUserSettings(); this.apiRoot$ = this.apiRootFacade.getApiRoot(); } - - private subscribeToDarkMode(): void { - this.darkMode$.subscribe((darkMode) => - darkMode - ? this.addClass(localStorageDark) - : this.removeClass(localStorageDark) - ); - } - - private addClass(styleClass: string): void { - this.renderer.addClass(this.document.body, styleClass); - } - - private removeClass(styleClass: string): void { - this.renderer.removeClass(this.document.body, styleClass); - } - - changeColorMode(darkMode: boolean): void { - this.appService.setDarkMode(darkMode); - } - - changeNotificationsSendFor(toggleValue: boolean): void { - this.userSettingsService.setUserSettings(this.createUserSettings(toggleValue)); - } - - private createUserSettings(toggleValue: boolean): UserSettings { - const notificationsSendFor: NotificationsSendFor = toggleValue ? NotificationsSendFor.ALL : NotificationsSendFor.NONE; - return { notificationsSendFor }; - } } \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.html b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.html index 07a006c57442bef409a85437b10a68fde2f5c680..0eb6e7c227193cd7124a3b6b710014715b9c9a63 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.html +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.html @@ -1,6 +1,6 @@ -<mat-slide-toggle - color="primary" - [checked]="darkMode$ | async" - (change)="darkModeEmitter.emit($event.checked)" - >Dark Mode -</mat-slide-toggle> +<goofy-client-slide-toggle data-test-id="toggle-dark-mode" + label="Dark Mode" + [checked]="darkMode" + (valueChanged)="valueChanged.emit($event)"> +</goofy-client-slide-toggle> + diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.scss b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.scss index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..da1cfd3eb891a5f6857e27dadc340527de7e240a 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.scss +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.scss @@ -0,0 +1,3 @@ +goofy-client-slide-toggle { + display: block; +} \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.spec.ts b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.spec.ts index f333224d4ba89c44239501605915654454dcfa27..90d17346a372e6650387e5c36fc6e3eef2d4554b 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.spec.ts +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.spec.ts @@ -1,5 +1,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { UiModule } from '@goofy-client/ui'; +import { SlideToggleComponent } from 'libs/ui/src/lib/ui/slide-toggle/slide-toggle.component'; +import { MockComponent } from 'ng-mocks'; import { UserSettingsDarkmodeComponent } from './user-settings-darkmode.component'; describe('UserSettingsDarkmodeComponent', () => { @@ -8,8 +9,10 @@ describe('UserSettingsDarkmodeComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [UiModule], - declarations: [UserSettingsDarkmodeComponent], + declarations: [ + UserSettingsDarkmodeComponent, + MockComponent(SlideToggleComponent) + ], }).compileComponents(); fixture = TestBed.createComponent(UserSettingsDarkmodeComponent); diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.ts b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.ts index 651132cf8620c19aa5b6375164247bf99ddb0384..d8b0ae504705e2ebf05031c768239a5d5c7b6f57 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.ts +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-darkmode/user-settings-darkmode.component.ts @@ -1,5 +1,4 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { Observable, of } from 'rxjs'; @Component({ selector: 'goofy-client-user-settings-darkmode', @@ -7,8 +6,8 @@ import { Observable, of } from 'rxjs'; styleUrls: ['./user-settings-darkmode.component.scss'], }) export class UserSettingsDarkmodeComponent { - @Input() darkMode$: Observable<boolean> = of(true); - @Output() public darkModeEmitter: EventEmitter<boolean> = - new EventEmitter(); + @Input() darkMode: boolean; + + @Output() valueChanged: EventEmitter<boolean> = new EventEmitter(); } diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.html b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.html index 4ee42fd2ca5a16c25d8a7404a9b8ff2115096474..7aa4001e220985f47b3951f4674a2f41fadb2e3e 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.html +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.html @@ -1,8 +1,11 @@ <ng-container *ngIf="userSettings.resource"> - <mat-slide-toggle data-test-id="toggle-notifications-send-for" - color="primary" - matTooltip="Benachrichtigung per E-Mail bei Eingang eines Antrags" - [checked]="getToggleStatus(userSettings.resource)" - (change)="valueChanged.emit($event.checked)">Benachrichtigung per E-Mail - </mat-slide-toggle> + + <goofy-client-slide-toggle data-test-id="toggle-notifications-send-for" + label="Benachrichtigung per E-Mail" + toolTip="Benachrichtigung per E-Mail bei Eingang eines Antrags" + [disabled]="userSettings.resource | notHasLink: userSettingsLinkRel.EDIT" + [checked]="isChecked(userSettings.resource)" + (valueChanged)="valueChanged.emit($event)"> + </goofy-client-slide-toggle> + </ng-container> \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.scss b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.scss index 92276dfe14738302abcf74e348103b1dfb94c9fe..541defa5587fd7dd46a8ae3e55bf955e3a5dbd90 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.scss +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.scss @@ -1,3 +1,4 @@ -mat-slide-toggle { +goofy-client-slide-toggle { margin-bottom: 0.5rem; -} + display: block; +} \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts index 4455f44a77af3323d0de67d23f70f175c5e99c1a..5ccdbfa447d14e6a3833f6099571badc0369fef5 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts @@ -1,35 +1,36 @@ +import { EventEmitter } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { MatRippleModule } from '@angular/material/core'; -import { MatMenuModule } from '@angular/material/menu'; -import { MatSlideToggle } from '@angular/material/slide-toggle'; -import { createStateResource } from '@goofy-client/tech-shared'; - -import { dispatchEventFromFixture, mock } from '@goofy-client/test-utils'; +import { createEmptyStateResource, createStateResource, NotHasLinkPipe } from '@goofy-client/tech-shared'; +import { dispatchEventFromFixture, getElementFromFixture, Mock, mock, useFromMock } from '@goofy-client/test-utils'; +import { UserSettingsLinkRel } from '@goofy-client/user-settings-shared'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; -import { NotificationsSendFor } from 'libs/user-settings-shared/src/lib/user-settings.model'; +import { SlideToggleComponent } from 'libs/ui/src/lib/ui/slide-toggle/slide-toggle.component'; +import { NotificationsSendFor, UserSettings } from 'libs/user-settings-shared/src/lib/user-settings.model'; import { createUserSettings, createUserSettingsResource } from 'libs/user-settings-shared/test/user-settings'; -import { EventEmitter } from 'stream'; +import { MockComponent } from 'ng-mocks'; import { UserSettingsEmailBenachrichtigungComponent } from './user-settings-email-benachrichtigung.component'; describe('UserSettingsEmailBenachrichtigungComponent', () => { let component: UserSettingsEmailBenachrichtigungComponent; let fixture: ComponentFixture<UserSettingsEmailBenachrichtigungComponent>; - const toggle: string = getDataTestIdOf('toggle-notifications-send-for'); - const userSettings = createUserSettings(); + const notificationSensForToggle: string = getDataTestIdOf('toggle-notifications-send-for'); + + const valueChangedEmitter: Mock<EventEmitter<boolean>> = { ...mock(EventEmitter), emit: jest.fn() }; beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [MatMenuModule, MatRippleModule], - declarations: [UserSettingsEmailBenachrichtigungComponent, MatSlideToggle], + declarations: [ + NotHasLinkPipe, + UserSettingsEmailBenachrichtigungComponent, + MockComponent(SlideToggleComponent) + ], }).compileComponents(); - fixture = TestBed.createComponent( - UserSettingsEmailBenachrichtigungComponent - ); + fixture = TestBed.createComponent(UserSettingsEmailBenachrichtigungComponent); component = fixture.componentInstance; - component.userSettings = createStateResource(createUserSettingsResource()); - component.valueChanged = { ...<any>mock(EventEmitter), emit: jest.fn() }; + component.userSettings = createEmptyStateResource(); + component.valueChanged = useFromMock(valueChangedEmitter); fixture.detectChanges(); }); @@ -37,33 +38,49 @@ describe('UserSettingsEmailBenachrichtigungComponent', () => { expect(component).toBeTruthy(); }); - it('should show toggle', () => { - const element = fixture.nativeElement.querySelector(toggle); - - expect(element).toBeInstanceOf(HTMLElement); - }) + describe('toggle', () => { - describe('toggle status', () => { - it('should be set if userSettings.notificationsSendFor is ALL', () => { - userSettings.notificationsSendFor = NotificationsSendFor.ALL; + it('should be active if notificationsSendFor is ALL', () => { + const userSettings: UserSettings = { ...createUserSettings(), notificationsSendFor: NotificationsSendFor.ALL }; - const result: boolean = component.getToggleStatus(userSettings); + const result: boolean = component.isChecked(userSettings); expect(result).toBeTruthy(); }) - it('should not be set if userSettings.notificationsSendFor is NONE', () => { - userSettings.notificationsSendFor = NotificationsSendFor.NONE; + it('should be not active if notificationsSendFor is NONE', () => { + const userSettings: UserSettings = { ...createUserSettings(), notificationsSendFor: NotificationsSendFor.NONE }; - const result: boolean = component.getToggleStatus(userSettings); + const result: boolean = component.isChecked(userSettings); expect(result).toBeFalsy(); }) it('should emit value if toggled', () => { - dispatchEventFromFixture(fixture, toggle, 'change'); + component.userSettings = createStateResource(createUserSettingsResource()); + fixture.detectChanges(); + + dispatchEventFromFixture(fixture, notificationSensForToggle, 'valueChanged'); expect(component.valueChanged.emit).toHaveBeenCalled(); }) + + it('should be deactivated if edit link is missing', () => { + component.userSettings = createStateResource(createUserSettingsResource()); + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, notificationSensForToggle); + + expect(element).toHaveAttribute('ng-reflect-disabled', 'true'); + }) + + it('should be activated if edit link exist', () => { + component.userSettings = createStateResource(createUserSettingsResource([UserSettingsLinkRel.EDIT])); + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, notificationSensForToggle); + + expect(element).toHaveAttribute('ng-reflect-disabled', 'false'); + }) }) }); diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.ts b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.ts index 185a0d82cb6fadf2faf58cb9032a55ca53c911b1..c75d06adc451eaf4454e35e6c216cceb315ed1c3 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.ts +++ b/goofy-client/libs/user-settings/src/lib/user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { createEmptyStateResource, StateResource } from '@goofy-client/tech-shared'; -import { NotificationsSendFor, UserSettings, UserSettingsResource } from '@goofy-client/user-settings-shared'; +import { NotificationsSendFor, UserSettings, UserSettingsLinkRel, UserSettingsResource } from '@goofy-client/user-settings-shared'; @Component({ selector: 'goofy-client-user-settings-email-benachrichtigung', @@ -8,10 +8,14 @@ import { NotificationsSendFor, UserSettings, UserSettingsResource } from '@goofy styleUrls: ['./user-settings-email-benachrichtigung.component.scss'], }) export class UserSettingsEmailBenachrichtigungComponent { + @Input() userSettings: StateResource<UserSettingsResource> = createEmptyStateResource<UserSettingsResource>(); + @Output() valueChanged: EventEmitter<boolean> = new EventEmitter(); - public getToggleStatus(userSettings: UserSettings): boolean { + readonly userSettingsLinkRel = UserSettingsLinkRel; + + public isChecked(userSettings: UserSettings): boolean { return userSettings.notificationsSendFor === NotificationsSendFor.ALL; } -} +} \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-darkmode-container/user-settings-darkmode-container.component.html b/goofy-client/libs/user-settings/src/lib/user-settings-darkmode-container/user-settings-darkmode-container.component.html new file mode 100644 index 0000000000000000000000000000000000000000..a560d5d9197ec12d62d5bf507d8416d4b2d6f48a --- /dev/null +++ b/goofy-client/libs/user-settings/src/lib/user-settings-darkmode-container/user-settings-darkmode-container.component.html @@ -0,0 +1,4 @@ +<goofy-client-user-settings-darkmode + [darkMode]="darkMode$ | async" + (valueChanged)="changeColorMode($event)"> +</goofy-client-user-settings-darkmode> \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-darkmode-container/user-settings-darkmode-container.component.scss b/goofy-client/libs/user-settings/src/lib/user-settings-darkmode-container/user-settings-darkmode-container.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-darkmode-container/user-settings-darkmode-container.component.spec.ts b/goofy-client/libs/user-settings/src/lib/user-settings-darkmode-container/user-settings-darkmode-container.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..25050b6d502cad46982f1fb8756ac58e4c05c49f --- /dev/null +++ b/goofy-client/libs/user-settings/src/lib/user-settings-darkmode-container/user-settings-darkmode-container.component.spec.ts @@ -0,0 +1,47 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { AppService } from '@goofy-client/app-shared'; +import { mock } from '@goofy-client/test-utils'; +import { MockComponent } from 'ng-mocks'; +import { BehaviorSubject } from 'rxjs'; +import { UserSettingsDarkmodeComponent } from '../user-settings-container/user-settings-darkmode/user-settings-darkmode.component'; +import { UserSettingsDarkmodeContainerComponent } from './user-settings-darkmode-container.component'; + +describe('UserSettingsDarkmodeContainerComponent', () => { + let component: UserSettingsDarkmodeContainerComponent; + let fixture: ComponentFixture<UserSettingsDarkmodeContainerComponent>; + + const darkModeSubj: BehaviorSubject<boolean> = new BehaviorSubject(false); + const appService = { ...mock(AppService), getDarkMode: () => darkModeSubj }; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + UserSettingsDarkmodeContainerComponent, + MockComponent(UserSettingsDarkmodeComponent) + ], + providers: [ + { + provide: AppService, + useValue: appService, + } + ] + }).compileComponents(); + + fixture = TestBed.createComponent(UserSettingsDarkmodeContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('change color mode', () => { + + it('should call app service', () => { + component.changeColorMode(true); + + expect(appService.setDarkMode).toHaveBeenCalledWith(true); + }) + }) +}); \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-darkmode-container/user-settings-darkmode-container.component.ts b/goofy-client/libs/user-settings/src/lib/user-settings-darkmode-container/user-settings-darkmode-container.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..07d0a9d53dcb43474a42c3bedbeabd7b0f999953 --- /dev/null +++ b/goofy-client/libs/user-settings/src/lib/user-settings-darkmode-container/user-settings-darkmode-container.component.ts @@ -0,0 +1,46 @@ +import { DOCUMENT } from '@angular/common'; +import { Component, Inject, OnInit, Renderer2 } from '@angular/core'; +import { AppService, localStorageDark } from '@goofy-client/app-shared'; +import { Observable } from 'rxjs'; + +@Component({ + selector: 'goofy-client-user-settings-darkmode-container', + templateUrl: './user-settings-darkmode-container.component.html', + styleUrls: ['./user-settings-darkmode-container.component.scss'], +}) +export class UserSettingsDarkmodeContainerComponent implements OnInit { + + darkMode$: Observable<boolean>; + + constructor( + private renderer: Renderer2, + private appService: AppService, + @Inject(DOCUMENT) private document: Document + ) { } + + ngOnInit(): void { + this.darkMode$ = this.appService.getDarkMode(); + + this.subscribeToDarkMode(); + } + + private subscribeToDarkMode(): void { + this.darkMode$.subscribe((darkMode) => + darkMode + ? this.addClass(localStorageDark) + : this.removeClass(localStorageDark) + ); + } + + private addClass(styleClass: string): void { + this.renderer.addClass(this.document.body, styleClass); + } + + private removeClass(styleClass: string): void { + this.renderer.removeClass(this.document.body, styleClass); + } + + public changeColorMode(darkMode: boolean): void { + this.appService.setDarkMode(darkMode); + } +} \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.html b/goofy-client/libs/user-settings/src/lib/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.html new file mode 100644 index 0000000000000000000000000000000000000000..cb8e4eef3b53e78862c66ab5d3dec7d2a2dbbb11 --- /dev/null +++ b/goofy-client/libs/user-settings/src/lib/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.html @@ -0,0 +1,4 @@ +<goofy-client-user-settings-email-benachrichtigung + [userSettings]="userSettings$ | async" + (valueChanged)="changeNotificationsSendFor($event)"> +</goofy-client-user-settings-email-benachrichtigung> \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.scss b/goofy-client/libs/user-settings/src/lib/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.spec.ts b/goofy-client/libs/user-settings/src/lib/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..4986f15c3e64221aa6fbfe5375b9a4edf620b03e --- /dev/null +++ b/goofy-client/libs/user-settings/src/lib/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.spec.ts @@ -0,0 +1,60 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { mock } from '@goofy-client/test-utils'; +import { NotificationsSendFor, UserSettingsService } from '@goofy-client/user-settings-shared'; +import { MockComponent } from 'ng-mocks'; +import { UserSettingsEmailBenachrichtigungComponent } from '../user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component'; +import { UserSettingsEmailBenachrichtigungContainerComponent } from './user-settings-email-benachrichtigung-container.component'; + +describe('UserSettingsEmailBenachrichtigungContainerComponent', () => { + let component: UserSettingsEmailBenachrichtigungContainerComponent; + let fixture: ComponentFixture<UserSettingsEmailBenachrichtigungContainerComponent>; + + const userSettingsService = { ...mock(UserSettingsService), setUserSettings: jest.fn() }; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + UserSettingsEmailBenachrichtigungContainerComponent, + MockComponent(UserSettingsEmailBenachrichtigungComponent) + ], + providers: [ + { + provide: UserSettingsService, + useValue: userSettingsService + } + ], + }).compileComponents(); + + fixture = TestBed.createComponent(UserSettingsEmailBenachrichtigungContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + + it('should call userSettings service', () => { + component.ngOnInit(); + + expect(userSettingsService.getUserSettings).toHaveBeenCalled(); + }) + }) + + describe('change notifications send for', () => { + + it('should call service with ALL', () => { + component.changeNotificationsSendFor(true); + + expect(userSettingsService.setUserSettings).toHaveBeenCalledWith({ notificationsSendFor: NotificationsSendFor.ALL }); + }) + + it('should call service with NONE', () => { + component.changeNotificationsSendFor(false); + + expect(userSettingsService.setUserSettings).toHaveBeenCalledWith({ notificationsSendFor: NotificationsSendFor.NONE }); + }) + }) +}); diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.ts b/goofy-client/libs/user-settings/src/lib/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..ba354ea97e4c3ae887f9a2aa7aaeb962ef0f4752 --- /dev/null +++ b/goofy-client/libs/user-settings/src/lib/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.ts @@ -0,0 +1,29 @@ +import { Component } from '@angular/core'; +import { StateResource } from '@goofy-client/tech-shared'; +import { NotificationsSendFor, UserSettings, UserSettingsResource, UserSettingsService } from '@goofy-client/user-settings-shared'; +import { Observable } from 'rxjs'; + +@Component({ + selector: 'goofy-client-user-settings-email-benachrichtigung-container', + templateUrl: './user-settings-email-benachrichtigung-container.component.html', + styleUrls: ['./user-settings-email-benachrichtigung-container.component.scss'] +}) +export class UserSettingsEmailBenachrichtigungContainerComponent { + + userSettings$: Observable<StateResource<UserSettingsResource>>; + + constructor(private userSettingsService: UserSettingsService) { } + + ngOnInit(): void { + this.userSettings$ = this.userSettingsService.getUserSettings(); + } + + changeNotificationsSendFor(toggleValue: boolean): void { + this.userSettingsService.setUserSettings(this.createUserSettings(toggleValue)); + } + + private createUserSettings(toggleValue: boolean): UserSettings { + const notificationsSendFor: NotificationsSendFor = toggleValue ? NotificationsSendFor.ALL : NotificationsSendFor.NONE; + return { notificationsSendFor }; + } +} diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-menu-button/user-settings-menu-button.component.html b/goofy-client/libs/user-settings/src/lib/user-settings-menu-button/user-settings-menu-button.component.html new file mode 100644 index 0000000000000000000000000000000000000000..818deb74c0fac712245a6fb44c24f354b756a976 --- /dev/null +++ b/goofy-client/libs/user-settings/src/lib/user-settings-menu-button/user-settings-menu-button.component.html @@ -0,0 +1 @@ +<goofy-client-icon-button-with-spinner icon="settings" toolTip="Einstellungen" data-test-id="menu-button"></goofy-client-icon-button-with-spinner> \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-menu-button/user-settings-menu-button.component.scss b/goofy-client/libs/user-settings/src/lib/user-settings-menu-button/user-settings-menu-button.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..d7da62a838b151a216dcea229531f0e7d813574f --- /dev/null +++ b/goofy-client/libs/user-settings/src/lib/user-settings-menu-button/user-settings-menu-button.component.scss @@ -0,0 +1,3 @@ +goofy-client-icon-button-with-spinner { + display: block; +} \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-menu-button/user-settings-menu-button.component.spec.ts b/goofy-client/libs/user-settings/src/lib/user-settings-menu-button/user-settings-menu-button.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..e1579bbb6e91664e24033528cd334c88983f337a --- /dev/null +++ b/goofy-client/libs/user-settings/src/lib/user-settings-menu-button/user-settings-menu-button.component.spec.ts @@ -0,0 +1,26 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { IconButtonWithSpinnerComponent } from '@goofy-client/ui'; +import { MockComponent } from 'ng-mocks'; +import { UserSettingsMenuButtonComponent } from './user-settings-menu-button.component'; + +describe('UserSettingsMenuButtonComponent', () => { + let component: UserSettingsMenuButtonComponent; + let fixture: ComponentFixture<UserSettingsMenuButtonComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + UserSettingsMenuButtonComponent, + MockComponent(IconButtonWithSpinnerComponent) + ] + }).compileComponents(); + + fixture = TestBed.createComponent(UserSettingsMenuButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/goofy-client/libs/user-settings/src/lib/user-settings-menu-button/user-settings-menu-button.component.ts b/goofy-client/libs/user-settings/src/lib/user-settings-menu-button/user-settings-menu-button.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..95409cf3727a4aeb4192b75f92c1efa83f2a11ef --- /dev/null +++ b/goofy-client/libs/user-settings/src/lib/user-settings-menu-button/user-settings-menu-button.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'goofy-client-user-settings-menu-button', + templateUrl: './user-settings-menu-button.component.html', + styleUrls: ['./user-settings-menu-button.component.scss'], +}) +export class UserSettingsMenuButtonComponent { + +} diff --git a/goofy-client/libs/user-settings/src/lib/user-settings.module.ts b/goofy-client/libs/user-settings/src/lib/user-settings.module.ts index 79c603fe449e56a1414bd9eec6ae65bc3aa9672e..394ade0a4febac14707a705a0415231d4c8f96e4 100644 --- a/goofy-client/libs/user-settings/src/lib/user-settings.module.ts +++ b/goofy-client/libs/user-settings/src/lib/user-settings.module.ts @@ -5,6 +5,10 @@ import { UserSettingsSharedModule } from '@goofy-client/user-settings-shared'; import { UserSettingsContainerComponent } from './user-settings-container/user-settings-container.component'; import { UserSettingsDarkmodeComponent } from './user-settings-container/user-settings-darkmode/user-settings-darkmode.component'; import { UserSettingsEmailBenachrichtigungComponent } from './user-settings-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component'; +import { UserSettingsDarkmodeContainerComponent } from './user-settings-darkmode-container/user-settings-darkmode-container.component'; +import { UserSettingsEmailBenachrichtigungContainerComponent } from './user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component'; +import { UserSettingsMenuButtonComponent } from './user-settings-menu-button/user-settings-menu-button.component'; +import { UserSettingsComponent } from './user-settings/user-settings.component'; @NgModule({ imports: [ @@ -16,10 +20,14 @@ import { UserSettingsEmailBenachrichtigungComponent } from './user-settings-cont UserSettingsContainerComponent, UserSettingsEmailBenachrichtigungComponent, UserSettingsDarkmodeComponent, + UserSettingsComponent, + UserSettingsDarkmodeContainerComponent, + UserSettingsEmailBenachrichtigungContainerComponent, + UserSettingsMenuButtonComponent, ], exports: [ UserSettingsContainerComponent, UserSettingsEmailBenachrichtigungComponent, ], }) -export class UserSettingsModule {} +export class UserSettingsModule { } diff --git a/goofy-client/libs/user-settings/src/lib/user-settings/user-settings.component.html b/goofy-client/libs/user-settings/src/lib/user-settings/user-settings.component.html new file mode 100644 index 0000000000000000000000000000000000000000..d46c460c866ab0a08822427b9cc1a5c56a211fa6 --- /dev/null +++ b/goofy-client/libs/user-settings/src/lib/user-settings/user-settings.component.html @@ -0,0 +1,9 @@ +<goofy-client-user-settings-menu-button [matMenuTriggerFor]="settingsMenu" data-test-id="menu-button"></goofy-client-user-settings-menu-button> + +<!-- TODO Das Menu in eine eigene Componente auslagern um die Technik zu kapseln --> +<mat-menu #settingsMenu="matMenu"> + <div class="menu-container" (click)="$event.stopPropagation()"> + <goofy-client-user-settings-email-benachrichtigung-container *ngIf="apiRoot.resource | hasLink: apiRootLinkRel.CURRENT_USER" data-test-id="email-benachrichtigung-toggle"></goofy-client-user-settings-email-benachrichtigung-container> + <goofy-client-user-settings-darkmode-container></goofy-client-user-settings-darkmode-container> + </div> +</mat-menu> \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings/user-settings.component.scss b/goofy-client/libs/user-settings/src/lib/user-settings/user-settings.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..038d35c13b62e3a68f60feaf4623f8a76d2cbd29 --- /dev/null +++ b/goofy-client/libs/user-settings/src/lib/user-settings/user-settings.component.scss @@ -0,0 +1,3 @@ +.menu-container { + margin: 12px 16px; +} \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings/user-settings.component.spec.ts b/goofy-client/libs/user-settings/src/lib/user-settings/user-settings.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..6c0280f43e68fe0defd37e6e778a857bd9b9d6da --- /dev/null +++ b/goofy-client/libs/user-settings/src/lib/user-settings/user-settings.component.spec.ts @@ -0,0 +1,70 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { MatButtonModule } from '@angular/material/button'; +import { MatMenuModule } from '@angular/material/menu'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { ApiRootLinkRel } from '@goofy-client/api-root-shared'; +import { createEmptyStateResource, createStateResource, HasLinkPipe } from '@goofy-client/tech-shared'; +import { getElementFromDomRoot, getElementFromFixture } from '@goofy-client/test-utils'; +import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; +import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; +import { MockComponent } from 'ng-mocks'; +import { UserSettingsDarkmodeContainerComponent } from '../user-settings-darkmode-container/user-settings-darkmode-container.component'; +import { UserSettingsEmailBenachrichtigungContainerComponent } from '../user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component'; +import { UserSettingsMenuButtonComponent } from '../user-settings-menu-button/user-settings-menu-button.component'; +import { UserSettingsComponent } from './user-settings.component'; + +describe('UserSettingsComponent', () => { + let component: UserSettingsComponent; + let fixture: ComponentFixture<UserSettingsComponent>; + + const menuButton: string = getDataTestIdOf('menu-button'); + const emailBenachrichtigung: string = getDataTestIdOf('email-benachrichtigung-toggle'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ + NoopAnimationsModule, + MatButtonModule, + MatMenuModule + ], + declarations: [ + HasLinkPipe, + UserSettingsComponent, + MockComponent(UserSettingsMenuButtonComponent), + MockComponent(UserSettingsEmailBenachrichtigungContainerComponent), + MockComponent(UserSettingsDarkmodeContainerComponent), + ], + }).compileComponents(); + + fixture = TestBed.createComponent(UserSettingsComponent); + component = fixture.componentInstance; + component.apiRoot = createEmptyStateResource() + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('Toggle for "email benachrichtigung"', () => { + + it('should show if link exists', () => { + component.apiRoot = createStateResource(createApiRootResource([ApiRootLinkRel.CURRENT_USER])); + fixture.detectChanges(); + + getElementFromFixture(fixture, menuButton).click(); + const element = getElementFromDomRoot(fixture, emailBenachrichtigung); + + expect(element).toBeInTheDocument(); + }) + + it('should hide if link not exists', () => { + component.apiRoot = createStateResource(createApiRootResource()); + + getElementFromFixture(fixture, menuButton).click(); + const element = getElementFromDomRoot(fixture, emailBenachrichtigung); + + expect(element).not.toBeInTheDocument(); + }) + }) +}); \ No newline at end of file diff --git a/goofy-client/libs/user-settings/src/lib/user-settings/user-settings.component.ts b/goofy-client/libs/user-settings/src/lib/user-settings/user-settings.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..fae9dc99d8e8cb242aa21bd03b3a9770aa46d173 --- /dev/null +++ b/goofy-client/libs/user-settings/src/lib/user-settings/user-settings.component.ts @@ -0,0 +1,15 @@ +import { Component, Input } from '@angular/core'; +import { ApiRootLinkRel, ApiRootResource } from '@goofy-client/api-root-shared'; +import { StateResource } from '@goofy-client/tech-shared'; + +@Component({ + selector: 'goofy-client-user-settings', + templateUrl: './user-settings.component.html', + styleUrls: ['./user-settings.component.scss'], +}) +export class UserSettingsComponent { + + @Input() apiRoot: StateResource<ApiRootResource>; + + readonly apiRootLinkRel = ApiRootLinkRel; +} \ No newline at end of file