diff --git a/alfa-client/apps/admin/src/app/app.component.html b/alfa-client/apps/admin/src/app/app.component.html index e504907b9ccb1ec0508e433b30f040f7ca174f99..f9f6573f38f14c261b0d6c431ad1fb0a1cd327c5 100644 --- a/alfa-client/apps/admin/src/app/app.component.html +++ b/alfa-client/apps/admin/src/app/app.component.html @@ -2,18 +2,22 @@ <header class="flex items-center justify-between bg-white p-6" data-test-id="admin-header"> <div class="text-ozgblue font-extrabold">OZG-Cloud Administration</div> <div> - <user-profile-button-container data-test-id="user-profile-button"></user-profile-button-container> + <user-profile-button-container + data-test-id="user-profile-button" + ></user-profile-button-container> </div> </header> <div class="relative flex w-full flex-auto justify-center"> - <div class="w-96 bg-slate-300 p-6"> - <nav> - NAV - </nav> - </div> + <div class="w-60 bg-slate-100 p-6"> + <nav> + <postfach-navigation-item + data-test-id="postfach-navigation-item" + ></postfach-navigation-item> + </nav> + </div> <main class="flex-auto bg-slate-200 p-6"> - <router-outlet></router-outlet> + <router-outlet></router-outlet> </main> </div> <span data-test-id="build-version">Version: {{ apiRoot.buildVersion }}</span> -</ng-container> \ No newline at end of file +</ng-container> 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 29671cb8504f5d6630a96f8b757de417386b917b..0fd3f5bb0cc54356d34ab02ddcff92a344d730bc 100644 --- a/alfa-client/apps/admin/src/app/app.component.spec.ts +++ b/alfa-client/apps/admin/src/app/app.component.spec.ts @@ -10,6 +10,7 @@ import { of } from 'rxjs'; import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; import { MockComponent } from 'ng-mocks'; import { UserProfileButtonContainerComponent } from '../common/user-profile-button-container/user-profile.button-container.component'; +import { PostfachNavigationItemComponent } from '../pages/postfach/postfach-navigation-item/postfach-navigation-item.component'; describe('AppComponent', () => { let component: AppComponent; @@ -18,13 +19,18 @@ describe('AppComponent', () => { const adminHeader: string = getDataTestIdOf('admin-header'); const buildVersion: string = getDataTestIdOf('build-version'); const userProfileButton: string = getDataTestIdOf('user-profile-button'); + const postfachNavigationItem: string = getDataTestIdOf('postfach-navigation-item'); const authService: Mock<AuthService> = mock(AuthService); const apiRootService: Mock<ApiRootService> = mock(ApiRootService); beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [AppComponent, MockComponent(UserProfileButtonContainerComponent)], + declarations: [ + AppComponent, + MockComponent(UserProfileButtonContainerComponent), + MockComponent(PostfachNavigationItemComponent), + ], imports: [RouterTestingModule], providers: [ { @@ -94,6 +100,17 @@ describe('AppComponent', () => { }); }); + describe('navigation', () => { + beforeEach(() => { + component.apiRoot$ = of(createStateResource(createApiRootResource())); + }); + it('should have postfach item', () => { + fixture.detectChanges(); + + existsAsHtmlElement(fixture, postfachNavigationItem); + }); + }); + describe('build version', () => { beforeEach(() => { component.apiRoot$ = of(createStateResource(createApiRootResource())); diff --git a/alfa-client/apps/admin/src/app/app.module.ts b/alfa-client/apps/admin/src/app/app.module.ts index 1c61909253212188bb0e527b6238e60c33f3ddae..e13deaf980ec4811058fd72666bd6a47659f2c47 100644 --- a/alfa-client/apps/admin/src/app/app.module.ts +++ b/alfa-client/apps/admin/src/app/app.module.ts @@ -16,11 +16,19 @@ import { environment } from '../environments/environment'; import { AppComponent } from './app.component'; import { initializeKeycloak } from './app.config'; import { appRoutes } from './app.routes'; +import { PostfachPageComponent } from '../pages/postfach/postfach-page/postfach-page.component'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { UserProfileButtonContainerComponent } from '../common/user-profile-button-container/user-profile.button-container.component'; +import { AdminSettingsModule } from '@admin-client/admin-settings'; +import { PostfachNavigationItemComponent } from '../pages/postfach/postfach-navigation-item/postfach-navigation-item.component'; @NgModule({ - declarations: [AppComponent, UserProfileButtonContainerComponent], + declarations: [ + AppComponent, + PostfachPageComponent, + UserProfileButtonContainerComponent, + PostfachNavigationItemComponent, + ], imports: [ CommonModule, TestbtnComponent, @@ -37,6 +45,7 @@ import { UserProfileButtonContainerComponent } from '../common/user-profile-butt StoreRouterConnectingModule.forRoot(), FormsModule, ReactiveFormsModule, + AdminSettingsModule, ], providers: [ { diff --git a/alfa-client/apps/admin/src/app/app.routes.ts b/alfa-client/apps/admin/src/app/app.routes.ts index 8762dfe2c6510c01425b35c6cf76371cc0b332c6..1834aa696228932a34d0b76ea2398d7e6a80b9c6 100644 --- a/alfa-client/apps/admin/src/app/app.routes.ts +++ b/alfa-client/apps/admin/src/app/app.routes.ts @@ -1,3 +1,15 @@ import { Route } from '@angular/router'; +import { PostfachPageComponent } from '../pages/postfach/postfach-page/postfach-page.component'; -export const appRoutes: Route[] = []; +export const appRoutes: Route[] = [ + { + path: '', + redirectTo: 'postfach', + pathMatch: 'full', + }, + { + path: 'postfach', + component: PostfachPageComponent, + title: 'Admin | Postfach', + }, +]; diff --git a/alfa-client/apps/admin/src/assets/mail.svg b/alfa-client/apps/admin/src/assets/mail.svg new file mode 100644 index 0000000000000000000000000000000000000000..510a1dc44dadd31e431e74cae39be8f248344465 --- /dev/null +++ b/alfa-client/apps/admin/src/assets/mail.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 14H4V8l8 5 8-5v10zm-8-7L4 6h16l-8 5z"/></svg> \ No newline at end of file diff --git a/alfa-client/apps/admin/src/main.ts b/alfa-client/apps/admin/src/main.ts index 5d388e265a6adda237cd7b2c9650f0055ca1457d..5e03b925b784465a49e2f49ead63c0801124b6b0 100644 --- a/alfa-client/apps/admin/src/main.ts +++ b/alfa-client/apps/admin/src/main.ts @@ -1,22 +1,23 @@ import { loadEnvironment } from '@alfa-client/environment-shared'; import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; -import { isNil } from 'lodash-es'; import { AppModule } from './app/app.module'; +import { isNil } from 'lodash-es'; import { environment } from './environments/environment'; loadEnvironment(environment.environmentUrl).then((env) => { - if (isNil(env)) { - console.error('Connection Error: environment is undefined'); - return; - } - if (env.production) { - enableProdMode(); - } - console.info('init bootstrap application...'); - //Für Standalone AppComponent - //bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err)); - platformBrowserDynamic() - .bootstrapModule(AppModule) - .catch((err) => console.log(err)); + if (isNil(env?.production)) { + console.error('Connection Error: environment is ', env); + return; + } + + if (env.production) { + enableProdMode(); + } + console.info('init bootstrap application...'); + //Für Standalone AppComponent + //bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err)); + platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err) => console.log(err)); }); diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.html b/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.html new file mode 100644 index 0000000000000000000000000000000000000000..aeceb900769ddcc0a0c4865c1b50fc0bf86f7a7b --- /dev/null +++ b/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.html @@ -0,0 +1 @@ +<navigation-item name="Postfach" imageSrc="/assets/mail.svg" link="/postfach"></navigation-item> diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.spec.ts b/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..d56e1f5c365d0aa5f650dcba1ae0345a3e41e8c9 --- /dev/null +++ b/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.spec.ts @@ -0,0 +1,28 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { PostfachNavigationItemComponent } from './postfach-navigation-item.component'; +import { MockComponent } from 'ng-mocks'; +import { ReactiveFormsModule } from '@angular/forms'; +import { NavigationItemComponent } from '@admin-client/admin-settings'; + +describe('PostfachPageComponent', () => { + let component: PostfachNavigationItemComponent; + let fixture: ComponentFixture<PostfachNavigationItemComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [PostfachNavigationItemComponent, MockComponent(NavigationItemComponent)], + imports: [ReactiveFormsModule], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PostfachNavigationItemComponent); + component = fixture.componentInstance; + + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.ts b/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..4c4820aa819932b900cd38d56aeb455124937ff5 --- /dev/null +++ b/alfa-client/apps/admin/src/pages/postfach/postfach-navigation-item/postfach-navigation-item.component.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'postfach-navigation-item', + templateUrl: './postfach-navigation-item.component.html', +}) +export class PostfachNavigationItemComponent {} diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.html b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.html new file mode 100644 index 0000000000000000000000000000000000000000..f066382bdd23dcf46af0b372491f28b4ba678b06 --- /dev/null +++ b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.html @@ -0,0 +1 @@ +<postfach-container></postfach-container> diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.spec.ts b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..8392b508a608c5dae1ba4c1edb6df5bf7e223114 --- /dev/null +++ b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.spec.ts @@ -0,0 +1,28 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { PostfachPageComponent } from './postfach-page.component'; +import { MockComponent } from 'ng-mocks'; +import { ReactiveFormsModule } from '@angular/forms'; +import { PostfachContainerComponent } from '@admin-client/admin-settings'; + +describe('PostfachPageComponent', () => { + let component: PostfachPageComponent; + let fixture: ComponentFixture<PostfachPageComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [PostfachPageComponent, MockComponent(PostfachContainerComponent)], + imports: [ReactiveFormsModule], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PostfachPageComponent); + component = fixture.componentInstance; + + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.ts b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..1d9a54ceddbd6e663477e382dbbff95d9ab13c66 --- /dev/null +++ b/alfa-client/apps/admin/src/pages/postfach/postfach-page/postfach-page.component.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'postfach-page', + templateUrl: './postfach-page.component.html', +}) +export class PostfachPageComponent {} diff --git a/alfa-client/libs/admin-settings/.eslintrc.json b/alfa-client/libs/admin-settings/.eslintrc.json new file mode 100644 index 0000000000000000000000000000000000000000..adbe7ae2dfabd4a42804f00846baec80877f4c5c --- /dev/null +++ b/alfa-client/libs/admin-settings/.eslintrc.json @@ -0,0 +1,25 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.ts", "*.tsx"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "rules": {} + }, + { + "files": ["*.json"], + "parser": "jsonc-eslint-parser", + "rules": { + "@nx/dependency-checks": "error" + } + } + ] +} diff --git a/alfa-client/libs/admin-settings/README.md b/alfa-client/libs/admin-settings/README.md new file mode 100644 index 0000000000000000000000000000000000000000..01b723f8400c9c3dd0f79fe697c5b1be2441a3eb --- /dev/null +++ b/alfa-client/libs/admin-settings/README.md @@ -0,0 +1,7 @@ +# admin-settings + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test admin-settings` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/alfa-client/libs/admin-settings/jest.config.ts b/alfa-client/libs/admin-settings/jest.config.ts new file mode 100644 index 0000000000000000000000000000000000000000..84427413b7cbe34595a96099da2cfafce5e69036 --- /dev/null +++ b/alfa-client/libs/admin-settings/jest.config.ts @@ -0,0 +1,23 @@ +/* eslint-disable */ +export default { + displayName: 'admin-settings', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/admin-settings', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/alfa-client/libs/admin-settings/project.json b/alfa-client/libs/admin-settings/project.json new file mode 100644 index 0000000000000000000000000000000000000000..073f1bfb8ef6bc708062de6387ef1a3fd9e31dd6 --- /dev/null +++ b/alfa-client/libs/admin-settings/project.json @@ -0,0 +1,25 @@ +{ + "name": "admin-settings", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/admin-settings/src", + "projectType": "library", + "prefix": "admin", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/admin-settings/package.json"] + } + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/admin-settings/jest.config.ts", + "passWithNoTests": true + } + } + }, + "tags": [] +} diff --git a/alfa-client/libs/admin-settings/src/index.ts b/alfa-client/libs/admin-settings/src/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..c0ce9b0d2d421edb40ae3069ce1adcb3884b6d36 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/index.ts @@ -0,0 +1,3 @@ +export * from './lib/admin-settings.module'; +export * from './lib/postfach/postfach-container/postfach-container.component'; +export * from './lib/shared/navigation-item/navigation-item.component'; diff --git a/alfa-client/libs/admin-settings/src/lib/admin-settings.module.spec.ts b/alfa-client/libs/admin-settings/src/lib/admin-settings.module.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..088fd75aa2076bf00593453f508704a6e6634344 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/admin-settings.module.spec.ts @@ -0,0 +1,14 @@ +import { TestBed } from '@angular/core/testing'; +import { AdminSettingsModule } from './admin-settings.module'; + +describe('AdminSettingsModule', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [AdminSettingsModule], + }); + }); + + it('should create', () => { + expect(AdminSettingsModule).toBeDefined(); + }); +}); 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 new file mode 100644 index 0000000000000000000000000000000000000000..7e62764c345cbfc8915b7d11d2132e0e3382c83a --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/admin-settings.module.ts @@ -0,0 +1,21 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { TechSharedModule } from '@alfa-client/tech-shared'; +import { NavigationItemComponent } from './shared/navigation-item/navigation-item.component'; +import { RouterModule } from '@angular/router'; +import { ReactiveFormsModule } from '@angular/forms'; +import { PostfachContainerComponent } from './postfach/postfach-container/postfach-container.component'; +import { PostfachFormComponent } from './postfach/postfach-container/postfach-form/postfach-form.component'; +import { TextFieldComponent } from './shared/text-field/text-field.component'; + +@NgModule({ + declarations: [ + PostfachContainerComponent, + PostfachFormComponent, + NavigationItemComponent, + TextFieldComponent, + ], + imports: [CommonModule, TechSharedModule, RouterModule, ReactiveFormsModule], + exports: [PostfachContainerComponent, NavigationItemComponent], +}) +export class AdminSettingsModule {} diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.html b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.html new file mode 100644 index 0000000000000000000000000000000000000000..f2e1c9803bf2ba4b38f629bdac9187c6a5d22a2c --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.html @@ -0,0 +1 @@ +<postfach-form></postfach-form> diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.scss b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..6d086752157a5429e787661c76783f5250df42e9 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.spec.ts @@ -0,0 +1,31 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { PostfachContainerComponent } from '@admin-client/admin-settings'; + +import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; +import { ReactiveFormsModule, UntypedFormGroup } from '@angular/forms'; + +import { PostfachFormComponent } from './postfach-form/postfach-form.component'; +import { MockComponent } from 'ng-mocks'; + +describe('PostfachContainerComponent', () => { + let component: PostfachContainerComponent; + let fixture: ComponentFixture<PostfachContainerComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [PostfachContainerComponent, MockComponent(PostfachFormComponent)], + imports: [ReactiveFormsModule], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PostfachContainerComponent); + component = fixture.componentInstance; + + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..6a9e73281ece58b6f3c416d8bd34a95d9eb9d217 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-container.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'postfach-container', + templateUrl: './postfach-container.component.html', + styleUrls: ['./postfach-container.component.scss'], +}) +export class PostfachContainerComponent {} diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.html b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.html new file mode 100644 index 0000000000000000000000000000000000000000..4ddfd2b7a927afdb4016395058ed22486429588a --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.html @@ -0,0 +1,53 @@ +<form class="form flex-col" [formGroup]="formService.form"> + <h1 class="text-2xl font-bold">Absender</h1> + <p id="absender-desc" class="p-1">Hinterlegen Sie Absenderinformationen zu Ihrem Postfach.</p> + <div aria-describedby="absender-desc" class="grid-col-1 mb-2 mt-2 grid w-96 gap-1"> + <text-field + inputId="absender-name" + data-test-id="absender-name" + label="Name" + [formControlName]="PostfachFormService.NAME_FIELD" + ></text-field> + <text-field + inputId="absender-anschrift" + data-test-id="absender-anschrift" + label="Anschrift" + [formControlName]="PostfachFormService.ANSCHRIFT_FIELD" + ></text-field> + <text-field + inputId="absender-dienst" + data-test-id="absender-dienst" + label="Dienst" + [formControlName]="PostfachFormService.DIENST_FIELD" + ></text-field> + <text-field + inputId="absender-mandant" + data-test-id="absender-mandant" + label="Mandant" + [formControlName]="PostfachFormService.MANDANT_FIELD" + ></text-field> + <text-field + inputId="absender-gemeindeschluessel" + data-test-id="absender-gemeindeschluessel" + label="Gemeindeschlüssel" + [formControlName]="PostfachFormService.GEMEINDESCHLUESSEL_FIELD" + ></text-field> + </div> + <div class="h-20"></div> + <h1 class="text-2xl font-bold">Signatur</h1> + <p id="signatur-desc">Erstellen oder ändern Sie die Signatur für Nachrichten.</p> + <textarea + data-test-id="signatur-text" + aria-describedby="signatur-desc" + [formControlName]="PostfachFormService.SIGNATUR_FIELD" + class="mb-2 mt-2 block h-40 w-96 p-1" + ></textarea> + + <button + (click)="submit()" + data-test-id="save-button" + class="bg-ozgblue-700 hover:bg-ozgblue-600 active:bg-ozgblue-600/90 focus-visible:outline-ozgblue-800 rounded-md px-3 py-2 text-sm font-semibold text-white shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2" + > + Speichern + </button> +</form> diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.scss b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..ee99eb6160254fa35e04559a9f11fa2bece3e8f4 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.spec.ts @@ -0,0 +1,93 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { PostfachFormComponent } from './postfach-form.component'; +import { FormsModule, ReactiveFormsModule, UntypedFormGroup } from '@angular/forms'; +import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; +import { + dispatchEventFromFixture, + existsAsHtmlElement, + getElementFromFixture, +} from '@alfa-client/test-utils'; +import { PostfachFormService } from './postfach.formservice'; +import { MockComponent } from 'ng-mocks'; +import { TextFieldComponent } from '../../../shared/text-field/text-field.component'; + +describe('PostfachFormComponent', () => { + let component: PostfachFormComponent; + let fixture: ComponentFixture<PostfachFormComponent>; + let form: UntypedFormGroup; + + const saveButton: string = getDataTestIdOf('save-button'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [PostfachFormComponent, MockComponent(TextFieldComponent)], + imports: [ReactiveFormsModule, FormsModule], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PostfachFormComponent); + component = fixture.componentInstance; + form = fixture.componentInstance.formService.form; + + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('Absender section', () => { + const fields = [ + [PostfachFormService.NAME_FIELD, 'Name', 'absender-name'], + [PostfachFormService.ANSCHRIFT_FIELD, 'Anschrift', 'absender-anschrift'], + [PostfachFormService.DIENST_FIELD, 'Dienst', 'absender-dienst'], + [PostfachFormService.MANDANT_FIELD, 'Mandant', 'absender-mandant'], + [ + PostfachFormService.GEMEINDESCHLUESSEL_FIELD, + 'Gemeindeschlüssel', + 'absender-gemeindeschluessel', + ], + ]; + + test.each(fields)( + 'should have label for field "%s" with name "%s"', + (fieldName, text, inputId) => { + const textFieldElement = getElementFromFixture(fixture, getDataTestIdOf(inputId)); + expect(textFieldElement.getAttribute('label')).toBe(text); + }, + ); + + test.each(fields)('should have inputId for field "%s"', (fieldName, text, inputId) => { + const textFieldElement = getElementFromFixture(fixture, getDataTestIdOf(inputId)); + expect(textFieldElement.getAttribute('inputId')).toBe(inputId); + }); + }); + + describe('Signatur section', () => { + const signaturTextarea = getDataTestIdOf('signatur-text'); + + it('should have signatur-text', () => { + existsAsHtmlElement(fixture, signaturTextarea); + }); + + it('should use form control for signatur-text', () => { + const someText = 'some signatur text'; + + form.get(PostfachFormService.SIGNATUR_FIELD).setValue(someText); + + const signatur = getElementFromFixture(fixture, signaturTextarea); + expect(signatur.value).toBe(someText); + }); + }); + + describe('save button', () => { + it('should call submit on click', () => { + component.submit = jest.fn(); + + dispatchEventFromFixture(fixture, saveButton, 'click'); + + expect(component.submit).toHaveBeenCalled(); + }); + }); +}); diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..f63f202379e5516f96668102acda229996af14f8 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; +import { PostfachFormService } from './postfach.formservice'; + +@Component({ + selector: 'postfach-form', + templateUrl: './postfach-form.component.html', + styleUrls: ['./postfach-form.component.scss'], + providers: [PostfachFormService], +}) +export class PostfachFormComponent { + constructor(public formService: PostfachFormService) {} + + protected readonly PostfachFormService = PostfachFormService; + + public submit() { + this.formService.submit(); + } +} diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.spec.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..0927e3991e8386cae53cb79bd05ec7b1f8359d91 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.spec.ts @@ -0,0 +1,16 @@ +import { FormBuilder } from '@angular/forms'; +import { PostfachFormService } from './postfach.formservice'; + +describe('PostfachFormService', () => { + let formService: PostfachFormService; + + const formBuilder: FormBuilder = new FormBuilder(); + + beforeEach(() => { + formService = new PostfachFormService(formBuilder); + }); + + it('should create', () => { + expect(formService).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.ts new file mode 100644 index 0000000000000000000000000000000000000000..53829e1fce73f0d3dbb83fcb30d91fafc1a576d0 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.ts @@ -0,0 +1,43 @@ +import { + AbstractFormService, + StateResource, + createEmptyStateResource, +} from '@alfa-client/tech-shared'; +import { Injectable } from '@angular/core'; +import { FormControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { Resource } from '@ngxp/rest'; +import { Observable, of } from 'rxjs'; + +@Injectable() +export class PostfachFormService extends AbstractFormService { + public static readonly NAME_FIELD: string = 'name'; + public static readonly ANSCHRIFT_FIELD: string = 'anschrift'; + public static readonly DIENST_FIELD: string = 'dienst'; + public static readonly MANDANT_FIELD: string = 'mandant'; + public static readonly GEMEINDESCHLUESSEL_FIELD: string = 'gemeindeschluessel'; + public static readonly SIGNATUR_FIELD: string = 'signatur'; + + constructor(formBuilder: UntypedFormBuilder) { + super(formBuilder); + } + + protected initForm(): UntypedFormGroup { + return this.formBuilder.group({ + [PostfachFormService.NAME_FIELD]: new FormControl(), + [PostfachFormService.ANSCHRIFT_FIELD]: new FormControl(), + [PostfachFormService.DIENST_FIELD]: new FormControl(), + [PostfachFormService.MANDANT_FIELD]: new FormControl(), + [PostfachFormService.GEMEINDESCHLUESSEL_FIELD]: new FormControl(), + [PostfachFormService.SIGNATUR_FIELD]: new FormControl(), + }); + } + + protected doSubmit(): Observable<StateResource<Resource>> { + console.info('FormValue: ', this.getFormValue()); + return of(createEmptyStateResource<Resource>()); + } + + protected getPathPrefix(): string { + return ''; + } +} diff --git a/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.html b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.html new file mode 100644 index 0000000000000000000000000000000000000000..c9f7e36c16335c9f94d205e9724542a219c62612 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.html @@ -0,0 +1,9 @@ +<a + [routerLink]="link" + routerLinkActive="active-link" + data-test-id="anchor" + class="hover:bg-ozgblue-200 active:bg-ozgblue-200/75 flex items-center gap-4 rounded-full p-3 font-semibold" +> + <img [src]="imageSrc" [alt]="name" class="w-6" [attr.data-test-id]="'image-' + name" /> + <span [attr.data-test-id]="'navigation-label-' + name | convertForDataTest">{{ name }}</span> +</a> diff --git a/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.scss b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..9214426c081848ac1a46efac41e715a120eeff02 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.scss @@ -0,0 +1,3 @@ +.active-link:not(:hover):not(:active) { + @apply bg-ozgblue-100; +} diff --git a/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..e800d7acf9df48a08b81190c029858010e332ad3 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.spec.ts @@ -0,0 +1,67 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ReactiveFormsModule } from '@angular/forms'; +import { NavigationItemComponent } from './navigation-item.component'; +import { getElementFromFixture } from '@alfa-client/test-utils'; +import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; +import { RouterTestingModule } from '@angular/router/testing'; +import { ConvertForDataTestPipe } from '@alfa-client/tech-shared'; + +describe('NavigationItemComponent', () => { + let component: NavigationItemComponent; + let fixture: ComponentFixture<NavigationItemComponent>; + + const anchorLink = getDataTestIdOf('anchor'); + const navigationLabelName = 'test'; + const image = getDataTestIdOf('image-' + navigationLabelName); + const label = getDataTestIdOf('navigation-label-' + navigationLabelName); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [NavigationItemComponent, ConvertForDataTestPipe], + imports: [ReactiveFormsModule, RouterTestingModule], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(NavigationItemComponent); + component = fixture.componentInstance; + component.name = 'test'; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should use imageSrc input', () => { + const imageSrc = 'imagesrc'; + component.imageSrc = imageSrc; + + fixture.detectChanges(); + + const imageElement: HTMLImageElement = getElementFromFixture(fixture, image); + expect(imageElement.getAttribute('src')).toBe(imageSrc); + }); + + it('should use router link', () => { + const link = '/testroute'; + component.link = link; + + fixture.detectChanges(); + + const anchorElement: HTMLAnchorElement = getElementFromFixture(fixture, anchorLink); + expect(anchorElement.getAttribute('ng-reflect-router-link')).toBe(link); + }); + + describe('image name', () => { + it('should be used for alt', () => { + const imageElement = getElementFromFixture(fixture, image); + expect(imageElement.alt).toBe(navigationLabelName); + }); + + it('should be used for navigation-label', () => { + const labelElement = getElementFromFixture(fixture, label); + expect(labelElement.textContent).toBe(navigationLabelName); + }); + }); +}); diff --git a/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.ts b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..f1b2e5f0f36c2575bf567d660fb63f1ff6da2938 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/shared/navigation-item/navigation-item.component.ts @@ -0,0 +1,15 @@ +import { Component, Input } from '@angular/core'; + +@Component({ + selector: 'navigation-item', + templateUrl: './navigation-item.component.html', + styleUrls: ['./navigation-item.component.scss'], +}) +export class NavigationItemComponent { + @Input() + link: string; + @Input() + imageSrc: string; + @Input() + name = 'Navigations-Link'; +} diff --git a/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.html b/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.html new file mode 100644 index 0000000000000000000000000000000000000000..c11e2cfdb73de1e35a9eb09c2e32846a8cbe4265 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.html @@ -0,0 +1,8 @@ +<label class="grid grid-cols-2"> + <span [attr.data-test-id]="'text-field-span-' + label | convertForDataTest">{{ label }}</span> + <input + [attr.data-test-id]="'text-field-input-' + label | convertForDataTest" + type="text" + [formControl]="fieldControl" + /> +</label> diff --git a/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..27baea4a3893bd7107800d210579220e9c621f93 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.spec.ts @@ -0,0 +1,46 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TextFieldComponent } from './text-field.component'; +import { getElementFromFixture } from '@alfa-client/test-utils'; +import { ReactiveFormsModule } from '@angular/forms'; +import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; +import { ConvertForDataTestPipe } from '@alfa-client/tech-shared'; + +describe('TextFieldComponent', () => { + let component: TextFieldComponent; + let fixture: ComponentFixture<TextFieldComponent>; + + const label = 'custom'; + const span = getDataTestIdOf('text-field-span-' + label); + const input = getDataTestIdOf('text-field-input-' + label); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [TextFieldComponent, ConvertForDataTestPipe], + imports: [ReactiveFormsModule], + }).compileComponents(); + + fixture = TestBed.createComponent(TextFieldComponent); + component = fixture.componentInstance; + component.label = label; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should use label', () => { + const labelElement = getElementFromFixture(fixture, span); + expect(labelElement.textContent).toBe(label); + }); + + it('should use form control', () => { + const fieldText = 'text'; + component.writeValue(fieldText); + + fixture.detectChanges(); + + const inputElement = getElementFromFixture(fixture, input); + expect(inputElement.value).toBe(fieldText); + }); +}); diff --git a/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.ts b/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..92abc83d9409865ee79be841d06d3b255c57ff3a --- /dev/null +++ b/alfa-client/libs/admin-settings/src/lib/shared/text-field/text-field.component.ts @@ -0,0 +1,11 @@ +import { Component, Input } from '@angular/core'; +import { FormControlEditorAbstractComponent } from 'libs/ui/src/lib/ui/editor/formcontrol-editor.abstract.component'; + +@Component({ + selector: 'text-field', + templateUrl: './text-field.component.html', +}) +export class TextFieldComponent extends FormControlEditorAbstractComponent { + @Input() + label: string; +} diff --git a/alfa-client/libs/admin-settings/src/test-setup.ts b/alfa-client/libs/admin-settings/src/test-setup.ts new file mode 100644 index 0000000000000000000000000000000000000000..e09d95a1bd4455db9bfd16809b94659c30a83956 --- /dev/null +++ b/alfa-client/libs/admin-settings/src/test-setup.ts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ +import '@testing-library/jest-dom'; +import 'jest-preset-angular/setup-jest'; + +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, +} from '@angular/platform-browser-dynamic/testing'; + +getTestBed().resetTestEnvironment(); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/admin-settings/tsconfig.json b/alfa-client/libs/admin-settings/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..03261df5a47903bb7d4de17fbef9e9a14b048bed --- /dev/null +++ b/alfa-client/libs/admin-settings/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } +} diff --git a/alfa-client/libs/admin-settings/tsconfig.lib.json b/alfa-client/libs/admin-settings/tsconfig.lib.json new file mode 100644 index 0000000000000000000000000000000000000000..dcc35a71ee8a26bc9394b9cf96b02996be26ec16 --- /dev/null +++ b/alfa-client/libs/admin-settings/tsconfig.lib.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": ["src/test-setup.ts", "src/**/*.spec.ts", "jest.config.ts", "src/**/*.test.ts"], + "include": ["src/**/*.ts"] +} diff --git a/alfa-client/libs/admin-settings/tsconfig.spec.json b/alfa-client/libs/admin-settings/tsconfig.spec.json new file mode 100644 index 0000000000000000000000000000000000000000..c3cb17f784fa2f7b9a4b0e7c9b03663500f4ee3d --- /dev/null +++ b/alfa-client/libs/admin-settings/tsconfig.spec.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] +} diff --git a/alfa-client/tsconfig.base.json b/alfa-client/tsconfig.base.json index d0242502a79252e59ba623be19ca9200a4e3ae4e..273aa6f0fd7e8b8dc7bfe7e87a4f644820431bf8 100644 --- a/alfa-client/tsconfig.base.json +++ b/alfa-client/tsconfig.base.json @@ -16,6 +16,7 @@ "skipDefaultLibCheck": true, "baseUrl": ".", "paths": { + "@admin-client/admin-settings": ["libs/admin-settings/src/index.ts"], "@alfa-client/api-root-shared": ["libs/api-root-shared/src/index.ts"], "@alfa-client/app-shared": ["libs/app-shared/src/index.ts"], "@alfa-client/bescheid": ["libs/bescheid/src/index.ts"],