diff --git a/alfa-client/apps/admin/src/app/app.component.html b/alfa-client/apps/admin/src/app/app.component.html index d9474d2f2172026acca436c5a7546f81d85683c3..87dbc4de9c89698e3ba41a8f9abb26db5ebb4f05 100644 --- a/alfa-client/apps/admin/src/app/app.component.html +++ b/alfa-client/apps/admin/src/app/app.component.html @@ -10,11 +10,23 @@ <div class="flex w-full flex-auto justify-center overflow-y-auto"> <div class="w-72 bg-slate-100 p-6"> <nav> - <admin-navigation data-test-id="navigation"></admin-navigation> + <admin-navigation + *ngIf="apiRoot | hasLink: ApiRootLinkRel.CONFIGURATION" + data-test-id="navigation" + ></admin-navigation> </nav> </div> <main class="flex-auto overflow-y-auto bg-slate-200 p-6"> - <router-outlet></router-outlet> + <router-outlet + *ngIf=" + apiRoot | hasLink: ApiRootLinkRel.CONFIGURATION; + else configurationResourceLinkNotAvailable + " + data-test-id="router-outlet" + ></router-outlet> + <ng-template #configurationResourceLinkNotAvailable> + <unavailable-page></unavailable-page> + </ng-template> </main> </div> <span data-test-id="build-version">Version: {{ apiRoot.version }}</span> diff --git a/alfa-client/apps/admin/src/app/app.component.spec.ts b/alfa-client/apps/admin/src/app/app.component.spec.ts index 3fe0aa1ac3590a65da846188511aef82710bcee5..3fa47f553b5adab8c940a6c1e1fdcc499722f4c0 100644 --- a/alfa-client/apps/admin/src/app/app.component.spec.ts +++ b/alfa-client/apps/admin/src/app/app.component.spec.ts @@ -1,8 +1,14 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { AppComponent } from './app.component'; -import { existsAsHtmlElement, mock, Mock, notExistsAsHtmlElement } from '@alfa-client/test-utils'; -import { ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared'; +import { + existsAsHtmlElement, + getElementFromFixture, + mock, + Mock, + notExistsAsHtmlElement, +} from '@alfa-client/test-utils'; +import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; import { of } from 'rxjs'; @@ -12,15 +18,18 @@ import { Router } from '@angular/router'; import { NavigationComponent } from 'libs/admin-settings/src/lib/navigation/navigation.component'; import { AuthenticationService } from 'authentication'; import { UserProfileButtonContainerComponent } from '../common/user-profile-button-container/user-profile.button-container.component'; +import { ConfigurationService } from '@admin-client/admin-settings'; +import { UnavailablePageComponent } from '../pages/unavailable/unavailable-page/unavailable-page.component'; describe('AppComponent', () => { let component: AppComponent; let fixture: ComponentFixture<AppComponent>; - const adminHeader: string = getDataTestIdOf('admin-header'); - const buildVersion: string = getDataTestIdOf('build-version'); - const userProfileButton: string = getDataTestIdOf('user-profile-button'); - const navigation: string = getDataTestIdOf('navigation'); + const adminHeaderSelector: string = getDataTestIdOf('admin-header'); + const buildVersionSelector: string = getDataTestIdOf('build-version'); + const userProfileButtonSelector: string = getDataTestIdOf('user-profile-button'); + const navigationSelector: string = getDataTestIdOf('navigation'); + const routerOutletSelector: string = getDataTestIdOf('router-outlet'); const authenticationService: Mock<AuthenticationService> = { ...mock(AuthenticationService), @@ -36,6 +45,7 @@ describe('AppComponent', () => { AppComponent, MockComponent(NavigationComponent), MockComponent(UserProfileButtonContainerComponent), + MockComponent(UnavailablePageComponent), ], imports: [RouterTestingModule], providers: [ @@ -58,7 +68,6 @@ describe('AppComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(AppComponent); component = fixture.componentInstance; - fixture.detectChanges(); }); it(`should have as title 'admin'`, () => { @@ -101,7 +110,7 @@ describe('AppComponent', () => { it('show not show header if apiRoot is not loaded', () => { component.apiRootStateResource$ = of(createEmptyStateResource<ApiRootResource>()); - notExistsAsHtmlElement(fixture, adminHeader); + notExistsAsHtmlElement(fixture, adminHeaderSelector); }); describe('user profile button', () => { @@ -112,30 +121,63 @@ describe('AppComponent', () => { it('should show if apiRoot exists', () => { fixture.detectChanges(); - existsAsHtmlElement(fixture, userProfileButton); + existsAsHtmlElement(fixture, userProfileButtonSelector); }); }); describe('navigation', () => { - beforeEach(() => { - component.apiRootStateResource$ = of(createStateResource(createApiRootResource())); + beforeEach(() => {}); + it('should exist if configuration link exists', () => { + component.apiRootStateResource$ = of( + createStateResource(createApiRootResource([ApiRootLinkRel.CONFIGURATION])), + ); + + fixture.detectChanges(); + + existsAsHtmlElement(fixture, navigationSelector); }); - it('should exists', () => { + + it('should not exist if configuration resource not available', () => { fixture.detectChanges(); - existsAsHtmlElement(fixture, navigation); + notExistsAsHtmlElement(fixture, navigationSelector); }); }); describe('build version', () => { + const apiResource: ApiRootResource = createApiRootResource(); + beforeEach(() => { - component.apiRootStateResource$ = of(createStateResource(createApiRootResource())); + component.apiRootStateResource$ = of(createStateResource(apiResource)); }); it('should show after apiRoot loaded', () => { fixture.detectChanges(); - existsAsHtmlElement(fixture, buildVersion); + const buildVersionElement = getElementFromFixture(fixture, buildVersionSelector); + expect(buildVersionElement.textContent.trim()).toEqual(`Version: ${apiResource.version}`); + }); + }); + + describe('router outlet', () => { + beforeEach(() => {}); + + it('should exist if configuration resource available', () => { + component.apiRootStateResource$ = of( + createStateResource(createApiRootResource([ApiRootLinkRel.CONFIGURATION])), + ); + + fixture.detectChanges(); + + existsAsHtmlElement(fixture, routerOutletSelector); + }); + + it('should not exist if configuration resource not available', () => { + component.apiRootStateResource$ = of(createStateResource(createApiRootResource())); + + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, routerOutletSelector); }); }); }); diff --git a/alfa-client/apps/admin/src/app/app.component.ts b/alfa-client/apps/admin/src/app/app.component.ts index 198bc3207d5b1a4e5242d3126e636c254dde891c..cffa4bd597c449b8057f42f10f959fc1823ad230 100644 --- a/alfa-client/apps/admin/src/app/app.component.ts +++ b/alfa-client/apps/admin/src/app/app.component.ts @@ -1,4 +1,4 @@ -import { ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared'; +import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared'; import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { StateResource } from '@alfa-client/tech-shared'; @@ -29,4 +29,6 @@ export class AppComponent implements OnInit { this.apiRootStateResource$ = this.apiRootService.getApiRoot(); this.router.navigate(['/']); } + + protected readonly ApiRootLinkRel = ApiRootLinkRel; } diff --git a/alfa-client/apps/admin/src/app/app.module.ts b/alfa-client/apps/admin/src/app/app.module.ts index f19f81f549d57aa324e8015507b93a3441c0ba87..5036e2f54cfd969333b209f909b99becb1f99971 100644 --- a/alfa-client/apps/admin/src/app/app.module.ts +++ b/alfa-client/apps/admin/src/app/app.module.ts @@ -21,6 +21,8 @@ import { AdminSettingsModule } from '@admin-client/admin-settings'; import { OAuthModule } from 'angular-oauth2-oidc'; import { HttpUnauthorizedInterceptor } from 'libs/authentication/src/lib/http-unauthorized.interceptor'; import { OrganisationseinheitPageComponent } from '../pages/organisationseinheit/organisationseinheit-page/organisationseinheit-page.component'; +import { UnavailablePageComponent } from '../pages/unavailable/unavailable-page/unavailable-page.component'; +import { TechSharedModule } from '@alfa-client/tech-shared'; @NgModule({ declarations: [ @@ -28,6 +30,7 @@ import { OrganisationseinheitPageComponent } from '../pages/organisationseinheit PostfachPageComponent, OrganisationseinheitPageComponent, UserProfileButtonContainerComponent, + UnavailablePageComponent, ], imports: [ CommonModule, @@ -50,6 +53,7 @@ import { OrganisationseinheitPageComponent } from '../pages/organisationseinheit sendAccessToken: true, }, }), + TechSharedModule, ], providers: [ { diff --git a/alfa-client/apps/admin/src/pages/unavailable/unavailable-page/unavailable-page.component.html b/alfa-client/apps/admin/src/pages/unavailable/unavailable-page/unavailable-page.component.html new file mode 100644 index 0000000000000000000000000000000000000000..f380cbb10ec6f603768bdad662fd23469e685071 --- /dev/null +++ b/alfa-client/apps/admin/src/pages/unavailable/unavailable-page/unavailable-page.component.html @@ -0,0 +1,7 @@ +<p class="mb-2 block font-bold">Die Administrations-Oberfläche ist nicht verfügbar.</p> + +<p> + Prüfen Sie, ob folgendes zutrifft:<br /> + Ihnen ist die Rolle Admin_Admin zugewiesen.<br /> + Bitte bei der verantwortlichen Person des User-Managements bzw. des Keycloaks melden.<br /> +</p> diff --git a/alfa-client/apps/admin/src/pages/unavailable/unavailable-page/unavailable-page.component.spec.ts b/alfa-client/apps/admin/src/pages/unavailable/unavailable-page/unavailable-page.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..5774dc89c467a7c686f56b1ac4650ac4c2ccaf53 --- /dev/null +++ b/alfa-client/apps/admin/src/pages/unavailable/unavailable-page/unavailable-page.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { UnavailablePageComponent } from './unavailable-page.component'; + +describe('UnavailablePageComponent', () => { + let component: UnavailablePageComponent; + let fixture: ComponentFixture<UnavailablePageComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [UnavailablePageComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(UnavailablePageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/apps/admin/src/pages/unavailable/unavailable-page/unavailable-page.component.ts b/alfa-client/apps/admin/src/pages/unavailable/unavailable-page/unavailable-page.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..597b820658e91b2fa84f5e33323b3493a41ff52b --- /dev/null +++ b/alfa-client/apps/admin/src/pages/unavailable/unavailable-page/unavailable-page.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'unavailable-page', + templateUrl: './unavailable-page.component.html', + styles: [], +}) +export class UnavailablePageComponent {}