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/libs/api-root-shared/src/lib/api-root.linkrel.ts b/alfa-client/libs/api-root-shared/src/lib/api-root.linkrel.ts index d8a70c20e7bccf6401fe08087ee4508002b14288..f4f18e65571d33e43ad0c3ea9f27a30107b9c463 100644 --- a/alfa-client/libs/api-root-shared/src/lib/api-root.linkrel.ts +++ b/alfa-client/libs/api-root-shared/src/lib/api-root.linkrel.ts @@ -51,6 +51,9 @@ export enum ApiRootLinkRel { ALL_WIEDERVORLAGEN = 'vorgaenge_wiedervorlagen_all', MY_WIEDERVORLAGEN = 'vorgaenge_wiedervorlagen_my', UNASSIGNED_WIEDERVORLAGEN = 'vorgaenge_wiedervorlagen_unassigned', + ALL_UNGELESENE_NACHRICHTEN = 'vorgaenge_ungelesene_nachrichten_all', + MY_UNGELESENE_NACHRICHTEN = 'vorgaenge_ungelesene_nachrichten_my', + UNASSIGNED_UNGELESENE_NACHRICHTEN = 'vorgaenge_ungelesene_nachrichten_unassigned', ALLE_VORGAENGE_ZU_LOESCHEN = 'vorgaenge_zu_loeschen_all', MEINE_VORGAENGE_ZU_LOESCHEN = 'vorgaenge_zu_loeschen_my', UNASSIGNED_ZU_LOESCHEN = 'vorgaenge_zu_loeschen_unassigned', diff --git a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts index 94216faa5f7884f6fa1252e711f49e26d957462c..c7a5be544eed27c2ee84715549bd578f02b079c7 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts @@ -143,6 +143,7 @@ function createEmptyVorgangStatistic(): VorgangStatistic { }, wiedervorlagen: null, existsWiedervorlageOverdue: false, + ungeleseneNachrichten: 0, }; } diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.ts index 67f6e3da2c32b30e3fe1140a25047b97196b193e..9214160eaabd1f68c97f33762312139fbe2241e9 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.ts @@ -42,6 +42,7 @@ export const BESCHIEDEN_ROUTE_PARAM: string = 'beschieden'; export const ABGESCHLOSSEN_ROUTE_PARAM: string = 'abgeschlossen'; export const VERWORFEN_ROUTE_PARAM: string = 'verworfen'; export const WIEDERVORLAGEN_ROUTE_PARAM: string = 'wiedervorlagen'; +export const UNGELESENE_NACHRICHTEN_ROUTE_PARAM: string = 'ungelesene_nachrichten'; export const ZU_LOESCHEN_ROUTE_PARAM: string = 'zu_loeschen'; export const SEARCH_ROUTE_PARAM: string = 'search'; @@ -56,6 +57,7 @@ export const ROUTE_PARAM_BY_VORGANG_VIEW: { [view: string]: string } = { [VorgangView.VERWORFEN]: VERWORFEN_ROUTE_PARAM, [VorgangView.VORGANG_LIST]: EMPTY_STRING, [VorgangView.WIEDERVORLAGEN]: WIEDERVORLAGEN_ROUTE_PARAM, + [VorgangView.UNGELESENE_NACHRICHTEN]: UNGELESENE_NACHRICHTEN_ROUTE_PARAM, [VorgangView.ZU_LOESCHEN]: ZU_LOESCHEN_ROUTE_PARAM, [VorgangView.SEARCH]: SEARCH_ROUTE_PARAM, }; @@ -68,6 +70,7 @@ export const VORGANG_VIEW_BY_ROUTE_PARAM: { [routeParam: string]: VorgangView } [ABGESCHLOSSEN_ROUTE_PARAM]: VorgangView.ABGESCHLOSSEN, [VERWORFEN_ROUTE_PARAM]: VorgangView.VERWORFEN, [WIEDERVORLAGEN_ROUTE_PARAM]: VorgangView.WIEDERVORLAGEN, + [UNGELESENE_NACHRICHTEN_ROUTE_PARAM]: VorgangView.UNGELESENE_NACHRICHTEN, [ZU_LOESCHEN_ROUTE_PARAM]: VorgangView.ZU_LOESCHEN, [SEARCH_ROUTE_PARAM]: VorgangView.SEARCH, }; diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang.model.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang.model.ts index 41b412c9839bb98940bbdd55ea74e8fcd1e47cb3..c18d952fcec598790bc40eee1a0522742c0eccd3 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang.model.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang.model.ts @@ -109,6 +109,7 @@ export interface VorgangStatistic { byStatus: ByStatus; wiedervorlagen: number; existsWiedervorlageOverdue: boolean; + ungeleseneNachrichten: number; } export interface ByStatus { @@ -163,6 +164,7 @@ export enum VorgangView { WIEDERVORLAGEN, SEARCH, ZU_LOESCHEN, + UNGELESENE_NACHRICHTEN, } export interface StatusCommandMap { diff --git a/alfa-client/libs/vorgang-shared/test/vorgang.ts b/alfa-client/libs/vorgang-shared/test/vorgang.ts index 743c5e65339cfc65091a3db158cdbf8664863b3c..8bddc8cc501bf26b18890d8106b0eef67dc3a3ff 100644 --- a/alfa-client/libs/vorgang-shared/test/vorgang.ts +++ b/alfa-client/libs/vorgang-shared/test/vorgang.ts @@ -145,6 +145,7 @@ export function createVorgangStatistic(): VorgangStatistic { byStatus: createByStatus(), wiedervorlagen: faker.datatype.number(), existsWiedervorlageOverdue: false, + ungeleseneNachrichten: faker.datatype.number(), }; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.html index c7d9d6fc8850a44c562412d25b77ea4a0c2cda83..6c874f1b35f4c2e6ea7955504a4dc69a5937fa6b 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.html @@ -130,6 +130,22 @@ > <div class="dot zu-loeschen"></div> </alfa-vorgang-view-item-container> + <alfa-vorgang-view-item-container + *ngIf=" + apiRootResource + | hasAnyLink + : apiRootLinkRel.ALL_UNGELESENE_NACHRICHTEN + : apiRootLinkRel.MY_UNGELESENE_NACHRICHTEN + : apiRootLinkRel.UNASSIGNED_UNGELESENE_NACHRICHTEN + " + data-test-id="vorgang-ungelesene-nachrichten-view" + label="Ungelesen" + [view]="vorgangView.UNGELESENE_NACHRICHTEN" + [count]="statistic.ungeleseneNachrichten" + class="top-border" + > + <ozgcloud-postfach-icon [showBadge]="true"></ozgcloud-postfach-icon> + </alfa-vorgang-view-item-container> <alfa-vorgang-view-item-container *ngIf=" apiRootResource @@ -142,7 +158,6 @@ label="Wiedervorlagen" [view]="vorgangView.WIEDERVORLAGEN" [count]="statistic.wiedervorlagen" - class="top-border" > <alfa-wiedervorlage-icon [isOverdue]="statistic.existsWiedervorlageOverdue" diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.scss index 4b089df917f623d3d02d1f44fcca2dc9e7ba79c1..6c9cb3c6e3416570c16839d351389bcc3519ff18 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.scss @@ -70,6 +70,8 @@ body.dark :host { } } -ozgcloud-icon { +ozgcloud-icon, +ozgcloud-postfach-icon { margin-right: 6px; + height: $iconHeight; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts index cf4f8bd301a92a054afbf9e6c3d22c7c1af0b5fe..2d312f19021b016c3985e0b17b487fc982210f79 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts @@ -25,7 +25,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ApiRootLinkRel } from '@alfa-client/api-root-shared'; import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared'; import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils'; -import { OzgcloudIconComponent } from '@alfa-client/ui'; +import { OzgcloudIconComponent, PostfachIconComponent } from '@alfa-client/ui'; import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; import { HasAnyLinkPipe } from 'libs/tech-shared/src/lib/pipe/has-any-link.pipe'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -48,6 +48,7 @@ describe('VorgangViewsMenuComponent', () => { const abgeschlossenView: string = getDataTestIdOf('vorgang-abgeschlossen-view'); const verworfenView: string = getDataTestIdOf('vorgang-verworfen-view'); const wiedervorlagenView: string = getDataTestIdOf('vorgang-wiedervorlagen-view'); + const ungeleseneNachrichtenView: string = getDataTestIdOf('vorgang-ungelesene-nachrichten-view'); const vorgangListView: string = getDataTestIdOf('vorgang-vorgang-list-view'); const searchView: string = getDataTestIdOf('vorgang-search-view'); @@ -62,6 +63,7 @@ describe('VorgangViewsMenuComponent', () => { MockComponent(VorgangViewItemComponent), MockComponent(VorgangSearchViewItemContainerComponent), MockComponent(OzgcloudIconComponent), + MockComponent(PostfachIconComponent), ], }).compileComponents(); @@ -215,6 +217,26 @@ describe('VorgangViewsMenuComponent', () => { }); }); + describe('ungelesene nachrichten view', () => { + it.each([ + ApiRootLinkRel.ALL_UNGELESENE_NACHRICHTEN, + ApiRootLinkRel.MY_UNGELESENE_NACHRICHTEN, + ApiRootLinkRel.UNASSIGNED_UNGELESENE_NACHRICHTEN, + ])('should show if %s link exists', (linkRel: string) => { + component.apiRootResource = createApiRootResource([linkRel]); + fixture.detectChanges(); + + existsAsHtmlElement(fixture, ungeleseneNachrichtenView); + }); + + it('should hide if link not exists', () => { + component.apiRootResource = createApiRootResource(); + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, ungeleseneNachrichtenView); + }); + }); + describe('vorgangList view', () => { it.each([ ApiRootLinkRel.ALLE_VORGAENGE, 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"], diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/FrontendEnvironment.java b/alfa-service/src/main/java/de/ozgcloud/alfa/Environment.java similarity index 97% rename from alfa-service/src/main/java/de/ozgcloud/alfa/FrontendEnvironment.java rename to alfa-service/src/main/java/de/ozgcloud/alfa/Environment.java index 218f2f1f4732c4bb0b856403f9fd0e8b9eafec73..d4506a9c0e64e2b842680a1c69d66fcd36cf8709 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/FrontendEnvironment.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/Environment.java @@ -30,7 +30,7 @@ import lombok.Getter; @Getter @Builder -public class FrontendEnvironment { +public class Environment { private boolean production; private String remoteHost; diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/EnvironmentController.java b/alfa-service/src/main/java/de/ozgcloud/alfa/EnvironmentController.java index 65f0ef8f07d25157d8fc52f73cc3852a13c2cd90..aa126fda712b2ed9ad962bbb745b0a4ee51233d4 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/EnvironmentController.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/EnvironmentController.java @@ -48,8 +48,8 @@ public class EnvironmentController { private VorgangProcessorProperties vorgangProcessorProperties; @GetMapping - public FrontendEnvironment getFrontendEnvironment() { - return FrontendEnvironment.builder() + public Environment getEnvironment() { + return Environment.builder() .production(productionProperties.isProduction()) .remoteHost(linkTo(RootController.class).toUri().toString()) .authServer(oAuth2Properties.getAuthServerUrl()) diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/RootViewLinkHandler.java b/alfa-service/src/main/java/de/ozgcloud/alfa/RootViewLinkHandler.java index e8d834618a56d3efd308efa231d6ca5c13cc13ef..b5d79fcc0ab64557b88236b0903d0aafc14e125f 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/RootViewLinkHandler.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/RootViewLinkHandler.java @@ -38,6 +38,10 @@ class RootViewLinkHandler { static final String SEARCH_MY_VORGEANGE_REL = "search_my"; static final String SEARCH_UNASSIGNED_VORGEANGE_REL = "search_unassigned"; + static final String ALL_UNGELESENE_NACHRICHTEN_REL = "vorgaenge_ungelesene_nachrichten_all"; + static final String MY_UNGELESENE_NACHRICHTEN_REL = "vorgaenge_ungelesene_nachrichten_my"; + static final String UNASSIGNED_UNGELESENE_NACHRICHTEN_REL = "vorgaenge_ungelesene_nachrichten_unassigned"; + static final int PAGE_SIZE = 100; @Autowired @@ -100,6 +104,8 @@ class RootViewLinkHandler { modelBuilder .addLink(buildGetAllByAssignedToAndHasNextWiedervorlageFristLink(UserId.empty(), UNASSIGNED_WIEDERVORLAGEN_REL)); userId.map(id -> buildGetAllByAssignedToAndHasNextWiedervorlageFristLink(id, MY_WIEDERVORLAGEN_REL)).ifPresent(modelBuilder::addLink); + + addGetByUngeleseneNachrichtenLinks(modelBuilder, userId); } Link buildGetAllUnassignedVorgaengeLink() { @@ -169,4 +175,22 @@ class RootViewLinkHandler { return linkTo(methodOn(VorgangController.class).getAllByAssignedToAndHasNextWiedervorlageFrist(0, PAGE_SIZE, userId, VorgangController.PARAM_NEXT_WIEDERVORLAGE_FRIST_EXISTS)).withRel(linkRel); } + + void addGetByUngeleseneNachrichtenLinks(ModelBuilder<Root> modelBuilder, Optional<UserId> userId) { + modelBuilder.addLink(buildGelAllByUngeleseneNachrichtenLink()); + modelBuilder.addLink(buildGetAllByAssignedToAndUngeleseneNachrichten(UserId.empty(), UNASSIGNED_UNGELESENE_NACHRICHTEN_REL)); + userId.map(id -> buildGetAllByAssignedToAndUngeleseneNachrichten(id, MY_UNGELESENE_NACHRICHTEN_REL)).ifPresent(modelBuilder::addLink); + } + + Link buildGelAllByUngeleseneNachrichtenLink() { + return linkTo(methodOn(VorgangController.class) + .getAllByUngeleseneNachrichten(0, PAGE_SIZE, VorgangController.PARAM_NACHRICHTEN_UNGELESENE)) + .withRel(ALL_UNGELESENE_NACHRICHTEN_REL); + } + + Link buildGetAllByAssignedToAndUngeleseneNachrichten(@NonNull UserId userId, String linkRel) { + return linkTo(methodOn(VorgangController.class) + .getAllByAssignedToAndUngeleseneNachrichten(0, PAGE_SIZE, userId, VorgangController.PARAM_NACHRICHTEN_UNGELESENE)) + .withRel(linkRel); + } } \ No newline at end of file diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/Statistic.java b/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/Statistic.java index 2a17cc875696000782390062587d6e91474db53f..855d2ef1c57c58cc69cebffe7fb37facf972a25f 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/Statistic.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/Statistic.java @@ -12,4 +12,5 @@ public class Statistic { private ByStatus byStatus; private int wiedervorlagen; private boolean existsWiedervorlageOverdue; + private int ungeleseneNachrichten; } diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticRemoteService.java b/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticRemoteService.java index cd508d6198827251fd4f661a7e0a4815570fa898..b39e47178187ac8a31b838d794bf7580f6748c67 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticRemoteService.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticRemoteService.java @@ -11,9 +11,9 @@ import org.springframework.stereotype.Service; import de.ozgcloud.alfa.AlfaProperties; import de.ozgcloud.alfa.common.GrpcUtil; import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus; +import de.ozgcloud.vorgang.common.GrpcQueryOperator; import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery; import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery.GroupMethod; -import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery.Operator; import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticRequest; import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticResponse; import de.ozgcloud.vorgang.statistic.StatisticServiceGrpc.StatisticServiceBlockingStub; @@ -25,9 +25,11 @@ class StatisticRemoteService { static final String COUNT_VORGANG_STATUS_RESULT_NAME_FORMAT = "countVorgangStatus_%s"; static final String COUNT_WIEDERVORLAGE_NEXT_FRIST_RESULT_NAME = "countWiedervorlage"; static final String EXISTS_WIEDERVORLAGE_OVERDUE_RESULT_NAME = "existsWiedervorlageOverdue"; + static final String COUNT_VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_RESULT_NAME = "countVorgaengeWithUngeleseneNachrichten"; static final String STATUS_PATH = "Vorgang.status"; static final String WIEDERVORLAGE_NEXT_FRIST_PATH_TEMPLATE = "ClientAttribute.%s.nextWiedervorlageFrist"; + static final String VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH = "ClientAttribute.OzgCloud_NachrichtenManager.hasNewPostfachNachricht"; static final String OPERAND_TODAY_DATE = "today()"; @@ -43,6 +45,7 @@ class StatisticRemoteService { .addAllQuery(buildCountByStatusQueries(countByVorgangStatus)) .addQuery(buildCountWiedervorlageNextFristQuery()) .addQuery(buildExistsWiedervorlageOverdueQuery()) + .addQuery(buildCountVorgaengeWithUngeleseneNachrichtenQuery()) .build(); var grpcResponse = statisticServiceStub.getVorgangStatistic(grpcRequest); @@ -59,7 +62,7 @@ class StatisticRemoteService { .setResultName(buildCountByStatusResultName(vorgangStatus)) .setPath(STATUS_PATH) .setGroupMethod(GroupMethod.COUNT) - .setOperator(Operator.EQUAL) + .setOperator(GrpcQueryOperator.EQUAL) .setOperandStringValue(vorgangStatus.name()) .build(); } @@ -69,7 +72,7 @@ class StatisticRemoteService { .setResultName(COUNT_WIEDERVORLAGE_NEXT_FRIST_RESULT_NAME) .setPath(String.format(WIEDERVORLAGE_NEXT_FRIST_PATH_TEMPLATE, alfaProperties.getApplicationName())) .setGroupMethod(GroupMethod.COUNT) - .setOperator(Operator.UNEQUAL) + .setOperator(GrpcQueryOperator.UNEQUAL) .build(); } @@ -78,7 +81,7 @@ class StatisticRemoteService { .setResultName(EXISTS_WIEDERVORLAGE_OVERDUE_RESULT_NAME) .setPath(String.format(WIEDERVORLAGE_NEXT_FRIST_PATH_TEMPLATE, alfaProperties.getApplicationName())) .setGroupMethod(GroupMethod.EXISTS) - .setOperator(Operator.LESS_THEN_OR_EQUAL_TO) + .setOperator(GrpcQueryOperator.LESS_THEN_OR_EQUAL_TO) .setOperandStringValue(OPERAND_TODAY_DATE) .build(); } @@ -93,4 +96,14 @@ class StatisticRemoteService { .map(mapper::toResult) .collect(Collectors.toMap(StatisticResult::getName, Function.identity())); } + + public GrpcVorgangStatisticQuery buildCountVorgaengeWithUngeleseneNachrichtenQuery() { + return GrpcVorgangStatisticQuery.newBuilder() + .setResultName(COUNT_VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_RESULT_NAME) + .setPath(VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH) + .setGroupMethod(GroupMethod.COUNT) + .setOperator(GrpcQueryOperator.EQUAL) + .setOperandBoolValue(true) + .build(); + } } \ No newline at end of file diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticService.java b/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticService.java index 68b9ab06c4d73f5b6810035b9b1312a6d3edbd2c..6b88ba78d635f291e3db330f661119f131ceb019 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticService.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/statistic/StatisticService.java @@ -48,6 +48,7 @@ class StatisticService { return Statistic.builder() .existsWiedervorlageOverdue(getBooleanResult(response, StatisticRemoteService.EXISTS_WIEDERVORLAGE_OVERDUE_RESULT_NAME)) .wiedervorlagen(getIntResult(response, StatisticRemoteService.COUNT_WIEDERVORLAGE_NEXT_FRIST_RESULT_NAME)) + .ungeleseneNachrichten(getIntResult(response, StatisticRemoteService.COUNT_VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_RESULT_NAME)) .byStatus(ByStatus.builder() .neu(getIntResult(response, remoteService.buildCountByStatusResultName(VorgangStatus.NEU))) .abgeschlossen(getIntResult(response, remoteService.buildCountByStatusResultName(VorgangStatus.ABGESCHLOSSEN))) diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/FilterCriteria.java b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/FilterCriteria.java index c80e8617af570fb48b34bf5bea4cd4070212630f..89fe664537bdb8c0f58eece1b848ce0a4e00b395 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/FilterCriteria.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/FilterCriteria.java @@ -22,4 +22,5 @@ class FilterCriteria { @Builder.Default private Optional<UserId> assignedTo = Optional.empty(); private boolean hasNextWiedervorlageFrist; + private boolean hasUngeleseneNachrichten; } diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangController.java b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangController.java index 35062413fb4a816eaf0263aa284d2bc5b32b4e6a..8d23095292dea0d30595fcdde1a13e3191e61d28 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangController.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangController.java @@ -25,8 +25,6 @@ package de.ozgcloud.alfa.vorgang; import java.util.Optional; -import jakarta.servlet.http.HttpServletResponse; - import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.hateoas.EntityModel; @@ -46,6 +44,7 @@ import de.ozgcloud.alfa.common.clientattribute.ClientAttributeService; import de.ozgcloud.alfa.common.user.UserId; import de.ozgcloud.alfa.statistic.StatisticController; import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus; +import jakarta.servlet.http.HttpServletResponse; @RestController @RequestMapping(VorgangController.PATH) @@ -58,8 +57,10 @@ public class VorgangController { static final String PARAM_ASSIGNED_TO = "assignedTo"; static final String PARAM_STATUS = "status"; static final String PARAM_NEXT_WIEDERVORLAGE_FRIST = "nextFrist"; + static final String PARAM_NACHRICHTEN = "nachrichten"; public static final String PARAM_NEXT_WIEDERVORLAGE_FRIST_EXISTS = "exists"; + public static final String PARAM_NACHRICHTEN_UNGELESENE = "ungelesene"; @Autowired private VorgangService vorgangService; @@ -189,4 +190,27 @@ public class VorgangController { clientAttributeService.resetPostfachNachricht(vorgangId); response.setStatus(HttpStatus.NO_CONTENT.value()); } + + @GetMapping(params = { PARAM_PAGE, PARAM_LIMIT, PARAM_NACHRICHTEN }) + public RepresentationModel<EntityModel<EnhancedVorgang>> getAllByUngeleseneNachrichten(@RequestParam int page, @RequestParam Integer limit, + @RequestParam String nachrichten) { + var requestCriteria = FindVorgaengeHeaderRequestCriteria.builder().page(page).limit(limit) + .filterCriteria(FilterCriteria.builder().hasUngeleseneNachrichten(PARAM_NACHRICHTEN_UNGELESENE.equals(nachrichten)).build()) + .build(); + + return handleGetAllRequest(requestCriteria); + } + + @GetMapping(params = { PARAM_PAGE, PARAM_LIMIT, PARAM_ASSIGNED_TO, PARAM_NACHRICHTEN }) + public RepresentationModel<EntityModel<EnhancedVorgang>> getAllByAssignedToAndUngeleseneNachrichten(@RequestParam int page, + @RequestParam Integer limit, @RequestParam UserId assignedTo, @RequestParam String nachrichten) { + var requestCriteria = FindVorgaengeHeaderRequestCriteria.builder().page(page).limit(limit) + .filterCriteria(FilterCriteria.builder() + .filterByAssignedTo(true).assignedTo(asOptional(assignedTo)) + .hasUngeleseneNachrichten(PARAM_NACHRICHTEN_UNGELESENE.equals(nachrichten)) + .build()) + .build(); + + return handleGetAllRequest(requestCriteria); + } } \ No newline at end of file diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangRemoteService.java b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangRemoteService.java index bb2d49e67b4e7c57dac52b54c1aa27d329fd9525..a6d44d0c43309ab1f751b909d66d7a2483b5e492 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangRemoteService.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangRemoteService.java @@ -29,18 +29,23 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import de.ozgcloud.alfa.common.GrpcUtil; +import de.ozgcloud.vorgang.common.GrpcQueryOperator; import de.ozgcloud.vorgang.vorgang.GrpcFilterBy; import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangRequest; import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangRequest.GrpcOrderBy; import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangResponse; import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangWithEingangRequest; import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangWithEingangResponse; +import de.ozgcloud.vorgang.vorgang.GrpcQuery; +import de.ozgcloud.vorgang.vorgang.GrpcVorgangQueryExpression; import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub; import net.devh.boot.grpc.client.inject.GrpcClient; @Service class VorgangRemoteService { + static final String VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH = "ClientAttribute.OzgCloud_NachrichtenManager.hasNewPostfachNachricht"; + @GrpcClient(GrpcUtil.VORGANG_MANAGER_GRPC_CLIENT) private VorgangServiceBlockingStub vorgangServiceStub; @Autowired @@ -70,7 +75,24 @@ class VorgangRemoteService { .setOrderBy(GrpcOrderBy.valueOf(requestCriteria.getOrderBy().name())) .setLimit(requestCriteria.getLimit()) .setOffset(requestCriteria.getPage() * requestCriteria.getLimit()) - .setFilterBy(mapFilterCriteria(filterCriteria)); + .setQuery(createQuery(filterCriteria)) + .setFilterBy(createFilterBy(filterCriteria)); + } + + GrpcQuery createQuery(FilterCriteria filterCriteria) { + var queryBuilder = GrpcQuery.newBuilder(); + if (filterCriteria.isHasUngeleseneNachrichten()) { + addUngeleseneNachrichtenExpression(queryBuilder); + } + return queryBuilder.build(); + } + + private void addUngeleseneNachrichtenExpression(GrpcQuery.Builder queryBuilder) { + queryBuilder.addExpressions(GrpcVorgangQueryExpression.newBuilder() + .setPath(VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH) + .setOperator(GrpcQueryOperator.EQUAL) + .setOperandBoolValue(true) + .build()); } VorgaengeHeaderResponse buildVorgaengeHeaderResponse(GrpcFindVorgangResponse response) { @@ -90,10 +112,10 @@ class VorgangRemoteService { } GrpcFindVorgangWithEingangRequest buildFindVorgangWithEingangRequest(String vorgangId, FilterCriteria filterCriteria) { - return GrpcFindVorgangWithEingangRequest.newBuilder().setId(vorgangId).setFilterBy(mapFilterCriteria(filterCriteria)).build(); + return GrpcFindVorgangWithEingangRequest.newBuilder().setId(vorgangId).setFilterBy(createFilterBy(filterCriteria)).build(); } - GrpcFilterBy mapFilterCriteria(FilterCriteria filterCriteria) { + GrpcFilterBy createFilterBy(FilterCriteria filterCriteria) { var filterCriteriaBuilder = GrpcFilterBy.newBuilder() .setFilterByAssignedTo(filterCriteria.isFilterByAssignedTo()) .setFilterByOrganisationseinheitenId(filterCriteria.isFilterByOrganisationseinheitenId()) diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/EnvironmentControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/EnvironmentControllerTest.java index 154de97e2243536056b9502ea6eac01d37cc2306..f8338cd99ed64bb6f6aeb63b798165c7671d1507 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/EnvironmentControllerTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/EnvironmentControllerTest.java @@ -62,9 +62,9 @@ class EnvironmentControllerTest { mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); } - @DisplayName("Get frontend environment") + @DisplayName("Get environment") @Nested - class TestGetFrontendEnvironment { + class TestGetEnvironment { private static final String CLIENT = LoremIpsum.getInstance().getFirstName() + "Client"; private static final boolean PRODUCTION = true; diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/RootViewLinkHandlerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/RootViewLinkHandlerTest.java index 64f4aadcf97daf229570e1affc1273dc9423da7a..84733b060eff9e273ab5bb84f97ccd00588bf73e 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/RootViewLinkHandlerTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/RootViewLinkHandlerTest.java @@ -6,6 +6,7 @@ import static org.mockito.Mockito.*; import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -18,6 +19,8 @@ import org.mockito.Spy; import org.springframework.hateoas.Link; import org.springframework.hateoas.LinkRelation; +import com.thedeanda.lorem.LoremIpsum; + import de.ozgcloud.alfa.common.ModelBuilder; import de.ozgcloud.alfa.common.user.CurrentUserService; import de.ozgcloud.alfa.common.user.UserId; @@ -282,6 +285,13 @@ class RootViewLinkHandlerTest { .get().extracting(Link::getHref).isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=&nextFrist=exists"); } } + + @Test + void shouldAddLinksForUngeleseneNachrichten() { + viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID)); + + verify(viewLinkHandler).addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID)); + } } @DisplayName("search all vorgaenge") @@ -318,7 +328,7 @@ class RootViewLinkHandlerTest { void shouldBeAddedIfUserIsPresent() { var link = viewLinkHandler.buildMyVorgaengeLink(UserProfileTestFactory.ID); - assertThat(link.getHref()).isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=" + UserProfileTestFactory.ID.toString()); + assertThat(link.getHref()).isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=" + UserProfileTestFactory.ID); } } @@ -504,6 +514,176 @@ class RootViewLinkHandlerTest { } } + @Nested + class TestBuildGelAllByUngeleseneNachrichtenLink { + + @Test + void shouldHaveLinkHref() { + var link = viewLinkHandler.buildGelAllByUngeleseneNachrichtenLink(); + + assertThat(link) + .extracting(Link::getHref) + .isEqualTo("/api/vorgangs?page=0&limit=100&nachrichten=ungelesene"); + } + + @Test + void shouldHaveLinkRel() { + var link = viewLinkHandler.buildGelAllByUngeleseneNachrichtenLink(); + + assertThat(link) + .extracting(Link::getRel) + .extracting(LinkRelation::value) + .isEqualTo(RootViewLinkHandler.ALL_UNGELESENE_NACHRICHTEN_REL); + } + } + + @Nested + class TestBuildGetAllByAssignedToAndUngeleseneNachrichten { + + @Nested + class AssignTo { + + @Test + void shouldHaveLink() { + var link = viewLinkHandler.buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID, + RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL); + + assertThat(link) + .extracting(Link::getHref) + .isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=" + UserProfileTestFactory.ID + "&nachrichten=ungelesene"); + } + + @Test + void shouldHaveLinkRel() { + var link = viewLinkHandler.buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID, + RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL); + + assertThat(link) + .extracting(Link::getRel) + .extracting(LinkRelation::value) + .isEqualTo(RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL); + } + } + + @Nested + class Unassigned { + + @Test + void shouldHaveLink() { + var link = viewLinkHandler.buildGetAllByAssignedToAndUngeleseneNachrichten(UserId.empty(), + RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL); + + assertThat(link) + .extracting(Link::getHref) + .isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=&nachrichten=ungelesene"); + } + + @Test + void shouldHaveLinkRel() { + var link = viewLinkHandler.buildGetAllByAssignedToAndUngeleseneNachrichten(UserId.empty(), + RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL); + + assertThat(link) + .extracting(Link::getRel) + .extracting(LinkRelation::value) + .isEqualTo(RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL); + } + + } + + } + + @Nested + class TestAddGetByUngeleseneNachrichtenLinks { + + @Mock + private Root rootResource; + private final ModelBuilder<Root> modelBuilder = ModelBuilder.fromEntity(rootResource); + private final Link linkAllUngeleseneNachrichten = Link.of(LoremIpsum.getInstance().getUrl()); + private final Link linkMyUngeleseneNachrichten = Link.of(LoremIpsum.getInstance().getUrl()); + private final Link linkUnassignedUngeleseneNachrichten = Link.of(LoremIpsum.getInstance().getUrl()); + + @BeforeEach + void setUp() { + doReturn(linkAllUngeleseneNachrichten).when(viewLinkHandler).buildGelAllByUngeleseneNachrichtenLink(); + doReturn(linkUnassignedUngeleseneNachrichten).when(viewLinkHandler) + .buildGetAllByAssignedToAndUngeleseneNachrichten(UserId.empty(), RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL); + } + + @Test + void shouldBuildLinkForUngeleseneNachrichten() { + viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID)); + + verify(viewLinkHandler).buildGelAllByUngeleseneNachrichtenLink(); + } + + @Test + void shouldAddLinkForUngeleseneNachrichten() { + var modelBuilder = ModelBuilder.fromEntity(rootResource); + + viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID)); + + assertThat(modelBuilder.buildModel().getLinks()).contains(linkAllUngeleseneNachrichten); + } + + @Test + void shouldBuildLinkForUnassignedUngeleseneNachrichten() { + viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.empty()); + + verify(viewLinkHandler).buildGetAllByAssignedToAndUngeleseneNachrichten(UserId.empty(), + RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL); + } + + @Test + void shouldAddLinkForUnassignedUngeleseneNachrichten() { + var modelBuilder = ModelBuilder.fromEntity(rootResource); + + viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.empty()); + + assertThat(modelBuilder.buildModel().getLinks()).contains(linkUnassignedUngeleseneNachrichten); + } + + @Nested + class UsedIdExists { + + @BeforeEach + void setUp() { + doReturn(linkMyUngeleseneNachrichten).when(viewLinkHandler).buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID, + RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL); + } + + @Test + void shouldBuildLinkForMyUngeleseneNachrichten() { + viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID)); + + verify(viewLinkHandler).buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID, + RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL); + } + + @Test + void shouldAddLinkForMyUngeleseneNachrichten() { + var modelBuilder = ModelBuilder.fromEntity(rootResource); + + viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID)); + + assertThat(modelBuilder.buildModel().getLinks()).contains(linkMyUngeleseneNachrichten); + } + } + + @Nested + class UserIdEmpty { + + @Test + void shouldNotBuildLinkForMyUngeleseneNachrichten() { + viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.empty()); + + verify(viewLinkHandler, never()).buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID, + RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL); + } + } + + } + // @DisplayName("Test user assistance documentation link") // @Nested // class TestDocumentationLink { diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/GrpcVorgangStatisticQueryTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/GrpcVorgangStatisticQueryTestFactory.java index 0d26d330dc055948cec844b3cfd851f4adf72fd5..517f2f4495241c63259375ad45e7e6389b120f67 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/GrpcVorgangStatisticQueryTestFactory.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/GrpcVorgangStatisticQueryTestFactory.java @@ -1,14 +1,19 @@ package de.ozgcloud.alfa.statistic; +import com.thedeanda.lorem.LoremIpsum; + import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery; public class GrpcVorgangStatisticQueryTestFactory { + public static final String RESULT_NAME = LoremIpsum.getInstance().getWords(1); + public static GrpcVorgangStatisticQuery create() { return createBuilder().build(); } public static GrpcVorgangStatisticQuery.Builder createBuilder() { - return GrpcVorgangStatisticQuery.newBuilder(); + return GrpcVorgangStatisticQuery.newBuilder() + .setResultName(RESULT_NAME); } } diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticRemoteServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticRemoteServiceTest.java index 5716d65c2197741fbf8d03e498f3b283e398cc17..8306173ae997b9ade430cb8dfe93a2a4749b531f 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticRemoteServiceTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticRemoteServiceTest.java @@ -15,6 +15,8 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.EnumSource.Mode; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; @@ -23,9 +25,10 @@ import com.thedeanda.lorem.LoremIpsum; import de.ozgcloud.alfa.AlfaProperties; import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus; +import de.ozgcloud.vorgang.common.GrpcQueryOperator; import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery; import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery.GroupMethod; -import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticQuery.Operator; +import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticRequest; import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticResponse; import de.ozgcloud.vorgang.statistic.GrpcVorgangStatisticResult; import de.ozgcloud.vorgang.statistic.StatisticServiceGrpc.StatisticServiceBlockingStub; @@ -79,7 +82,7 @@ class StatisticRemoteServiceTest { void shouldContainOperator(VorgangStatus vorgangStatus) { var query = service.buildCountByVorgangStatusQuery(vorgangStatus); - assertThat(query.getOperator()).isEqualTo(Operator.EQUAL); + assertThat(query.getOperator()).isEqualTo(GrpcQueryOperator.EQUAL); } @ParameterizedTest @@ -126,7 +129,7 @@ class StatisticRemoteServiceTest { .contains( COUNT_WIEDERVORLAGE_NEXT_FRIST_RESULT_NAME, String.format(StatisticRemoteService.WIEDERVORLAGE_NEXT_FRIST_PATH_TEMPLATE, applicationName), - Operator.UNEQUAL, + GrpcQueryOperator.UNEQUAL, GroupMethod.COUNT ); } @@ -167,7 +170,7 @@ class StatisticRemoteServiceTest { void shouldContainOperator() { var query = service.buildExistsWiedervorlageOverdueQuery(); - assertThat(query.getOperator()).isEqualTo(Operator.LESS_THEN_OR_EQUAL_TO); + assertThat(query.getOperator()).isEqualTo(GrpcQueryOperator.LESS_THEN_OR_EQUAL_TO); } @Test @@ -190,12 +193,20 @@ class StatisticRemoteServiceTest { class TestGetVorgaengeStatistics { private final GrpcVorgangStatisticResponse response = GrpcVorgangStatisticResponseTestFactory.create(); + private final GrpcVorgangStatisticQuery countVorgaengeWithUngeleseneNachrichtenQuery = GrpcVorgangStatisticQueryTestFactory.createBuilder() + .setResultName("ungelesene nachrichten").build(); + private final GrpcVorgangStatisticQuery existsWiedervorlageOverdueQuery = GrpcVorgangStatisticQueryTestFactory.createBuilder() + .setResultName("exists overdue").build(); + + @Captor + private ArgumentCaptor<GrpcVorgangStatisticRequest> grpcRequestCaptor; @BeforeEach void beforeEach() { when(serviceStub.getVorgangStatistic(any())).thenReturn(response); - doReturn(GrpcVorgangStatisticQueryTestFactory.create()).when(service).buildExistsWiedervorlageOverdueQuery(); + doReturn(existsWiedervorlageOverdueQuery).when(service).buildExistsWiedervorlageOverdueQuery(); + doReturn(countVorgaengeWithUngeleseneNachrichtenQuery).when(service).buildCountVorgaengeWithUngeleseneNachrichtenQuery(); } @Test @@ -232,6 +243,21 @@ class StatisticRemoteServiceTest { verify(service).buildStatisticResult(response); } + + @Test + void shouldCallBuildCountVorgaengeWithUngeleseneNachrichtenQuery() { + service.getVorgaengeStatistics(STATUSES_TO_COUNT); + + verify(service).buildCountVorgaengeWithUngeleseneNachrichtenQuery(); + } + + @Test + void shouldAddCountVorgaengeWithUngeleseneNachrichtenQuery() { + service.getVorgaengeStatistics(STATUSES_TO_COUNT); + + verify(serviceStub).getVorgangStatistic(grpcRequestCaptor.capture()); + assertThat(grpcRequestCaptor.getValue().getQueryList()).contains(countVorgaengeWithUngeleseneNachrichtenQuery); + } } @Nested @@ -270,4 +296,47 @@ class StatisticRemoteServiceTest { .hasEntrySatisfying(RESULT_NAME, statisticResult -> assertThat(statisticResult.getIntValue()).isEqualTo(RESULT_INT)); } } + + @Nested + class TestBuildCountVorgaengeWithUngeleseneNachrichtenQuery { + + @Test + void shouldHaveResultName() { + var query = callService(); + + assertThat(query.getResultName()).isEqualTo(COUNT_VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_RESULT_NAME); + } + + @Test + void shouldHavePath() { + var query = callService(); + + assertThat(query.getPath()).isEqualTo(VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH); + } + + @Test + void shouldHaveGroupingMethod() { + var query = callService(); + + assertThat(query.getGroupMethod()).isEqualTo(GroupMethod.COUNT); + } + + @Test + void shouldHaveOperator() { + var query = callService(); + + assertThat(query.getOperator()).isEqualTo(GrpcQueryOperator.EQUAL); + } + + @Test + void shouldHaveOperandValue() { + var query = callService(); + + assertThat(query.getOperandBoolValue()).isTrue(); + } + + private GrpcVorgangStatisticQuery callService() { + return service.buildCountVorgaengeWithUngeleseneNachrichtenQuery(); + } + } } \ No newline at end of file diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticServiceTest.java index 1b030d675d4eec8e8cee9f8c2bcb0f3f83e339e1..e35e1de7fecbdcfeae02ca7e75064d40e354546d 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticServiceTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticServiceTest.java @@ -138,6 +138,14 @@ class StatisticServiceTest { assertThat(statistic.getByStatus().getNeu()).isZero(); } + + @Test + void shouldContainUngeleseneNachrichten() { + var statistic = service.buildGetVorgaengeStatisticResult( + Map.of(COUNT_VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_RESULT_NAME, StatisticResultTestFactory.create())); + + assertThat(statistic.getUngeleseneNachrichten()).isEqualTo(StatisticResultTestFactory.INT_VALUE); + } } @Nested diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticTestFactory.java index d4acbda72b80abdb119b6e736812291208ae0411..5808eb9355941f76f27cf1e036c4eabd9fc410ec 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticTestFactory.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/statistic/StatisticTestFactory.java @@ -4,6 +4,7 @@ public class StatisticTestFactory { public static final int COUNT_WIEDERVORLAGEN = 8; public static final boolean EXISTS_WIEDERVORLAGE_OVERDUE = true; + public static final int COUNT_UNGELESENE_NACHRICHTEN = 5; public static Statistic create() { return createBuilder().build(); @@ -13,6 +14,7 @@ public class StatisticTestFactory { return Statistic.builder() .byStatus(ByStatusTestFactory.create()) .wiedervorlagen(COUNT_WIEDERVORLAGEN) - .existsWiedervorlageOverdue(EXISTS_WIEDERVORLAGE_OVERDUE); + .existsWiedervorlageOverdue(EXISTS_WIEDERVORLAGE_OVERDUE) + .ungeleseneNachrichten(COUNT_UNGELESENE_NACHRICHTEN); } } diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/FilterCriteriaTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/FilterCriteriaTestFactory.java index a4572dc1eaf28498d41b9aa0da67f8a935ea837b..a6fd2febaf7e1c665f9fbee464ba4d0c48f45f68 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/FilterCriteriaTestFactory.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/FilterCriteriaTestFactory.java @@ -10,11 +10,10 @@ public class FilterCriteriaTestFactory { public static final boolean FILTER_BY_ORGANISATIONS_EINHEITEN_ID = true; public static final boolean FILTER_BY_ASSIGNED_TO = true; - public static final VorgangStatus VORGANG_STATUS = VorgangStatus.NEU; public static final String ORGANISATIONS_EINHEIT_ID = ZustaendigeStelleTestFactory.ORGANISATIONSEINHEITEN_ID; - public static final boolean HAS_NEXT_WIEDERVORLAGE_FRIST = false; + public static final boolean HAS_UNGELESENE_NACHRICHTEN = false; public static FilterCriteria create() { return createBuilder().build(); @@ -27,6 +26,7 @@ public class FilterCriteriaTestFactory { .filterByAssignedTo(FILTER_BY_ASSIGNED_TO) .assignedTo(Optional.of(UserProfileTestFactory.ID)) .organisationsEinheitenId(List.of(ORGANISATIONS_EINHEIT_ID)) - .hasNextWiedervorlageFrist(HAS_NEXT_WIEDERVORLAGE_FRIST); + .hasNextWiedervorlageFrist(HAS_NEXT_WIEDERVORLAGE_FRIST) + .hasUngeleseneNachrichten(HAS_UNGELESENE_NACHRICHTEN); } } diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/GrpcQueryTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/GrpcQueryTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..33c4fe7c36a9af6b5a85423c00b649af863ab468 --- /dev/null +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/GrpcQueryTestFactory.java @@ -0,0 +1,14 @@ +package de.ozgcloud.alfa.vorgang; + +import de.ozgcloud.vorgang.vorgang.GrpcQuery; + +public class GrpcQueryTestFactory { + + public static GrpcQuery create() { + return createBuilder().build(); + } + + public static GrpcQuery.Builder createBuilder() { + return GrpcQuery.newBuilder(); + } +} diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java index 8eea6215c5ed51e9cd4d184c627a70ba5ee5a55a..c93835bcb0da848cf565cdedfc35ee677880ce3a 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java @@ -142,42 +142,42 @@ class VorgangControllerITCase { private static final String BY_STATUS_PATH = "$.statistic.byStatus."; @Test - void shouldContainsNeu() throws Exception { + void shouldContainNeu() throws Exception { var response = doRequest(); response.andExpect(jsonPath(BY_STATUS_PATH + "neu").value(ByStatusTestFactory.NEU_COUNT)); } @Test - void shouldContainsAngenommen() throws Exception { + void shouldContainAngenommen() throws Exception { var response = doRequest(); response.andExpect(jsonPath(BY_STATUS_PATH + "angenommen").value(ByStatusTestFactory.ANGENOMMEN_COUNT)); } @Test - void shouldContainsInBearbeitung() throws Exception { + void shouldContainInBearbeitung() throws Exception { var response = doRequest(); response.andExpect(jsonPath(BY_STATUS_PATH + "inBearbeitung").value(ByStatusTestFactory.IN_BEARBEITUNG_COUNT)); } @Test - void shouldContainsBeschieden() throws Exception { + void shouldContainBeschieden() throws Exception { var response = doRequest(); response.andExpect(jsonPath(BY_STATUS_PATH + "beschieden").value(ByStatusTestFactory.BESCHIEDEN_COUNT)); } @Test - void shouldContainsAbgeschlossen() throws Exception { + void shouldContainAbgeschlossen() throws Exception { var response = doRequest(); response.andExpect(jsonPath(BY_STATUS_PATH + "abgeschlossen").value(ByStatusTestFactory.ABGESCHLOSSEN_COUNT)); } @Test - void shouldContainsVerworfen() throws Exception { + void shouldContainVerworfen() throws Exception { var response = doRequest(); response.andExpect(jsonPath(BY_STATUS_PATH + "verworfen").value(ByStatusTestFactory.VERWORFEN_COUNT)); @@ -185,11 +185,18 @@ class VorgangControllerITCase { } @Test - void shouldContainsWiedervorlagen() throws Exception { + void shouldContainWiedervorlagen() throws Exception { var response = doRequest(); response.andExpect(jsonPath("$.statistic.wiedervorlagen").value(StatisticTestFactory.COUNT_WIEDERVORLAGEN)); } + + @Test + void shouldContainUngeleseneNachrichten() throws Exception { + var response = doRequest(); + + response.andExpect(jsonPath("$.statistic.ungeleseneNachrichten").value(StatisticTestFactory.COUNT_UNGELESENE_NACHRICHTEN)); + } } } diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerTest.java index eb68a2d7b8716df1ac05a12ae42ffc6b34e89600..4c237346f037043fb98cf7c8c49a3a72b8e65bfd 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerTest.java @@ -30,10 +30,15 @@ import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import java.util.List; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.InjectMocks; @@ -606,6 +611,163 @@ class VorgangControllerTest { } } } + + @Nested + class TestGetAllByUngeleseneNachrichten { + + @ParameterizedTest + @MethodSource("nachrichtenValues") + void shouldCallHandleGetAllRequest(String nachrichtenValue) { + doRequestWithNachrichtenParam(nachrichtenValue); + + verify(controller).handleGetAllRequest(any(FindVorgaengeHeaderRequestCriteria.class)); + } + + @ParameterizedTest + @MethodSource("nachrichtenValues") + void shouldCriteriaHavePage(String nachrichtenValue) { + doRequestWithNachrichtenParam(nachrichtenValue); + + verify(controller).handleGetAllRequest(criteriaCaptor.capture()); + assertThat(criteriaCaptor.getValue().getPage()).isEqualTo(PAGE); + } + + @ParameterizedTest + @MethodSource("nachrichtenValues") + void shouldCriteriaHaveLimit(String nachrichtenValue) { + doRequestWithNachrichtenParam(nachrichtenValue); + + verify(controller).handleGetAllRequest(criteriaCaptor.capture()); + assertThat(criteriaCaptor.getValue().getLimit()).isEqualTo(LIMIT); + } + + static List<String> nachrichtenValues() { + return List.of(VorgangController.PARAM_NACHRICHTEN_UNGELESENE, "", "dummy"); + } + + @Nested + class WithParamNachrichtenUngelesene { + + @Test + void shouldCriteriaHaveHasUngeleseneNachrichtenTrue() { + doRequestWithNachrichtenParam(VorgangController.PARAM_NACHRICHTEN_UNGELESENE); + + verify(controller).handleGetAllRequest(criteriaCaptor.capture()); + assertThat(criteriaCaptor.getValue().getFilterCriteria().isHasUngeleseneNachrichten()).isTrue(); + } + } + + @Nested + class WithoutParamNachrichtenUngelesene { + + @ParameterizedTest + @ValueSource(strings = {"", "dummy"}) + void shouldCriteriaHaveHasUngeleseneNachrichtenFalse(String nachrichtenValue) { + doRequestWithNachrichtenParam(nachrichtenValue); + + verify(controller).handleGetAllRequest(criteriaCaptor.capture()); + assertThat(criteriaCaptor.getValue().getFilterCriteria().isHasUngeleseneNachrichten()).isFalse(); + } + } + + @SneakyThrows + private void doRequestWithNachrichtenParam(String paramValue) { + mockMvc.perform(get(PATH) + .param(VorgangController.PARAM_PAGE, Integer.toString(PAGE)) + .param(VorgangController.PARAM_LIMIT, Integer.toString(LIMIT)) + .param(VorgangController.PARAM_NACHRICHTEN, paramValue)) + .andExpect(status().isOk()); + } + } + + @Nested + class TestGetAllByAssignedToAndUngeleseneNachrichten { + + private static final UserId ASSIGNED_TO = UserProfileTestFactory.ID; + + @ParameterizedTest + @MethodSource("nachrichtenValues") + void shouldCallHandleGetAllRequest(String nachrichtenValue) { + doRequestWithNachrichtenParam(nachrichtenValue); + + verify(controller).handleGetAllRequest(any(FindVorgaengeHeaderRequestCriteria.class)); + } + + @ParameterizedTest + @MethodSource("nachrichtenValues") + void shouldCriteriaHavePage(String nachrichtenValue) { + doRequestWithNachrichtenParam(nachrichtenValue); + + verify(controller).handleGetAllRequest(criteriaCaptor.capture()); + assertThat(criteriaCaptor.getValue().getPage()).isEqualTo(PAGE); + } + + @ParameterizedTest + @MethodSource("nachrichtenValues") + void shouldCriteriaHaveLimit(String nachrichtenValue) { + doRequestWithNachrichtenParam(nachrichtenValue); + + verify(controller).handleGetAllRequest(criteriaCaptor.capture()); + assertThat(criteriaCaptor.getValue().getLimit()).isEqualTo(LIMIT); + } + + @ParameterizedTest + @MethodSource("nachrichtenValues") + void shouldCriteriaHaveAssignedTo(String nachrichtenValue) { + doRequestWithNachrichtenParam(nachrichtenValue); + + verify(controller).handleGetAllRequest(criteriaCaptor.capture()); + assertThat(criteriaCaptor.getValue().getFilterCriteria().getAssignedTo()).hasValue(ASSIGNED_TO); + } + + @ParameterizedTest + @MethodSource("nachrichtenValues") + void shouldSetFilterByAssignedTo(String nachrichtenValue) { + doRequestWithNachrichtenParam(nachrichtenValue); + + verify(controller).handleGetAllRequest(criteriaCaptor.capture()); + assertThat(criteriaCaptor.getValue().getFilterCriteria().isFilterByAssignedTo()).isTrue(); + } + + static List<String> nachrichtenValues() { + return List.of(VorgangController.PARAM_NACHRICHTEN_UNGELESENE, "", "dummy"); + } + + @Nested + class WithParamNachrichtenUngelesene { + + @Test + void shouldCriteriaHaveHasUngeleseneNachrichtenTrue() { + doRequestWithNachrichtenParam(VorgangController.PARAM_NACHRICHTEN_UNGELESENE); + + verify(controller).handleGetAllRequest(criteriaCaptor.capture()); + assertThat(criteriaCaptor.getValue().getFilterCriteria().isHasUngeleseneNachrichten()).isTrue(); + } + } + + @Nested + class WithoutParamNachrichtenUngelesene { + + @ParameterizedTest + @ValueSource(strings = {"", "dummy"}) + void shouldCriteriaHaveHasUngeleseneNachrichtenFalse(String nachrichtenValue) { + doRequestWithNachrichtenParam(nachrichtenValue); + + verify(controller).handleGetAllRequest(criteriaCaptor.capture()); + assertThat(criteriaCaptor.getValue().getFilterCriteria().isHasUngeleseneNachrichten()).isFalse(); + } + } + + @SneakyThrows + private void doRequestWithNachrichtenParam(String paramValue) { + mockMvc.perform(get(PATH) + .param(VorgangController.PARAM_PAGE, Integer.toString(PAGE)) + .param(VorgangController.PARAM_LIMIT, Integer.toString(LIMIT)) + .param(VorgangController.PARAM_ASSIGNED_TO, ASSIGNED_TO.toString()) + .param(VorgangController.PARAM_NACHRICHTEN, paramValue)) + .andExpect(status().isOk()); + } + } } @DisplayName("As Optional") diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangRemoteServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangRemoteServiceTest.java index c2c4eb8db070a11c9fecdc60473d9325d3e77745..be66261c6e40450b44a08d50d9f325ce6b2df18a 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangRemoteServiceTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangRemoteServiceTest.java @@ -23,6 +23,7 @@ */ package de.ozgcloud.alfa.vorgang; +import static de.ozgcloud.alfa.vorgang.VorgangRemoteService.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @@ -39,9 +40,12 @@ import org.mockito.Mock; import org.mockito.Spy; import de.ozgcloud.alfa.common.user.UserProfileTestFactory; +import de.ozgcloud.vorgang.common.GrpcQueryOperator; import de.ozgcloud.vorgang.vorgang.GrpcFilterBy; import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangRequest; import de.ozgcloud.vorgang.vorgang.GrpcFindVorgangResponse; +import de.ozgcloud.vorgang.vorgang.GrpcQuery; +import de.ozgcloud.vorgang.vorgang.GrpcVorgangQueryExpression; import de.ozgcloud.vorgang.vorgang.VorgangServiceGrpc.VorgangServiceBlockingStub; class VorgangRemoteServiceTest { @@ -59,6 +63,8 @@ class VorgangRemoteServiceTest { private final GrpcFilterBy filterBy = GrpcFilterByTestFactory.create(); + private final GrpcQuery query = GrpcQueryTestFactory.create(); + @DisplayName("Find vorgaenge header") @Nested class TestFindVorgaengeHeader { @@ -73,7 +79,8 @@ class VorgangRemoteServiceTest { @BeforeEach void initMockReturnValues() { - doReturn(filterBy).when(service).mapFilterCriteria(any()); + doReturn(query).when(service).createQuery(any()); + doReturn(filterBy).when(service).createFilterBy(any()); doReturn(VorgangListResponseTestFactory.create()).when(service).buildVorgaengeHeaderResponse(any()); } @@ -84,11 +91,18 @@ class VorgangRemoteServiceTest { verify(service).buildFindVorgangRequest(requestCriteria, filterCriteria); } + @Test + void callCreateQuery() { + callService(); + + verify(service).createQuery(filterCriteria); + } + @Test void callCreateFilterBy() { callService(); - verify(service).mapFilterCriteria(filterCriteria); + verify(service).createFilterBy(filterCriteria); } @Test @@ -109,7 +123,8 @@ class VorgangRemoteServiceTest { @BeforeEach void initMockReturnValues() { - doReturn(filterBy).when(service).mapFilterCriteria(any()); + doReturn(query).when(service).createQuery(any()); + doReturn(filterBy).when(service).createFilterBy(any()); } @Test @@ -127,6 +142,13 @@ class VorgangRemoteServiceTest { .isEqualTo(FindVorgaengeRequestCriteriaTestFactory.PAGE * FindVorgaengeRequestCriteriaTestFactory.LIMIT); } + @Test + void shouldSetQuery() { + var request = callService(); + + assertThat(request.getQuery()).isEqualTo(query); + } + @Test void shouldSetFilterBy() { var request = callService(); @@ -186,13 +208,64 @@ class VorgangRemoteServiceTest { } } + @Nested + class TestCreateQuery { + + @Nested + class WhenHasUngeleseneNachrichtenIsTrue { + + private final FilterCriteria filterCriteria = FilterCriteriaTestFactory.createBuilder().hasUngeleseneNachrichten(true).build(); + + @Test + void shouldAddExpression() { + var query = service.createQuery(filterCriteria); + + assertThat(query.getExpressionsList()).extracting(GrpcVorgangQueryExpression::getPath) + .containsOnlyOnce(VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH); + } + + @Test + void shouldHaveOperator() { + var expression = getExpression(service.createQuery(filterCriteria)); + + assertThat(expression.getOperator()).isEqualTo(GrpcQueryOperator.EQUAL); + } + + @Test + void shouldHaveOperandBoolValue() { + var expression = getExpression(service.createQuery(filterCriteria)); + + assertThat(expression.getOperandBoolValue()).isTrue(); + } + + private GrpcVorgangQueryExpression getExpression(GrpcQuery query) { + return query.getExpressionsList().stream() + .filter(expression -> expression.getPath().equals(VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH)).findFirst().orElseThrow(); + } + } + + @Nested + class WhenHasUngeleseneNachrichtenIsFalse { + + private final FilterCriteria filterCriteria = FilterCriteriaTestFactory.createBuilder().hasUngeleseneNachrichten(false).build(); + + @Test + void shouldNotAddExpression() { + var query = service.createQuery(filterCriteria); + + assertThat(query.getExpressionsList()).extracting(GrpcVorgangQueryExpression::getPath) + .isNotEqualTo(VORGAENGE_WITH_UNGELESENE_NACHRICHTEN_PATH); + } + } + } + @DisplayName("Create filterBy") @Nested class TestCreateFilterBy { @Test void shouldSetFilterByOrganisationsEinheitId() { - var filterCriteria = mapFilterCriteria(); + var filterCriteria = createFilterBy(); assertThat(filterCriteria.getFilterByOrganisationseinheitenId()) .isEqualTo(FilterCriteriaTestFactory.FILTER_BY_ORGANISATIONS_EINHEITEN_ID); @@ -200,7 +273,7 @@ class VorgangRemoteServiceTest { @Test void shouldSetOrganisationsEinheitIds() { - var filterCriteria = mapFilterCriteria(); + var filterCriteria = createFilterBy(); assertThat(filterCriteria.getOrganisationseinheitIdList()).containsExactly(FilterCriteriaTestFactory.ORGANISATIONS_EINHEIT_ID); } @@ -211,7 +284,7 @@ class VorgangRemoteServiceTest { @Test void shouldBeSet() { - var filterCriteria = mapFilterCriteria(); + var filterCriteria = createFilterBy(); assertThat(filterCriteria.getFilterByAssignedTo()).isTrue(); } @@ -223,14 +296,14 @@ class VorgangRemoteServiceTest { @Test void shouldBeSetIfExists() { - var filterCriteria = mapFilterCriteria(); + var filterCriteria = createFilterBy(); assertThat(filterCriteria.getAssignedTo()).isEqualTo(UserProfileTestFactory.ID.toString()); } @Test void shouldNotBeSetIfNotExist() { - var filterCriteria = mapFilterCriteria(FilterCriteriaTestFactory.createBuilder().assignedTo(Optional.empty()).build()); + var filterCriteria = createFilterBy(FilterCriteriaTestFactory.createBuilder().assignedTo(Optional.empty()).build()); assertThat(filterCriteria.getAssignedTo()).isEqualTo(StringUtils.EMPTY); } @@ -242,14 +315,14 @@ class VorgangRemoteServiceTest { @Test void shouldBeSetIfExists() { - var filterCriteria = mapFilterCriteria(); + var filterCriteria = createFilterBy(); assertThat(filterCriteria.getStatusList()).containsExactly(FilterCriteriaTestFactory.VORGANG_STATUS.toString()); } @Test void shouldNotBeSetIfNotExist() { - var filterCriteria = mapFilterCriteria(FilterCriteriaTestFactory.createBuilder().status(Optional.empty()).build()); + var filterCriteria = createFilterBy(FilterCriteriaTestFactory.createBuilder().status(Optional.empty()).build()); assertThat(filterCriteria.getStatusCount()).isZero(); @@ -262,25 +335,25 @@ class VorgangRemoteServiceTest { @Test void shouldBeSetToFalse() { - var filterCriteria = mapFilterCriteria(FilterCriteriaTestFactory.createBuilder().hasNextWiedervorlageFrist(false).build()); + var filterCriteria = createFilterBy(FilterCriteriaTestFactory.createBuilder().hasNextWiedervorlageFrist(false).build()); assertThat(filterCriteria.getHasNextWiedervorlageFrist()).isFalse(); } @Test void shouldNotBeSetToTrue() { - var filterCriteria = mapFilterCriteria(FilterCriteriaTestFactory.createBuilder().hasNextWiedervorlageFrist(true).build()); + var filterCriteria = createFilterBy(FilterCriteriaTestFactory.createBuilder().hasNextWiedervorlageFrist(true).build()); assertThat(filterCriteria.getHasNextWiedervorlageFrist()).isTrue(); } } - private GrpcFilterBy mapFilterCriteria() { - return mapFilterCriteria(FilterCriteriaTestFactory.create()); + private GrpcFilterBy createFilterBy() { + return createFilterBy(FilterCriteriaTestFactory.create()); } - private GrpcFilterBy mapFilterCriteria(FilterCriteria filterCriteria) { - return service.mapFilterCriteria(filterCriteria); + private GrpcFilterBy createFilterBy(FilterCriteria filterCriteria) { + return service.createFilterBy(filterCriteria); } } @@ -300,14 +373,14 @@ class VorgangRemoteServiceTest { when(serviceStub.findVorgangWithEingang(any())) .thenReturn(GrpcVorgangWithEingangResponseTestFactory.createVorgangWithEingangResponse()); when(vorgangWithEingangMapper.toVorgangWithEingang(any())).thenReturn(vorgangWithEingang); - doReturn(filterBy).when(service).mapFilterCriteria(any()); + doReturn(filterBy).when(service).createFilterBy(any()); } @Test void shouldCreateFilterBy() { callService(); - verify(service).mapFilterCriteria(any()); + verify(service).createFilterBy(any()); } @Test @@ -345,7 +418,7 @@ class VorgangRemoteServiceTest { @BeforeEach void mockReturnValue() { - doReturn(filterBy).when(service).mapFilterCriteria(any()); + doReturn(filterBy).when(service).createFilterBy(any()); } @Test diff --git a/pom.xml b/pom.xml index 4f00d84c16a1cc6f981d55ab11f3d1d05e2eb9fd..63d83b82f45e7cb960bc3f0d3382c29e7a999119 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> - <vorgang-manager.version>2.3.0</vorgang-manager.version> + <vorgang-manager.version>2.4.0-SNAPSHOT</vorgang-manager.version> <ozgcloud-common-pdf.version>3.0.1</ozgcloud-common-pdf.version> <user-manager.version>2.2.0</user-manager.version>