Skip to content
Snippets Groups Projects
Commit cfbcba57 authored by Sebastian Bergandy's avatar Sebastian Bergandy :keyboard:
Browse files

Merge branch 'OZG-5977-single-comment-edit' into 'main'

OZG-5977 allow for single comment edition

See merge request !79
parents e9d7bef2 e6024bbd
No related branches found
No related tags found
1 merge request!79OZG-5977 allow for single comment edition
Showing
with 187 additions and 74 deletions
......@@ -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));
});
});
});
......@@ -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);
}
}
......@@ -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>
......
......@@ -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();
......
......@@ -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)),
);
}
......
......@@ -27,5 +27,6 @@
*ngFor="let kommentar of kommentare"
[kommentar]="kommentar"
[kommentarListStateResource]="kommentarListStateResource"
[currentlyEdited]="currentlyEdited"
>
</alfa-kommentar-list-item-in-vorgang>
......@@ -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);
}
}
......@@ -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));
});
});
});
......@@ -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));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment