diff --git a/alfa-client/.editorconfig b/alfa-client/.editorconfig index e14b6a99e7209e7a792eb54731d0a73614ce9d7c..21bdfce6b9ac66fd38fc1afc849a66da184e0352 100644 --- a/alfa-client/.editorconfig +++ b/alfa-client/.editorconfig @@ -28,8 +28,8 @@ root = true [*] -indent_style = tab -indent_size = 4 +indent_style = space +indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true diff --git a/alfa-client/apps/alfa-e2e/Jenkinsfile b/alfa-client/apps/alfa-e2e/Jenkinsfile index 18cd45748722fa9b6c1dd723af62878744e1b819..eca38dd16248ecdb8ffd648482e74a0cbbd5f168 100644 --- a/alfa-client/apps/alfa-e2e/Jenkinsfile +++ b/alfa-client/apps/alfa-e2e/Jenkinsfile @@ -676,7 +676,7 @@ String generateCypressConfig(String bezeichner, String testFolder, String userFo config.env.dbUrl = "mongodb://${decodeString(vorgangManagerDatabaseSecret.username)}:${parsablePassword}@localhost:${dbPort}/admin?ssl=false&directConnection=true" as String config.env.keycloakUrl = "https://${env.SSO_URL}/" as String config.env.keycloakRealm = namespace as String - config.env += createUserIdsEnv(userFolder, namespace) + // config.env += createUserIdsEnv(userFolder, namespace) config.videosFolder = "./reports/${testFolder}/videos" as String config.screenshotsFolder = "./reports/${testFolder}/screenshots" as String config.reporterOptions.reportDir = "./reports/${testFolder}/mochawesome-report" as String diff --git a/alfa-client/apps/alfa-e2e/cypress.config.json b/alfa-client/apps/alfa-e2e/cypress.config.json index 51aed25856700ddaa535421360ac106f45ca759a..bf241ca8448e0a90bc8ba525d7eb9d5c7bfd3fba 100644 --- a/alfa-client/apps/alfa-e2e/cypress.config.json +++ b/alfa-client/apps/alfa-e2e/cypress.config.json @@ -2,7 +2,7 @@ "baseUrl": "http://localhost:4300", "env": { "dbUrl": "mongodb://localhost:27018", - "database": "test", + "database": "local", "keycloakRealm": "by-e2e-local-dev", "keycloakUrl": "https://sso.dev.by.ozg-cloud.de/", "keycloakClient": "alfa", @@ -36,4 +36,4 @@ "reportFilename": "report", "overwrite": true } -} +} \ No newline at end of file diff --git a/alfa-client/apps/alfa-e2e/docker-compose.yml b/alfa-client/apps/alfa-e2e/docker-compose.yml index fc0bb1476055b3067a232095fb0c74b355ae3e15..49d874732f102f16d13f94b8ad0aba54d4bcc2c1 100644 --- a/alfa-client/apps/alfa-e2e/docker-compose.yml +++ b/alfa-client/apps/alfa-e2e/docker-compose.yml @@ -45,6 +45,7 @@ services: - OZGCLOUD_PROCESSORS_0_NAME=ticketCheck - OZGCLOUD_USER-MANAGER_URL=http://localhost:9092 - SPRING_DATA_MONGODB_HOST=mongodb + - SPRING_DATA_MONGODB_DATABASE=local - SPRING_PROFILES_ACTIVE=${SPRING_PROFILE:-local,e2e} - LOGGING_CONFIG=classpath:log4j2-local.xml ports: diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.util.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.util.ts index 8b8507d5e77ccbe0074810da1d3a47a93b1aa10d..4b0e6396bccece591f7fbbfc09bc428bc15e5148 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.util.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.util.ts @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { EnumEditorItem } from '@alfa-client/ui'; +import { CheckboxEnumEditorItem } from '@alfa-client/ui'; import { getEmbeddedResource } from '@ngxp/rest'; import { isNil } from 'lodash-es'; import { PostfachMailListLinkRel } from './postfach.linkrel'; @@ -77,13 +77,9 @@ export function getPostfachNachrichtenCount( } } -export const FORBIDDEN_REPLY_OPTION_ITEM: EnumEditorItem = { +export const FORBIDDEN_REPLY_OPTION_ITEM: CheckboxEnumEditorItem = { type: ReplyOption.FORBIDDEN, - svgIcon: 'no_reply', - text: 'Antworten unterbinden', }; -export const POSSIBLE_REPLY_OPTION_ITEM: EnumEditorItem = { +export const POSSIBLE_REPLY_OPTION_ITEM: CheckboxEnumEditorItem = { type: ReplyOption.POSSIBLE, - icon: 'reply', - text: 'Antworten erlauben', }; diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.html index 54088d409e922a838fb6f4350c575af9dbd92cc7..c56d5eeb8514ed4295ffba4817c573e304009ffb 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.html @@ -46,7 +46,7 @@ [postfachNachricht]="dialogData.postfachNachricht" ></alfa-postfach-nachricht-attachment-container> - <div class="button-bar-bottom"> + <div class="button-bar-bottom space-between"> <ozgcloud-stroked-button-with-spinner data-test-id="postfach-send-button" [stateResource]="sendInProgress$ | async" diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.scss b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.scss index e62869c090e63ed5b7bc93aa35b8e4d74f4e6751..d72717d84ac61991ea6146183c7800a5ed773fae 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.scss +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.scss @@ -65,3 +65,8 @@ min-height: 20px; } } + +.space-between { + display: flex; + justify-content: space-between; +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.html index 4d6b60475269f0c8fea1aadf4917c03875d01581..89bb3a3050bd289ee340d028736d074c59e62265 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.html @@ -1,10 +1,12 @@ <ng-container *ngIf="postfachFeatures$ | async as postfachFeatures"> - <ozgcloud-enum-editor + <ozgcloud-checkbox-enum-editor *ngIf="postfachFeatures.reply" data-test-id="postfach-reply-option" + label="Antwort vom Antragsteller benötigt" [formControlName]="formServiceClass.FIELD_REPLY_OPTION" - [defaultItem]="defaultItem" - [itemList]="itemList" + [defaultItem]="checkedItem" + [checkedItem]="checkedItem" + [uncheckedItem]="uncheckedItem" > - </ozgcloud-enum-editor> + </ozgcloud-checkbox-enum-editor> </ng-container> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.spec.ts index ef6570a027fa28d5536b40d0474788aba82608a3..7f04f09813364491d022e2311d6167be12052978 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.spec.ts @@ -13,12 +13,12 @@ import { mock, notExistsAsHtmlElement, } from '@alfa-client/test-utils'; -import { EnumEditorComponent } from '@alfa-client/ui'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { MockComponent } from 'ng-mocks'; import { of } from 'rxjs'; import { PostfachMailFormservice } from '../postfach-mail.formservice'; import { PostfachNachrichtReplyEditorContainerComponent } from './postfach-nachricht-reply-editor-container.component'; +import { CheckboxEnumEditorComponent } from '@alfa-client/ui'; describe('PostfachNachrichtReplyEditorContainerComponent', () => { let component: PostfachNachrichtReplyEditorContainerComponent; @@ -39,7 +39,7 @@ describe('PostfachNachrichtReplyEditorContainerComponent', () => { await TestBed.configureTestingModule({ declarations: [ PostfachNachrichtReplyEditorContainerComponent, - MockComponent(EnumEditorComponent), + MockComponent(CheckboxEnumEditorComponent), ], providers: [ { @@ -86,25 +86,41 @@ describe('PostfachNachrichtReplyEditorContainerComponent', () => { it.skip('should be called with formControlName', () => { fixture.detectChanges(); - const enumEditor: EnumEditorComponent = getMockComponent(fixture, EnumEditorComponent); + const enumEditor: CheckboxEnumEditorComponent = getMockComponent( + fixture, + CheckboxEnumEditorComponent, + ); expect(enumEditor.control).toBe(PostfachMailFormservice.FIELD_REPLY_OPTION); }); it('should be called with defaultItem', () => { fixture.detectChanges(); - const enumEditor: EnumEditorComponent = getMockComponent(fixture, EnumEditorComponent); + const enumEditor: CheckboxEnumEditorComponent = getMockComponent( + fixture, + CheckboxEnumEditorComponent, + ); expect(enumEditor.defaultItem).toBe(POSSIBLE_REPLY_OPTION_ITEM); }); - it('should be called wirh itemList', () => { + it('should be called with checked item', () => { fixture.detectChanges(); - const enumEditor: EnumEditorComponent = getMockComponent(fixture, EnumEditorComponent); - expect(enumEditor.itemList).toEqual([ - POSSIBLE_REPLY_OPTION_ITEM, - FORBIDDEN_REPLY_OPTION_ITEM, - ]); + const enumEditor: CheckboxEnumEditorComponent = getMockComponent( + fixture, + CheckboxEnumEditorComponent, + ); + expect(enumEditor.checkedItem).toBe(POSSIBLE_REPLY_OPTION_ITEM); + }); + + it('should be called with unchecked item', () => { + fixture.detectChanges(); + + const enumEditor: CheckboxEnumEditorComponent = getMockComponent( + fixture, + CheckboxEnumEditorComponent, + ); + expect(enumEditor.uncheckedItem).toBe(FORBIDDEN_REPLY_OPTION_ITEM); }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.ts index dff70f9872dcaf71b52d57f44894a9a443f6c15d..1e6ae6bea4559a733a50f29c4411aedc738c8e1c 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.ts @@ -1,12 +1,12 @@ import { Component, OnInit } from '@angular/core'; import { - FORBIDDEN_REPLY_OPTION_ITEM, Features, + FORBIDDEN_REPLY_OPTION_ITEM, POSSIBLE_REPLY_OPTION_ITEM, PostfachService, } from '@alfa-client/postfach-shared'; import { FormProvider } from '@alfa-client/tech-shared'; -import { EnumEditorItem } from '@alfa-client/ui'; +import { CheckboxEnumEditorItem } from '@alfa-client/ui'; import { Observable } from 'rxjs'; import { PostfachMailFormservice } from '../postfach-mail.formservice'; @@ -17,16 +17,13 @@ import { PostfachMailFormservice } from '../postfach-mail.formservice'; viewProviders: [FormProvider], }) export class PostfachNachrichtReplyEditorContainerComponent implements OnInit { - public readonly itemList: EnumEditorItem[] = [ - POSSIBLE_REPLY_OPTION_ITEM, - FORBIDDEN_REPLY_OPTION_ITEM, - ]; - public readonly defaultItem: EnumEditorItem = POSSIBLE_REPLY_OPTION_ITEM; - public readonly formServiceClass = PostfachMailFormservice; public postfachFeatures$: Observable<Features>; + public checkedItem: CheckboxEnumEditorItem = POSSIBLE_REPLY_OPTION_ITEM; + public uncheckedItem: CheckboxEnumEditorItem = FORBIDDEN_REPLY_OPTION_ITEM; + constructor(private postfachService: PostfachService) {} ngOnInit(): void { diff --git a/alfa-client/libs/ui/.eslintrc.json b/alfa-client/libs/ui/.eslintrc.json index 07ceb6eb1f7d34299016dadeedc8f8546f74158e..0ff6d35a3359167cd29a27ecc2b6fbf663325bab 100644 --- a/alfa-client/libs/ui/.eslintrc.json +++ b/alfa-client/libs/ui/.eslintrc.json @@ -10,7 +10,7 @@ "error", { "type": "attribute", - "prefix": "alfa", + "prefix": "ozgcloud", "style": "camelCase" } ], @@ -18,7 +18,7 @@ "error", { "type": "element", - "prefix": "alfa", + "prefix": "ozgcloud", "style": "kebab-case" } ] diff --git a/alfa-client/libs/ui/src/index.ts b/alfa-client/libs/ui/src/index.ts index 82706251be4ccd84055ccb4e37c82717b35e59be..c1159e21d049fc4b787912e39bffd85efda89962 100644 --- a/alfa-client/libs/ui/src/index.ts +++ b/alfa-client/libs/ui/src/index.ts @@ -58,3 +58,5 @@ export * from './lib/ui/subnavigation/subnavigation.component'; export * from './lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component'; export * from './lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component'; export * from './lib/ui/ui.module'; +export * from './lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component'; +export * from './lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.model'; diff --git a/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.html new file mode 100644 index 0000000000000000000000000000000000000000..3c8b8cc76209df603cbccb8c06af18a43bf9dd9e --- /dev/null +++ b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.html @@ -0,0 +1,3 @@ +<mat-checkbox color="primary" [checked]="selected" (change)="setSelection($event)" + >{{ label }} +</mat-checkbox> diff --git a/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.scss b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..4c0855d0914ebcca40f1287042a581b97707bea7 --- /dev/null +++ b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.spec.ts @@ -0,0 +1,59 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ReactiveFormsModule } from '@angular/forms'; +import { MatIcon } from '@angular/material/icon'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { ConvertForDataTestPipe } from '@alfa-client/tech-shared'; +import { IconButtonWithSpinnerComponent, UiModule } from '@alfa-client/ui'; +import { MockComponent } from 'ng-mocks'; +import { CheckboxEnumEditorComponent } from '@alfa-client/ui'; + +describe('CheckboxEnumEditorComponent', () => { + let component: CheckboxEnumEditorComponent; + let fixture: ComponentFixture<CheckboxEnumEditorComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + CheckboxEnumEditorComponent, + MatIcon, + ConvertForDataTestPipe, + MockComponent(IconButtonWithSpinnerComponent), + ], + imports: [UiModule, MatFormFieldModule, ReactiveFormsModule, BrowserAnimationsModule], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CheckboxEnumEditorComponent); + component = fixture.componentInstance; + component.defaultItem = { type: 'enumType' }; + component.checkedItem = { type: 'positive' }; + component.uncheckedItem = { type: 'negative' }; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('setSelection', () => { + const writeMethodMock = jest.fn(); + + beforeEach(() => { + component.writeValue = writeMethodMock; + }); + + it('should write checked value on selected', () => { + component.setSelection({ source: null, checked: true }); + + expect(writeMethodMock).toHaveBeenCalledWith('positive'); + }); + + it('should write unchecked value on selected', () => { + component.setSelection({ source: null, checked: false }); + + expect(writeMethodMock).toHaveBeenCalledWith('negative'); + }); + }); +}); diff --git a/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..d896c82a1626ffd500382b34f58481fd1a794124 --- /dev/null +++ b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.component.ts @@ -0,0 +1,34 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component'; +import { CheckboxEnumEditorItem } from './checkbox-enum-editor.model'; +import { MatCheckboxChange } from '@angular/material/checkbox'; + +/** + * Ein Checkbox, dessen Wert beim FormControl statt boolean als string aus dem enum editor item + * abgebildet wird. + */ +@Component({ + selector: 'ozgcloud-checkbox-enum-editor', + templateUrl: './checkbox-enum-editor.component.html', + styleUrls: ['./checkbox-enum-editor.component.scss'], +}) +export class CheckboxEnumEditorComponent + extends FormControlEditorAbstractComponent + implements OnInit +{ + @Input() label: string; + @Input() defaultItem: CheckboxEnumEditorItem; + @Input() checkedItem: CheckboxEnumEditorItem; + @Input() uncheckedItem: CheckboxEnumEditorItem; + + public selected: boolean; + + override ngOnInit(): void { + this.selected = this.defaultItem === this.checkedItem; + this.writeValue(this.defaultItem.type); + } + + setSelection(event: MatCheckboxChange): void { + this.writeValue(event.checked ? this.checkedItem.type : this.uncheckedItem.type); + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.model.ts b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.model.ts new file mode 100644 index 0000000000000000000000000000000000000000..1833e17688d96ea2cf28e350ee935d6974258bf5 --- /dev/null +++ b/alfa-client/libs/ui/src/lib/ui/editor/checkbox-enum-editor/checkbox-enum-editor.model.ts @@ -0,0 +1,3 @@ +export interface CheckboxEnumEditorItem { + type: any; +} diff --git a/alfa-client/libs/ui/src/lib/ui/ui.module.ts b/alfa-client/libs/ui/src/lib/ui/ui.module.ts index 61c0bd7440b5187519bb0b8397c35f88bc7f7678..26c004579db2d598a5585164729315680082ce6a 100644 --- a/alfa-client/libs/ui/src/lib/ui/ui.module.ts +++ b/alfa-client/libs/ui/src/lib/ui/ui.module.ts @@ -97,6 +97,7 @@ import { SubnavigationComponent } from './subnavigation/subnavigation.component' import { ValidationErrorComponent } from './validation-error/validation-error.component'; import { OzgcloudIconButtonPrimaryComponent } from './ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component'; import { OzgcloudPasteTextButtonComponent } from './ozgcloud-paste-text-button/ozgcloud-paste-text-button.component'; +import { CheckboxEnumEditorComponent } from './editor/checkbox-enum-editor/checkbox-enum-editor.component'; @NgModule({ declarations: [ @@ -146,6 +147,7 @@ import { OzgcloudPasteTextButtonComponent } from './ozgcloud-paste-text-button/o BasicDialogComponent, OzgcloudButtonContentComponent, OzgcloudPasteTextButtonComponent, + CheckboxEnumEditorComponent, ], imports: [ MatButtonModule, @@ -245,6 +247,7 @@ import { OzgcloudPasteTextButtonComponent } from './ozgcloud-paste-text-button/o SnackbarCloseButtonComponent, BasicDialogComponent, OzgcloudPasteTextButtonComponent, + CheckboxEnumEditorComponent, ], providers: [ { diff --git a/alfa-server/src/main/resources/application-dev.yml b/alfa-server/src/main/resources/application-dev.yml index 938a6bfeef434fd896cf8f9e7a46bf172e2a5c62..c7c2bdd8d6c319ae464c13b109ca4a191021cc68 100644 --- a/alfa-server/src/main/resources/application-dev.yml +++ b/alfa-server/src/main/resources/application-dev.yml @@ -1,7 +1,7 @@ keycloak: - auth-server-url: https://sso.dev.by.ozg-cloud.de - realm: by-kiel-dev - resource: alfa + auth-server-url: https://sso.dev.by.ozg-cloud.de + realm: by-kiel-dev + resource: alfa server: error: @@ -9,7 +9,8 @@ server: ozgcloud: feature: - vorgang-export: true + vorgang-export: true + reply-always-allowed: true production: false stage: production: false \ No newline at end of file diff --git a/alfa-server/src/main/resources/application-e2e.yml b/alfa-server/src/main/resources/application-e2e.yml index 1f0ddf6798f02a5215ba2e80b778c0cad8f2aa47..5cd02cdd6daa75998f2b06164f0065fcaf7c4afe 100644 --- a/alfa-server/src/main/resources/application-e2e.yml +++ b/alfa-server/src/main/resources/application-e2e.yml @@ -5,16 +5,17 @@ logging: keycloak: realm: by-e2e-local-dev - + ozgcloud: feature: - vorgang-export: true - createBescheid: true + vorgang-export: true + createBescheid: true + reply-always-allowed: true forwarding: lninfo: url: classpath:files/LandesnetzInfo.html user-assistance: - documentation: - url: /assets/benutzerleitfaden/benutzerleitfaden.pdf + documentation: + url: /assets/benutzerleitfaden/benutzerleitfaden.pdf user-manager: url: http://localhost:9092 \ No newline at end of file diff --git a/alfa-server/src/main/resources/application-local.yml b/alfa-server/src/main/resources/application-local.yml index 9f07a50d310e520c0d3437193b886a91001836cf..0c348fd48f2ab5dc221f5ea5c1cf3b98986cf3a6 100644 --- a/alfa-server/src/main/resources/application-local.yml +++ b/alfa-server/src/main/resources/application-local.yml @@ -12,19 +12,20 @@ grpc: user-manager: address: static://127.0.0.1:9000 negotiationType: PLAINTEXT - + ozgcloud: feature: vorgang-export: true + reply-always-allowed: true production: false user-assistance: - documentation: - url: /assets/benutzerleitfaden/benutzerleitfaden.pdf + documentation: + url: /assets/benutzerleitfaden/benutzerleitfaden.pdf user-manager: url: http://localhost:9091 profile-template: /api/userProfiles/%s search-template: /api/userProfiles/?searchBy={searchBy} - + keycloak: auth-server-url: http://localhost:8088 realm: by-kiel-dev diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/common/FeatureToggleProperties.java b/alfa-service/src/main/java/de/ozgcloud/alfa/common/FeatureToggleProperties.java index 30cb6d5e030a9de48c1ecac7e53fdff1e7c32606..1b516773c30d287d3a1571cb75f3c4009bee0873 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/common/FeatureToggleProperties.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/common/FeatureToggleProperties.java @@ -21,4 +21,9 @@ public class FeatureToggleProperties { * Enable/Disable bescheid creation feature. */ private boolean createBescheid = false; + + /** + * Enable mail reply option regardless of other configuration. + */ + private boolean replyAlwaysAllowed = false; } diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailController.java b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailController.java index 1237dc244c373c99b8803ec026bfc11519cc8c05..606c6ec3433a2d1cc012da17e56124884d83b33f 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailController.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailController.java @@ -55,29 +55,24 @@ import de.ozgcloud.alfa.common.file.OzgFile; import de.ozgcloud.alfa.vorgang.VorgangController; import de.ozgcloud.alfa.vorgang.VorgangWithEingang; import lombok.NonNull; +import lombok.RequiredArgsConstructor; +@RequiredArgsConstructor @RestController @RequestMapping(PostfachMailController.PATH) public class PostfachMailController { public static final String PATH = "/api/postfachMails"; // NOSONAR - public static final String PARAM_VORGANG_ID = "vorgangId"; - static final String PDF_NAME_TEMPLATE = "%s_%s_Nachrichten.pdf"; - static final DateTimeFormatter PDF_NAME_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd"); - @Autowired - private PostfachMailService service; - @Autowired - private PostfachMailModelAssembler assembler; + private final PostfachMailService service; - @Autowired - private VorgangController vorgangController; + private final PostfachMailModelAssembler assembler; - @Autowired - private BinaryFileController binaryFileController; + private final VorgangController vorgangController; + private final BinaryFileController binaryFileController; @GetMapping(params = PARAM_VORGANG_ID) public RepresentationModel<EntityModel<Postfach>> getAll(@RequestParam String vorgangId) { @@ -86,11 +81,15 @@ public class PostfachMailController { return assembler.toCollectionModel(sort(service.getAll(vorgangId)), buildPostfach(vorgang), vorgang); } - private Postfach buildPostfach(VorgangWithEingang vorgang) { - return Postfach.builder().features(Features.builder().reply(service.isReplyToMessageAllowed(vorgang)).build()).build(); + Postfach buildPostfach(VorgangWithEingang vorgang) { + return Postfach.builder() + .features(Features.builder() + .reply(service.isReplyToMessageAllowed(vorgang)) + .build()) + .build(); } - private Stream<PostfachMail> sort(Stream<PostfachMail> nachrichten) { + Stream<PostfachMail> sort(Stream<PostfachMail> nachrichten) { return nachrichten.sorted(new PostfachNachrichtComparator().reversed()); } diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailService.java b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailService.java index a94151852adef541a174920e40dc35081e801d4b..67b6a85aeb116118b4477b84290c7dac54d8bd2a 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailService.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailService.java @@ -32,9 +32,9 @@ import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import de.ozgcloud.alfa.common.FeatureToggleProperties; import de.ozgcloud.alfa.common.binaryfile.BinaryFileService; import de.ozgcloud.alfa.common.binaryfile.FileId; import de.ozgcloud.alfa.common.command.Command; @@ -47,25 +47,23 @@ import de.ozgcloud.alfa.common.user.UserProfile; import de.ozgcloud.alfa.common.user.UserService; import de.ozgcloud.alfa.vorgang.ServiceKonto; import de.ozgcloud.alfa.vorgang.VorgangWithEingang; +import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; +@RequiredArgsConstructor @Log4j2 @Service class PostfachMailService { private PostfachConfigGroup postfachConfigGroup; - @Autowired - private PostfachMailRemoteService remoteService; - @Autowired - private PostfachNachrichtPdfService pdfService; + private final PostfachMailRemoteService remoteService; + private final PostfachNachrichtPdfService pdfService; + private final BinaryFileService fileService; + private final UserService userService; + private final CommandService commandService; - @Autowired - private BinaryFileService fileService; - @Autowired - private UserService userService; - @Autowired - private CommandService commandService; + private final FeatureToggleProperties featureToggleProperties; public PostfachMail findById(PostfachNachrichtId nachrichtId) { return remoteService.findById(nachrichtId) @@ -150,9 +148,14 @@ class PostfachMailService { } boolean isReplyAllowed(String serviceKontoType) { + if (featureToggleProperties.isReplyAlwaysAllowed()) { + return true; + } + if (!isPostfachConfigured()) { return false; } + return postfachConfigGroup.getPostfachConfigs().stream() .filter(postfachConfig -> postfachConfig.getType().equals(serviceKontoType)) .map(PostfachConfig::isReplyAllowed) diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailControllerTest.java index 1b707f0650ed39bab2581ce7bed2dfcd288fd092..17f732923cf5995bae45c8521461e328b84b490c 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailControllerTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailControllerTest.java @@ -23,6 +23,7 @@ */ package de.ozgcloud.alfa.postfach; +import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; @@ -31,13 +32,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import java.io.IOException; import java.io.OutputStream; import java.time.LocalDate; +import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.mockito.ArgumentMatchers; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; @@ -60,10 +61,13 @@ class PostfachMailControllerTest { @Spy @InjectMocks // NOSONAR private PostfachMailController controller; + @Mock private PostfachMailService service; + @Mock private PostfachMailModelAssembler assembler; + @Mock private VorgangController vorgangController; @Mock @@ -80,9 +84,17 @@ class PostfachMailControllerTest { @Nested class TestGetAll { + private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create(); + private final Postfach postfach = PostfachTestFactory.create(); + private final Stream<PostfachMail> postfachMails = Stream.of(PostfachMailTestFactory.create()); + private final Stream<PostfachMail> sortedPostfachMails = Stream.of(PostfachMailTestFactory.create()); + @BeforeEach void mockVorgangController() { - when(vorgangController.getVorgang(anyString())).thenReturn(VorgangWithEingangTestFactory.create()); + when(vorgangController.getVorgang(anyString())).thenReturn(vorgang); + when(service.getAll(VorgangHeaderTestFactory.ID)).thenReturn(postfachMails); + doReturn(postfach).when(controller).buildPostfach(vorgang); + doReturn(sortedPostfachMails).when(controller).sort(postfachMails); } @Test @@ -103,14 +115,21 @@ class PostfachMailControllerTest { void shouldCallModelAssembler() { doRequest(); - verify(assembler).toCollectionModel(ArgumentMatchers.any(), any(Postfach.class), any()); + verify(assembler).toCollectionModel(sortedPostfachMails, postfach, vorgang); } @Test - void shouldCheckIsReplyAllowed() { + void shouldSortPostfachMails() { doRequest(); - verify(service).isReplyToMessageAllowed(any(VorgangWithEingang.class)); + verify(controller).sort(postfachMails); + } + + @Test + void shouldBuildPostfach() { + doRequest(); + + verify(controller).buildPostfach(vorgang); } @SneakyThrows @@ -120,6 +139,32 @@ class PostfachMailControllerTest { } } + @Nested + class TestBuildPostfach { + + private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create(); + + @Test + void shouldCheckIsReplyAllowed() { + callController(); + + verify(service).isReplyToMessageAllowed(any(VorgangWithEingang.class)); + } + + @Test + void shouldSetIsReplyAllowedFeature() { + when(service.isReplyToMessageAllowed(vorgang)).thenReturn(true); + + var postfach = callController(); + + assertThat(postfach.getFeatures().isReply()).isTrue(); + } + + private Postfach callController() { + return controller.buildPostfach(vorgang); + } + } + @DisplayName("Get all as pdf") @Nested class TestGetAllAsPdf { diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailServiceTest.java index aa07067a624b2dbc8d8a38d77f521da35b6ed36b..ddd2d24fd82e0776b55b363b219f7422a0f5a960 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailServiceTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailServiceTest.java @@ -47,6 +47,7 @@ import org.springframework.test.util.ReflectionTestUtils; import com.thedeanda.lorem.LoremIpsum; +import de.ozgcloud.alfa.common.FeatureToggleProperties; import de.ozgcloud.alfa.common.binaryfile.BinaryFileService; import de.ozgcloud.alfa.common.binaryfile.BinaryFileTestFactory; import de.ozgcloud.alfa.common.command.CommandService; @@ -81,6 +82,9 @@ class PostfachMailServiceTest { @Mock private CommandService commandService; + @Mock + private FeatureToggleProperties featureToggleProperties; + @DisplayName("Get all") @Nested class TestGetAll { @@ -512,6 +516,11 @@ class PostfachMailServiceTest { private static final String DUMMY_SERVICE_KONTO_TYPE = LoremIpsum.getInstance().getWords(1); + @BeforeEach + void setUp() { + when(featureToggleProperties.isReplyAlwaysAllowed()).thenReturn(false); + } + @Test @DisplayName("reply not allowed for given ServiceKonto-type") void shouldReturnFalseIfPostfachNotConfigured() { @@ -568,6 +577,15 @@ class PostfachMailServiceTest { assertThat(replyAllowed).isTrue(); } + + @Test + void shouldReturnTrueIfAlwaysAllowed() { + when(featureToggleProperties.isReplyAlwaysAllowed()).thenReturn(true); + + var replyAllowed = service.isReplyAllowed(PostfachConfigTestFactory.TYPE); + + assertThat(replyAllowed).isTrue(); + } } private void setPostfachConfigGroup(PostfachConfigGroup postfachConfigGroup) {