diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts index 98a918c03eb9d525d9bc2977f1885838dd873da3..1ceecd9e1f16e3309e234235887150f8e5c6ee3a 100644 --- a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts +++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts @@ -24,16 +24,19 @@ import { BinaryFileService } from '@alfa-client/binary-file-shared'; import { CommandOrder, CommandResource, CommandService, CreateCommand } from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { createEmptyStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared'; +import { createEmptyStateResource, createStateResource, EMPTY_STRING, StateResource } from '@alfa-client/tech-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { faker } from '@faker-js/faker'; import { expect } from '@jest/globals'; +import { ResourceUri } from '@ngxp/rest'; import { cold, hot } from 'jest-marbles'; import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; import { createCommandResource } from 'libs/command-shared/test/command'; import { createKommentar, createKommentarListResource, createKommentarResource } from 'libs/kommentar-shared/test/kommentar'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; import { of } from 'rxjs'; +import { singleCold } from '../../../tech-shared/test/marbles'; import { KommentarLinkRel, KommentarListLinkRel } from './kommentar.linkrel'; import { Kommentar, KOMMENTAR_UPLOADED_ATTACHMENTS, KommentarListResource, KommentarResource } from './kommentar.model'; import { KommentarRepository } from './kommentar.repository'; @@ -327,4 +330,78 @@ describe('KommentarService', () => { expect(binaryFileService.clearUploadedFiles).toHaveBeenCalledWith(KOMMENTAR_UPLOADED_ATTACHMENTS); }); }); + + describe('is new kommentar formular visible', () => { + it('should emit true', () => { + service._currentlyEdited$.next(EMPTY_STRING); + service.formularVisibility$.next(true); + + expect(service.isFormularVisible()).toBeObservable(singleCold(true)); + }); + + it('should emit false if any kommentar is being edited', () => { + service._currentlyEdited$.next(faker.internet.url()); + service.formularVisibility$.next(true); + + expect(service.isFormularVisible()).toBeObservable(singleCold(false)); + }); + + it('should emit false if not visible', () => { + service._currentlyEdited$.next(EMPTY_STRING); + service.formularVisibility$.next(false); + + expect(service.isFormularVisible()).toBeObservable(singleCold(false)); + }); + }); + + describe('show new kommentar formular', () => { + beforeEach(() => { + service.setCurrentlyEdited = jest.fn(); + }); + + it('should set currently edited to empty string', () => { + service.showFormular(); + + expect(service.setCurrentlyEdited).toHaveBeenCalledWith(EMPTY_STRING); + }); + + it('should set formular visibility', () => { + service.showFormular(); + + expect(service.formularVisibility$).toBeObservable(singleCold(true)); + }); + }); + + describe('set currently edited kommentar uri', () => { + beforeEach(() => { + service.clearUploadedFiles = jest.fn(); + service.hideFormular = jest.fn(); + }); + + it('should clear uploaded files', () => { + service.setCurrentlyEdited(faker.internet.url()); + + expect(service.clearUploadedFiles).toHaveBeenCalled(); + }); + + it('should hide kommentar creation formular', () => { + service.setCurrentlyEdited(faker.internet.url()); + + expect(service.hideFormular).toHaveBeenCalled(); + }); + + it('should NOT hide kommentar creation formular', () => { + service.setCurrentlyEdited(EMPTY_STRING); + + expect(service.hideFormular).not.toHaveBeenCalled(); + }); + + it('should emit currently edited resource uri', () => { + const resourceUri: ResourceUri = faker.internet.url(); + + service.setCurrentlyEdited(resourceUri); + + expect(service._currentlyEdited$).toBeObservable(singleCold(resourceUri)); + }); + }); }); diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts index 27efa8ae9da9e852906f3917b070e27e9faeca2d..6749d94ff0079091abf5f3a42d6c67786b171d08 100644 --- a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts +++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts @@ -24,13 +24,13 @@ import { BinaryFileListResource, BinaryFileService } from '@alfa-client/binary-file-shared'; import { CommandOrder, CommandResource, CommandService, CreateCommand, isDone } from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { createEmptyStateResource, createStateResource, doIfLoadingRequired, StateResource } from '@alfa-client/tech-shared'; +import { createEmptyStateResource, createStateResource, doIfLoadingRequired, EMPTY_STRING, isNotEmpty, StateResource, } from '@alfa-client/tech-shared'; import { VorgangResource, VorgangService } from '@alfa-client/vorgang-shared'; import { Injectable } from '@angular/core'; import { Params } from '@angular/router'; -import { hasLink, Resource } from '@ngxp/rest'; +import { hasLink, Resource, ResourceUri } from '@ngxp/rest'; import { isNil } from 'lodash-es'; -import { BehaviorSubject, Observable, of, Subscription } from 'rxjs'; +import { BehaviorSubject, combineLatest, Observable, of, Subscription } from 'rxjs'; import { map, startWith, tap } from 'rxjs/operators'; import { KommentarLinkRel, KommentarListLinkRel } from './kommentar.linkrel'; import { Kommentar, KOMMENTAR_UPLOADED_ATTACHMENTS, KommentarListResource, KommentarResource } from './kommentar.model'; @@ -42,6 +42,7 @@ export class KommentarService { createEmptyStateResource<KommentarListResource>(), ); readonly formularVisibility$: BehaviorSubject<boolean> = new BehaviorSubject(false); + readonly _currentlyEdited$: BehaviorSubject<ResourceUri> = new BehaviorSubject(''); private navigationSub: Subscription; @@ -104,7 +105,9 @@ export class KommentarService { } public isFormularVisible(): Observable<boolean> { - return this.formularVisibility$.asObservable(); + return combineLatest([this.formularVisibility$, this._currentlyEdited$]).pipe( + map(([isVisible, currentlyEdited]) => isVisible && currentlyEdited === EMPTY_STRING), + ); } public canCreateNewKommentar(kommentareListResource: KommentarListResource): Observable<boolean> { @@ -114,6 +117,7 @@ export class KommentarService { } public showFormular(): void { + this.setCurrentlyEdited(EMPTY_STRING); this.formularVisibility$.next(true); } @@ -170,4 +174,16 @@ export class KommentarService { public clearUploadedFiles(): void { this.binaryFileService.clearUploadedFiles(KOMMENTAR_UPLOADED_ATTACHMENTS); } + + public getCurrentlyEdited(): Observable<ResourceUri> { + return this._currentlyEdited$.asObservable(); + } + + public setCurrentlyEdited(resourceUri: ResourceUri): void { + this.clearUploadedFiles(); + if (isNotEmpty(resourceUri)) { + this.hideFormular(); + } + this._currentlyEdited$.next(resourceUri); + } } diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.html b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.html index 8b432f5eee5589efc42249c5bfdf3f64a631b818..30f142acca7a7374f7e11d554c238f72a235b1ae 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.html +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.html @@ -27,6 +27,7 @@ <ozgcloud-expansion-panel headline="Kommentare"> <alfa-kommentar-list-in-vorgang [kommentarListStateResource]="kommentarListStateResource" + [currentlyEdited]="kommentarService.getCurrentlyEdited() | async" data-test-id="kommentar-list-in-vorgang" > </alfa-kommentar-list-in-vorgang> diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts index 44794b0072f9b661cd22120938e0a045e9b5d330..1fa11168673776f20130a7be5616abb0ac84380a 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts @@ -70,6 +70,14 @@ describe('KommentarListInVorgangContainerComponent', () => { expect(component).toBeTruthy(); }); + describe('ng on init', () => { + it('should call kommentar service isFormularVisible', () => { + component.ngOnInit(); + + expect(kommentarService.isFormularVisible).toHaveBeenCalled(); + }); + }); + describe('ng on changes', () => { beforeEach(() => { kommentarService.isFormularVisible.mockReturnValue(new Observable((o) => o.next(false))); @@ -78,12 +86,6 @@ describe('KommentarListInVorgangContainerComponent', () => { ); }); - it('should call kommentar service isFormularVisible', () => { - component.ngOnChanges(); - - expect(kommentarService.isFormularVisible).toHaveBeenCalled(); - }); - it('should call kommentar service getKommentareByVorgang', () => { component.ngOnChanges(); diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.ts index 8c601d9240a060ca4ceb9cd18a9b9964198eae83..21d3159a29496a6927f7076de4734ff03c663f44 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.ts @@ -21,10 +21,10 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { Component, Input, OnChanges } from '@angular/core'; import { KommentarListResource, KommentarService } from '@alfa-client/kommentar-shared'; import { StateResource } from '@alfa-client/tech-shared'; import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { Component, inject, Input, OnChanges, OnInit } from '@angular/core'; import { mergeMap, Observable } from 'rxjs'; @Component({ @@ -32,25 +32,24 @@ import { mergeMap, Observable } from 'rxjs'; templateUrl: './kommentar-list-in-vorgang-container.component.html', styleUrls: ['./kommentar-list-in-vorgang-container.component.scss'], }) -export class KommentarListInVorgangContainerComponent implements OnChanges { +export class KommentarListInVorgangContainerComponent implements OnChanges, OnInit { @Input() vorgangStateResource: StateResource<VorgangWithEingangResource>; - showFormular$: Observable<boolean>; + public readonly kommentarService = inject(KommentarService); + + public showFormular$: Observable<boolean>; kommentarListStateResource$: Observable<StateResource<KommentarListResource>>; canCreateNewKommentar$: Observable<boolean>; - constructor(private kommentarService: KommentarService) {} + ngOnInit(): void { + this.showFormular$ = this.kommentarService.isFormularVisible(); + } ngOnChanges(): void { this.reloadKommentarListOnVorgangReload(); - this.showFormular$ = this.kommentarService.isFormularVisible(); - this.kommentarListStateResource$ = this.kommentarService.getKommentareByVorgang( - this.vorgangStateResource.resource, - ); + this.kommentarListStateResource$ = this.kommentarService.getKommentareByVorgang(this.vorgangStateResource.resource); this.canCreateNewKommentar$ = this.kommentarListStateResource$.pipe( - mergeMap((stateResource) => - this.kommentarService.canCreateNewKommentar(stateResource.resource), - ), + mergeMap((stateResource) => this.kommentarService.canCreateNewKommentar(stateResource.resource)), ); } diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.html b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.html index be3ecc3720ffb2e967b888e54243eb72a5234c11..75ccfb30068aad3b5d8e2847618a3267cb0fb400 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.html +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.html @@ -27,5 +27,6 @@ *ngFor="let kommentar of kommentare" [kommentar]="kommentar" [kommentarListStateResource]="kommentarListStateResource" + [currentlyEdited]="currentlyEdited" > </alfa-kommentar-list-item-in-vorgang> diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.ts index 4519d517cefe76995824afd7b45b8651ac354b8a..1d7212702a1b398d0da13637dc24e598d1f5bf8d 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.ts @@ -21,10 +21,11 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { Component, Input, OnChanges } from '@angular/core'; import { KommentarListResource, KommentarResource } from '@alfa-client/kommentar-shared'; -import { KommentarListLinkRel } from 'libs/kommentar-shared/src/lib/kommentar.linkrel'; import { getEmbeddedResources, StateResource } from '@alfa-client/tech-shared'; +import { Component, Input, OnChanges } from '@angular/core'; +import { ResourceUri } from '@ngxp/rest'; +import { KommentarListLinkRel } from 'libs/kommentar-shared/src/lib/kommentar.linkrel'; @Component({ selector: 'alfa-kommentar-list-in-vorgang', @@ -33,17 +34,15 @@ import { getEmbeddedResources, StateResource } from '@alfa-client/tech-shared'; }) export class KommentarListInVorgangComponent implements OnChanges { @Input() kommentarListStateResource: StateResource<KommentarListResource>; + @Input() currentlyEdited: ResourceUri; - kommentare: KommentarResource[]; + public kommentare: KommentarResource[]; ngOnChanges(): void { this.kommentare = this.getKommentare(); } getKommentare(): KommentarResource[] { - return getEmbeddedResources( - this.kommentarListStateResource, - KommentarListLinkRel.KOMMENTAR_LIST, - ); + return getEmbeddedResources(this.kommentarListStateResource, KommentarListLinkRel.KOMMENTAR_LIST); } } diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.spec.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.spec.ts index 127b7fda5dd6f18ac336393aa425dd3903e94ee7..c5a1d190d2f95214dd39f60e95119fbda5d9e9ba 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.spec.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.spec.ts @@ -21,26 +21,17 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ +import { KommentarLinkRel, KommentarResource, KommentarService } from '@alfa-client/kommentar-shared'; +import { ConvertForDataTestPipe, FormatDateWithTimePipe, HasLinkPipe } from '@alfa-client/tech-shared'; +import { getElementFromFixture, mock } from '@alfa-client/test-utils'; +import { UserProfileInKommentarContainerComponent } from '@alfa-client/user-profile'; import { registerLocaleData } from '@angular/common'; import localeDe from '@angular/common/locales/de'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { - KommentarLinkRel, - KommentarListLinkRel, - KommentarService, -} from '@alfa-client/kommentar-shared'; -import { - ConvertForDataTestPipe, - createStateResource, - FormatDateWithTimePipe, - HasLinkPipe, -} from '@alfa-client/tech-shared'; -import { getElementFromFixture, mock } from '@alfa-client/test-utils'; -import { UserProfileInKommentarContainerComponent } from '@alfa-client/user-profile'; -import { - createKommentarListResource, - createKommentarResource, -} from 'libs/kommentar-shared/test/kommentar'; +import { faker } from '@faker-js/faker/.'; +import { expect } from '@jest/globals'; +import { getUrl } from '@ngxp/rest'; +import { createKommentarResource } from 'libs/kommentar-shared/test/kommentar'; import { getDataTestClassOf } from 'libs/tech-shared/test/data-test'; import { MockComponent } from 'ng-mocks'; import { KommentarFormComponent } from '../../kommentar-form/kommentar-form.component'; @@ -85,6 +76,37 @@ describe('KommentarListItemInVorgangComponent', () => { expect(component).toBeTruthy(); }); + describe('set currently edited', () => { + const kommentar: KommentarResource = createKommentarResource(); + + it('should set edit mode to false on same currently edited resource uri', () => { + component.editMode = false; + component.kommentar = kommentar; + + component.currentlyEdited = getUrl(kommentar); + + expect(component.editMode).toBe(false); + }); + + it('should set edit mode to false on different currently edited resource uri', () => { + component.editMode = true; + component.kommentar = kommentar; + + component.currentlyEdited = faker.internet.url(); + + expect(component.editMode).toBe(false); + }); + + it('should set edit mode to true', () => { + component.editMode = true; + component.kommentar = kommentar; + + component.currentlyEdited = getUrl(kommentar); + + expect(component.editMode).toBe(true); + }); + }); + describe('user profile', () => { it('should be visible on existing link', () => { component.kommentar = createKommentarResource([KommentarLinkRel.CREATED_BY]); @@ -105,18 +127,9 @@ describe('KommentarListItemInVorgangComponent', () => { }); }); - describe('kommentare attachments', () => { - it('should be loaded', () => { - const kommentarResource = createKommentarResource(); - component.kommentar = kommentarResource; - - component.ngOnInit(); - - expect(kommentarService.getAttachments).toHaveBeenCalledWith(kommentarResource); - }); - }); - describe('edit', () => { + const kommentar: KommentarResource = createKommentarResource(); + it('should change editMode', () => { component.kommentar = createKommentarResource([KommentarLinkRel.EDIT]); @@ -125,12 +138,20 @@ describe('KommentarListItemInVorgangComponent', () => { expect(component.editMode).toBeTruthy(); }); - it('should not change editMode', () => { - component.kommentar = createKommentarResource(); + it('should NOT change editMode', () => { + component.kommentar = kommentar; component.edit(); expect(component.editMode).toBeFalsy(); }); + + it('should set currently edited kommetar uri', () => { + component.kommentar = kommentar; + + component.edit(); + + expect(kommentarService.setCurrentlyEdited).toHaveBeenCalledWith(getUrl(kommentar)); + }); }); }); diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.ts index cf6a951f4bd32c241281ce7c3207092387f92ce1..7da6b91741e10ca74fdb3a4572d43190481826d5 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.ts @@ -21,35 +21,32 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { BinaryFileListResource } from '@alfa-client/binary-file-shared'; import { KommentarLinkRel, KommentarListResource, KommentarResource, KommentarService } from '@alfa-client/kommentar-shared'; -import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared'; -import { Component, Input, OnInit } from '@angular/core'; -import { hasLink } from '@ngxp/rest'; -import { Observable, of } from 'rxjs'; +import { StateResource } from '@alfa-client/tech-shared'; +import { Component, inject, Input } from '@angular/core'; +import { getUrl, hasLink, ResourceUri } from '@ngxp/rest'; @Component({ selector: 'alfa-kommentar-list-item-in-vorgang', templateUrl: './kommentar-list-item-in-vorgang.component.html', styleUrls: ['./kommentar-list-item-in-vorgang.component.scss'], }) -export class KommentarListItemInVorgangComponent implements OnInit { +export class KommentarListItemInVorgangComponent { @Input() kommentar: KommentarResource; - @Input() kommentarListStateResource: StateResource<KommentarListResource>; - attachments$: Observable<StateResource<BinaryFileListResource>> = of(createEmptyStateResource<BinaryFileListResource>()); - editMode: boolean = false; + @Input() set currentlyEdited(value: ResourceUri) { + this.editMode &&= value === getUrl(this.kommentar); + } - readonly kommentarLinkRel = KommentarLinkRel; + public kommentarService = inject(KommentarService); - constructor(public kommentarService: KommentarService) {} + public editMode: boolean = false; - ngOnInit(): void { - this.attachments$ = this.kommentarService.getAttachments(this.kommentar); - } + public readonly kommentarLinkRel = KommentarLinkRel; - edit(): void { + public edit(): void { this.editMode = hasLink(this.kommentar, KommentarLinkRel.EDIT); + this.kommentarService.setCurrentlyEdited(getUrl(this.kommentar)); } }