From 164975e4943d4f03648c93497b76301c83c7fd83 Mon Sep 17 00:00:00 2001
From: OZGCloud <ozgcloud@mgm-tp.com>
Date: Mon, 28 Jun 2021 17:02:41 +0200
Subject: [PATCH] OZG-297 refresh attachments on wiedervorlage; extend e2e test

---
 ...wiedervorlage-attachment-list.component.ts |  5 +-
 .../wiedervorlage-attachment.e2e-spec.ts      | 44 ++++++++---
 .../goofy-e2e/src/support/cypress.util.ts     |  4 +
 .../kommentar.formservice.spec.ts             |  4 +-
 .../src/lib/services/formservice.abstract.ts  | 22 +++---
 ...edervorlage-attachment-list.component.html |  2 +-
 ...rvorlage-attachment-list.component.spec.ts |  8 +-
 ...wiedervorlage-attachment-list.component.ts | 27 ++++---
 .../wiedervorlage-attachments.component.html  |  5 +-
 ...iedervorlage-attachments.component.spec.ts | 73 +++++++++++++++++--
 .../wiedervorlage-attachments.component.ts    | 23 ++++--
 .../wiedervorlage-form.component.spec.ts      | 12 +--
 .../wiedervorlage.formservice.spec.ts         |  4 +-
 .../wiedervorlage.formservice.ts              | 34 ++++-----
 14 files changed, 187 insertions(+), 80 deletions(-)

diff --git a/goofy-client/apps/goofy-e2e/src/components/wiedervorlage/wiedervorlage-attachment-list.component.ts b/goofy-client/apps/goofy-e2e/src/components/wiedervorlage/wiedervorlage-attachment-list.component.ts
index eb6e7ab78e..6e34462ffb 100644
--- a/goofy-client/apps/goofy-e2e/src/components/wiedervorlage/wiedervorlage-attachment-list.component.ts
+++ b/goofy-client/apps/goofy-e2e/src/components/wiedervorlage/wiedervorlage-attachment-list.component.ts
@@ -9,13 +9,16 @@ export class WiedervorlageAttachmentListE2EComponent {
 	public getAttachment(fileName: string): AttachmentE2EItem {
 		return new AttachmentE2EItem(fileName);
 	}
+
+	public getAttachments() {
+		return this.getRoot().children();
+	}
 }
 
 class AttachmentE2EItem {
 
 	private deleteButton$: string = 'icon-button';
 
-
 	constructor(private fileName: string) { }
 
 	public getRoot() {
diff --git a/goofy-client/apps/goofy-e2e/src/integration/wiedervorlage-attachment/wiedervorlage-attachment.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/wiedervorlage-attachment/wiedervorlage-attachment.e2e-spec.ts
index 71e0951397..23e1f07f6f 100644
--- a/goofy-client/apps/goofy-e2e/src/integration/wiedervorlage-attachment/wiedervorlage-attachment.e2e-spec.ts
+++ b/goofy-client/apps/goofy-e2e/src/integration/wiedervorlage-attachment/wiedervorlage-attachment.e2e-spec.ts
@@ -5,7 +5,7 @@ import { WiedervorlageE2EComponent } from '../../components/wiedervorlage/wieder
 import { MainPage } from '../../page-objects/main.po';
 import { VorgangPage } from '../../page-objects/vorgang.po';
 import { WiedervorlagePage } from '../../page-objects/wiedervorlage.po';
-import { CypressTasks, DatabaseUser, DataCollections, exist, MongoCollections, notExist } from '../../support/cypress.util';
+import { CypressTasks, DatabaseUser, DataCollections, exist, haveLength, MongoCollections, notExist } from '../../support/cypress.util';
 import { TEST_FILE, TEST_FILE_WITH_CONTENT } from '../../support/data.util';
 import { uploadEmptyFile, uploadFile } from '../../support/file-upload';
 
@@ -21,13 +21,13 @@ describe('Wiedervorlage attachments', () => {
 	const attachmentContainer: WiedervorlageAttachmentsE2EComponent = wiedervorlageContainer.getAttachmentContainer();
 	const attachmentList: WiedervorlageAttachmentListE2EComponent = attachmentContainer.getAttachmentList();
 
-	const WIEDERVORLAGE_BETREFF: string = 'WiedervorlageWithAttachments';
+	const WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF: string = 'WiedervorlageWithAttachments';
 
 	let vorgangWithoutWiedervorlage;
 
 	before(() => {
 		cy.fixture(DataCollections.WIEDERVORLAGEN).then(data => {
-			vorgangWithoutWiedervorlage = data[0];
+			vorgangWithoutWiedervorlage = data[2];
 			cy.task(CypressTasks.INIT_DATA, { collection: MongoCollections.VORGANG, data })
 		});
 
@@ -65,22 +65,22 @@ describe('Wiedervorlage attachments', () => {
 		})
 
 		it('save wiedervorlage', () => {
-			wiedervorlageContainer.getBetreff().clear().type(WIEDERVORLAGE_BETREFF);
+			wiedervorlageContainer.getBetreff().clear().type(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF);
 
 			wiedervorlageContainer.getSpeichernButton().click();
 		})
 
 		it('wiedervorlage in vorgang-detail should show attachments', () => {
-			wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_BETREFF).expandItem();
+			wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF).expandItem();
 
-			exist(wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_BETREFF).getAttachmentList().getAttachment(TEST_FILE).getRoot());
+			exist(wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF).getAttachmentList().getAttachment(TEST_FILE).getRoot());
 		})
 	})
 
 	describe('Delete attachment', () => {
 
 		it('open wiedervorlage page', () => {
-			wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_BETREFF).getLink().click();
+			wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF).getLink().click();
 
 			exist(attachmentList.getAttachment(TEST_FILE).getRoot());
 			exist(attachmentList.getAttachment(TEST_FILE_WITH_CONTENT).getRoot());
@@ -96,10 +96,32 @@ describe('Wiedervorlage attachments', () => {
 		})
 
 		it('check attachments in wiedervorlage list', () => {
-			wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_BETREFF).expandItem();
+			wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF).expandItem();
 
-			notExist(wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_BETREFF).getAttachmentList().getAttachment(TEST_FILE).getRoot());
-			exist(wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_BETREFF).getAttachmentList().getAttachment(TEST_FILE_WITH_CONTENT).getRoot());
+			notExist(wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF).getAttachmentList().getAttachment(TEST_FILE).getRoot());
+			exist(wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF).getAttachmentList().getAttachment(TEST_FILE_WITH_CONTENT).getRoot());
 		})
 	})
-})
+
+	describe('switch to wiedervorlage without attachments', () => {
+
+		const WIEDERVORLAGE_WITHOUT_ATTACHMENT_BETREFF: string = 'WiedervorlageZumErledigen';
+
+		it('should not show any attachments', () => {
+			wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITHOUT_ATTACHMENT_BETREFF).getLink().click();
+
+			haveLength(attachmentList.getAttachments(), 0);
+
+			wiedervorlagePage.getSubnavigation().navigateBack();
+		})
+	})
+
+	describe('switch to wiedervorlage with attachments', () => {
+
+		it('should show attachments', () => {
+			wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF).getLink().click();
+
+			haveLength(attachmentList.getAttachments(), 1);
+		})
+	})
+})
\ No newline at end of file
diff --git a/goofy-client/apps/goofy-e2e/src/support/cypress.util.ts b/goofy-client/apps/goofy-e2e/src/support/cypress.util.ts
index 4e79a97e5a..7398b36d34 100644
--- a/goofy-client/apps/goofy-e2e/src/support/cypress.util.ts
+++ b/goofy-client/apps/goofy-e2e/src/support/cypress.util.ts
@@ -42,6 +42,10 @@ export function enterWith(element: any, value: any): void {
 	element.clear().type(value + '{enter}')
 }
 
+export function haveLength(element: any, length: number) {
+	return element.should('have.length', length);
+}
+
 //TODO: "first()" rausnehmen -> im html eine entprechende data-test-id ansprechen?!
 export function shouldFirstContains(element: any, containing: string) {
 	element.first().should('exist').contains(containing);
diff --git a/goofy-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.spec.ts b/goofy-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.spec.ts
index b38f92a9b6..2aa530a886 100644
--- a/goofy-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.spec.ts
+++ b/goofy-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.spec.ts
@@ -32,7 +32,7 @@ describe('KommentarFormService', () => {
 		})
 
 		it('should call createKommentar', () => {
-			formService.source.next(null);
+			formService.source = null;
 
 			formService.submit();
 
@@ -40,7 +40,7 @@ describe('KommentarFormService', () => {
 		})
 
 		it('should call editKommentar', () => {
-			formService.source.next(kommentarResource);
+			formService.source = kommentarResource;
 
 			formService.submit();
 
diff --git a/goofy-client/libs/tech-shared/src/lib/services/formservice.abstract.ts b/goofy-client/libs/tech-shared/src/lib/services/formservice.abstract.ts
index 978357cb58..e9eec1092c 100644
--- a/goofy-client/libs/tech-shared/src/lib/services/formservice.abstract.ts
+++ b/goofy-client/libs/tech-shared/src/lib/services/formservice.abstract.ts
@@ -1,13 +1,13 @@
 import { FormBuilder, FormGroup } from '@angular/forms';
 import { ApiError, hasError, setValidationError, StateResource } from '@goofy-client/tech-shared';
-import { isNull } from 'lodash-es';
-import { BehaviorSubject, Observable } from 'rxjs';
+import { isNil } from 'lodash-es';
+import { Observable } from 'rxjs';
 import { map } from 'rxjs/operators';
 
 export abstract class AbstractFormService {
 	form: FormGroup;
 	pathPrefix: string;
-	source: BehaviorSubject<any> = new BehaviorSubject(null);
+	source: any;
 
 	constructor(public formBuilder: FormBuilder) {
 		this.form = this.initForm();
@@ -33,9 +33,15 @@ export abstract class AbstractFormService {
 		this.form.reset();
 		this.form.patchValue(valueToPatch);
 
-		this.source.next(valueToPatch);
+		this.source = valueToPatch;
+
+		this.doAfterPatch(valueToPatch);
 	}
 
+	doAfterPatch(source: any): void {
+		//No Implementation here for abstract class
+	};
+
 	setError(apiError: ApiError): void {
 		apiError.issues.forEach(issue => setValidationError(this.form, issue, this.getPathPrefix()))
 	}
@@ -46,15 +52,11 @@ export abstract class AbstractFormService {
 		return this.form.value;
 	}
 
-	public getSource(): Observable<any> {
-		return this.source.asObservable();
-	}
-
 	protected getSourceValue(): any {
-		return this.source.value;
+		return this.source;
 	}
 
 	public isPatch(): boolean {
-		return !isNull(this.source.value);
+		return !isNil(this.source);
 	}
 }
\ No newline at end of file
diff --git a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachment-list/wiedervorlage-attachment-list.component.html b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachment-list/wiedervorlage-attachment-list.component.html
index 9a04bb8f11..fe658127d0 100644
--- a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachment-list/wiedervorlage-attachment-list.component.html
+++ b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachment-list/wiedervorlage-attachment-list.component.html
@@ -1,4 +1,4 @@
 <goofy-client-anhang-list-in-wiedervorlage data-test-id="wiedervorlage-attachment-list"
 	[attachments]="attachments$ | async" [deletable]="deletable" 
-	(deleteAttachment)="deleteAttachment($event)">
+	(deleteAttachment)="deleteAttachment.emit($event)">
 </goofy-client-anhang-list-in-wiedervorlage>
\ No newline at end of file
diff --git a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachment-list/wiedervorlage-attachment-list.component.spec.ts b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachment-list/wiedervorlage-attachment-list.component.spec.ts
index fc30c600eb..b9a25106d4 100644
--- a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachment-list/wiedervorlage-attachment-list.component.spec.ts
+++ b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachment-list/wiedervorlage-attachment-list.component.spec.ts
@@ -5,14 +5,14 @@ import { mock } from '@goofy-client/test-utils';
 import { WiedervorlageService } from '@goofy-client/wiedervorlage-shared';
 import { configureTestSuite } from 'ng-bullet';
 import { MockComponent } from 'ng-mocks';
-import { WiedervorlageFormService } from '../wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice';
+import { of } from 'rxjs';
 import { WiedervorlageAttachmentListComponent } from './wiedervorlage-attachment-list.component';
 
 describe('WiedervorlageAttachmentListComponent', () => {
 	let component: WiedervorlageAttachmentListComponent;
 	let fixture: ComponentFixture<WiedervorlageAttachmentListComponent>;
 
-	const wiedervorlageFormService = mock(WiedervorlageService);
+	const wiedervorlageService = { ...mock(WiedervorlageService), getAttachmentList: () => of(null) };
 
 	configureTestSuite(() => {
 		TestBed.configureTestingModule({
@@ -23,8 +23,8 @@ describe('WiedervorlageAttachmentListComponent', () => {
 			],
 			providers: [
 				{
-					provide: WiedervorlageFormService,
-					useValue: wiedervorlageFormService
+					provide: WiedervorlageService,
+					useValue: wiedervorlageService
 				}
 			]
 		})
diff --git a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachment-list/wiedervorlage-attachment-list.component.ts b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachment-list/wiedervorlage-attachment-list.component.ts
index eb94a697ae..1c99d67139 100644
--- a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachment-list/wiedervorlage-attachment-list.component.ts
+++ b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachment-list/wiedervorlage-attachment-list.component.ts
@@ -1,9 +1,10 @@
-import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
+import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
 import { OzgFileListLinkRel, OzgFileResource } from '@goofy-client/ozg-file-shared';
-import { WiedervorlageResource } from '@goofy-client/wiedervorlage-shared';
+import { WiedervorlageResource, WiedervorlageService } from '@goofy-client/wiedervorlage-shared';
+import { getEmbeddedResource } from '@ngxp/rest';
 import { isNil } from 'lodash-es';
 import { Observable, of } from 'rxjs';
-import { WiedervorlageFormService } from '../wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice';
+import { map } from 'rxjs/operators';
 
 @Component({
 	selector: 'goofy-client-wiedervorlage-attachment-list',
@@ -15,23 +16,25 @@ export class WiedervorlageAttachmentListComponent implements OnChanges {
 	@Input() wiedervorlage: WiedervorlageResource;
 	@Input() deletable: boolean;
 
+	@Output() deleteAttachment: EventEmitter<OzgFileResource> = new EventEmitter();
+
 	readonly fileListRel = OzgFileListLinkRel;
 
 	attachments$: Observable<OzgFileResource[]> = of([]);
 
-	constructor(public formService: WiedervorlageFormService) { }
+	constructor(public service: WiedervorlageService) { }
 
 	ngOnChanges(changes: SimpleChanges): void {
-		if (changes.wiedervorlage) {
-			this.attachments$ = this.formService.getAttachments();
-
-			if (!isNil(this.wiedervorlage)) {
-				this.formService.patch(this.wiedervorlage);
-			}
+		if (changes.wiedervorlage && !isNil(this.wiedervorlage)) {
+			this.updateAttachments();
 		}
 	}
 
-	deleteAttachment(attachment: OzgFileResource): void {
-		this.formService.deleteAttachment(attachment);
+	updateAttachments() {
+		this.attachments$ = this.service.getAttachmentList(this.wiedervorlage).pipe(map(list => {
+			return list.resource
+				? getEmbeddedResource<OzgFileResource[]>(list.resource, OzgFileListLinkRel.FILE_LIST)
+				: [];
+		}))
 	}
 }
\ No newline at end of file
diff --git a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachments/wiedervorlage-attachments.component.html b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachments/wiedervorlage-attachments.component.html
index 80268c836a..1efc5f41b0 100644
--- a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachments/wiedervorlage-attachments.component.html
+++ b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachments/wiedervorlage-attachments.component.html
@@ -1,4 +1,7 @@
-<goofy-client-wiedervorlage-attachment-list [wiedervorlage]="wiedervorlage" [deletable]="true"></goofy-client-wiedervorlage-attachment-list>
+<goofy-client-anhang-list-in-wiedervorlage data-test-id="wiedervorlage-attachment-list"
+	[attachments]="attachments$ | async" [deletable]="true" 
+	(deleteAttachment)="deleteAttachment($event)">
+</goofy-client-anhang-list-in-wiedervorlage>
 
 <goofy-client-spinner [stateResource]="uploadInProgress$ | async">
 	<goofy-client-file-upload (fileChanged)="uploadFile($event)" data-test-id="wiedervorlage-file-upload"></goofy-client-file-upload>
diff --git a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachments/wiedervorlage-attachments.component.spec.ts b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachments/wiedervorlage-attachments.component.spec.ts
index 57e476e49c..519b49edba 100644
--- a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachments/wiedervorlage-attachments.component.spec.ts
+++ b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachments/wiedervorlage-attachments.component.spec.ts
@@ -1,11 +1,14 @@
 import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { AnhaengeComponent } from '@goofy-client/ozg-file';
-import { HasLinkPipe } from '@goofy-client/tech-shared';
+import { AnhaengeComponent, AnhangListInWiedervorlageComponent } from '@goofy-client/ozg-file';
+import { OzgFileResource } from '@goofy-client/ozg-file-shared';
+import { createEmptyStateResource, createStateResource, HasLinkPipe } from '@goofy-client/tech-shared';
 import { mock } from '@goofy-client/test-utils';
 import { FileUploadComponent, SpinnerComponent } from '@goofy-client/ui';
 import { WiedervorlageService } from '@goofy-client/wiedervorlage-shared';
+import { createOzgFileResource } from 'libs/ozg-file-shared/test/ozg-file';
 import { configureTestSuite } from 'ng-bullet';
 import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
 import { WiedervorlageAttachmentListComponent } from '../wiedervorlage-attachment-list/wiedervorlage-attachment-list.component';
 import { WiedervorlageFormService } from '../wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice';
 import { WiedervorlageAttachmentsComponent } from './wiedervorlage-attachments.component';
@@ -14,8 +17,10 @@ describe('WiedervorlageAttachmentsComponent', () => {
 	let component: WiedervorlageAttachmentsComponent;
 	let fixture: ComponentFixture<WiedervorlageAttachmentsComponent>;
 
-	const wiedervorlageFormService = mock(WiedervorlageFormService);
-	const wiedervorlageService = mock(WiedervorlageService);
+	const formService = mock(WiedervorlageFormService);
+	const service = mock(WiedervorlageService);
+
+	const file: OzgFileResource = createOzgFileResource();
 
 	configureTestSuite(() => {
 		TestBed.configureTestingModule({
@@ -25,16 +30,17 @@ describe('WiedervorlageAttachmentsComponent', () => {
 				MockComponent(WiedervorlageAttachmentListComponent),
 				MockComponent(SpinnerComponent),
 				MockComponent(AnhaengeComponent),
-				MockComponent(FileUploadComponent)
+				MockComponent(FileUploadComponent),
+				MockComponent(AnhangListInWiedervorlageComponent)
 			],
 			providers: [
 				{
 					provide: WiedervorlageFormService,
-					useValue: wiedervorlageFormService
+					useValue: formService
 				},
 				{
 					provide: WiedervorlageService,
-					useValue: wiedervorlageService
+					useValue: service
 				}
 			]
 		})
@@ -49,4 +55,57 @@ describe('WiedervorlageAttachmentsComponent', () => {
 	it('should create', () => {
 		expect(component).toBeTruthy();
 	});
+
+	describe('upload file', () => {
+
+		const file: File = <any>{ name: 'TestDatei' };
+		const ozgFile: OzgFileResource = createOzgFileResource();
+
+		beforeEach(() => {
+			service.uploadFile.mockReturnValue(of(createStateResource(ozgFile)));
+		})
+
+		it('should call service', () => {
+			component.uploadFile(<any>file)
+
+			expect(service.uploadFile).toHaveBeenCalledWith(file);
+		})
+
+		describe('do after upload', () => {
+
+			beforeEach(() => {
+				component.addAttachment = jest.fn();
+			})
+
+			it('should emit file after successfull upload', () => {
+				component.doAfterFileUpload(createStateResource(ozgFile));
+
+				expect(component.addAttachment).toHaveBeenCalledWith(ozgFile);
+			})
+
+			it('should not emit file while stateResource is null', () => {
+				component.doAfterFileUpload(createEmptyStateResource());
+
+				expect(component.addAttachment).not.toHaveBeenCalled();
+			})
+		})
+	})
+
+	describe('delete attachment', () => {
+
+		it('should call form service', () => {
+			component.deleteAttachment(file);
+
+			expect(formService.deleteAttachment).toHaveBeenCalledWith(file);
+		})
+	})
+
+	describe('add attachment', () => {
+
+		it('should call form service', () => {
+			component.addAttachment(file);
+
+			expect(formService.addAttachment).toHaveBeenCalledWith(file);
+		})
+	})
 });
\ No newline at end of file
diff --git a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachments/wiedervorlage-attachments.component.ts b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachments/wiedervorlage-attachments.component.ts
index 3df63750a2..e9b4ac9d85 100644
--- a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachments/wiedervorlage-attachments.component.ts
+++ b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-attachments/wiedervorlage-attachments.component.ts
@@ -1,7 +1,8 @@
-import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
 import { OzgFileResource } from '@goofy-client/ozg-file-shared';
 import { createEmptyStateResource, StateResource } from '@goofy-client/tech-shared';
 import { WiedervorlageLinkRel, WiedervorlageResource, WiedervorlageService } from '@goofy-client/wiedervorlage-shared';
+import { isNull } from 'lodash-es';
 import { Observable, of } from 'rxjs';
 import { tap } from 'rxjs/operators';
 import { WiedervorlageFormService } from '../wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice';
@@ -19,19 +20,29 @@ export class WiedervorlageAttachmentsComponent {
 
 	readonly linkRel = WiedervorlageLinkRel;
 
+	attachments$: Observable<OzgFileResource[]> = of([]);
 	uploadInProgress$: Observable<StateResource<any>> = of(createEmptyStateResource());
 
-	constructor(public formService: WiedervorlageFormService, private changeDetector: ChangeDetectorRef, private wiedervorlageService: WiedervorlageService) { }
+	constructor(public formService: WiedervorlageFormService, private wiedervorlageService: WiedervorlageService) {
+		this.attachments$ = this.formService.getAttachments();
+	}
 
 	uploadFile(file: File): void {
 		this.uploadInProgress$ = this.wiedervorlageService.uploadFile(file).pipe(
 			tap((stateResource: StateResource<OzgFileResource>) => this.doAfterFileUpload(stateResource)));
 	}
 
-	private doAfterFileUpload(stateResource: StateResource<OzgFileResource>): void {
-		if (stateResource.loaded) {
-			this.formService.addAttachment(stateResource.resource);
-			this.changeDetector.detectChanges();
+	doAfterFileUpload(stateResource: StateResource<OzgFileResource>): void {
+		if (stateResource.loaded && !isNull(stateResource.resource)) {
+			this.addAttachment(stateResource.resource);
 		}
 	}
+
+	addAttachment(ozgFile: OzgFileResource) {
+		this.formService.addAttachment(ozgFile);
+	}
+
+	deleteAttachment(ozgFile: OzgFileResource) {
+		this.formService.deleteAttachment(ozgFile);
+	}
 }
\ No newline at end of file
diff --git a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.spec.ts b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.spec.ts
index 32348d4d09..72dbe1ac97 100644
--- a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.spec.ts
+++ b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.spec.ts
@@ -20,7 +20,7 @@ describe('WiedervorlageFormComponent', () => {
 	let component: WiedervorlageFormComponent;
 	let fixture: ComponentFixture<WiedervorlageFormComponent>;
 
-	const wiedervorlageFormService = new WiedervorlageFormService(new FormBuilder(), useFromMock(mock(WiedervorlageService)));
+	const formService = new WiedervorlageFormService(new FormBuilder(), useFromMock(mock(WiedervorlageService)));
 	const wiedervorlage: WiedervorlageResource = createWiedervorlageResource();
 
 	configureTestSuite(() => {
@@ -42,14 +42,14 @@ describe('WiedervorlageFormComponent', () => {
 			providers: [
 				{
 					provide: WiedervorlageFormService,
-					useValue: wiedervorlageFormService
+					useValue: formService
 				}
 			]
 		})
 	});
 
 	beforeEach(() => {
-		wiedervorlageFormService.patch = jest.fn();
+		formService.patch = jest.fn();
 
 		fixture = TestBed.createComponent(WiedervorlageFormComponent);
 		component = fixture.componentInstance;
@@ -60,14 +60,14 @@ describe('WiedervorlageFormComponent', () => {
 		expect(component).toBeTruthy();
 	});
 
-	describe('pathWiedervorlage', () => {
+	describe('patch wiedervorlage', () => {
 
 		it('should NOT patch by formservice', () => {
 			component.wiedervorlage = null;
 
 			component.patchWiedervorlage();
 
-			expect(wiedervorlageFormService.patch).not.toHaveBeenCalled();
+			expect(formService.patch).not.toHaveBeenCalled();
 		})
 
 		it('should patch by formservice', () => {
@@ -75,7 +75,7 @@ describe('WiedervorlageFormComponent', () => {
 
 			component.patchWiedervorlage();
 
-			expect(wiedervorlageFormService.patch).toHaveBeenCalledWith(wiedervorlage);
+			expect(formService.patch).toHaveBeenCalledWith(wiedervorlage);
 		})
 	})
 });
diff --git a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.spec.ts b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.spec.ts
index 5246232ba1..bd207c2d8c 100644
--- a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.spec.ts
+++ b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.spec.ts
@@ -38,7 +38,7 @@ describe('WiedervorlageFormService', () => {
 		})
 
 		it('should call createWiedervorlage', () => {
-			formService.source.next(null);
+			formService.source = null;
 
 			formService.submit();
 
@@ -46,7 +46,7 @@ describe('WiedervorlageFormService', () => {
 		})
 
 		it('should call saveWiedervorlage', () => {
-			formService.source.next(wiedervorlageResource);
+			formService.source = wiedervorlageResource;
 
 			formService.submit();
 
diff --git a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts
index 822955565a..89d26e6516 100644
--- a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts
+++ b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts
@@ -6,6 +6,7 @@ import { Wiedervorlage, WiedervorlageLinkRel, WiedervorlageResource, Wiedervorla
 import { getEmbeddedResource, getUrl, hasLink } from '@ngxp/rest';
 import { isNil, isNull } from 'lodash-es';
 import { BehaviorSubject, Observable, Subscription } from 'rxjs';
+import { tap } from 'rxjs/operators';
 
 @Injectable()
 export class WiedervorlageFormService extends AbstractFormService implements OnDestroy {
@@ -18,26 +19,24 @@ export class WiedervorlageFormService extends AbstractFormService implements OnD
 
 	private attachments: BehaviorSubject<OzgFileResource[]> = new BehaviorSubject([]);
 	private attachmentSubscription: Subscription;
-	private sourceSubscription: Subscription;
 
 	constructor(
 		formBuilder: FormBuilder,
 		private wiedervorlageService: WiedervorlageService
 	) {
 		super(formBuilder);
-
-		this.subscribeToSource();
 	}
 
-	private subscribeToSource(): void {
-		if (!isNil(this.sourceSubscription)) this.sourceSubscription.unsubscribe();
-		this.sourceSubscription = this.getSource().subscribe((wiedervorlage: WiedervorlageResource) => this.handleSourceChange(wiedervorlage))
-	}
+	doAfterPatch(wiedervorlage: WiedervorlageResource): void {
+		if (!isNil(this.attachmentSubscription)) this.attachmentSubscription.unsubscribe();
+		console.info('do after patch');
 
-	handleSourceChange(wiedervorlage: WiedervorlageResource): void {
-		this.hasAttachments(wiedervorlage)
-			? this.subscribeToAttachments(wiedervorlage)
-			: this.attachments.next([]);
+		if (this.hasAttachments(wiedervorlage)) {
+			this.subscribeToAttachments(wiedervorlage);
+		} else {
+			console.info('update attachments to []');
+			this.attachments.next([]);
+		}
 	}
 
 	private hasAttachments(wiedervorlage: WiedervorlageResource): boolean {
@@ -45,14 +44,14 @@ export class WiedervorlageFormService extends AbstractFormService implements OnD
 	}
 
 	private subscribeToAttachments(wiedervorlage: WiedervorlageResource): void {
-		if (!isNil(this.attachmentSubscription)) this.attachmentSubscription.unsubscribe();
 		this.attachmentSubscription = this.wiedervorlageService.getAttachmentList(wiedervorlage).subscribe(attachmentsList => this.handleAttachmentList(attachmentsList));
 	}
 
 	handleAttachmentList(attachmentsList: StateResource<OzgFileListResource>): void {
-		attachmentsList.resource
-			? this.attachments.next(getEmbeddedResource<OzgFileResource[]>(attachmentsList.resource, OzgFileListLinkRel.FILE_LIST))
-			: this.attachments.next([]);
+		if (attachmentsList.resource) {
+			console.info('update attachments to existing');
+			this.attachments.next(getEmbeddedResource<OzgFileResource[]>(attachmentsList.resource, OzgFileListLinkRel.FILE_LIST));
+		}
 	}
 
 	protected initForm(): FormGroup {
@@ -81,18 +80,20 @@ export class WiedervorlageFormService extends AbstractFormService implements OnD
 	}
 
 	public getAttachments(): Observable<OzgFileResource[]> {
-		return this.attachments.asObservable();
+		return this.attachments.asObservable().pipe(tap(attachments => console.info('fire with: ', attachments)));
 	}
 
 	public addAttachment(attachment: OzgFileResource): void {
 		let attachments = this.attachments.value;
 		attachments.push(attachment);
+		console.info('update attachment: add: ', attachment);
 		this.attachments.next(attachments);
 	}
 
 	public deleteAttachment(attachment: OzgFileResource): void {
 		let attachments = this.attachments.value;
 		attachments.splice(attachments.indexOf(attachment), 1);
+		console.info('update attachment: delete: ', attachment);
 		this.attachments.next(attachments);
 	}
 
@@ -101,7 +102,6 @@ export class WiedervorlageFormService extends AbstractFormService implements OnD
 	}
 
 	unsubscribe(): void {
-		if (!isNil(this.sourceSubscription)) this.sourceSubscription.unsubscribe();
 		if (!isNil(this.attachmentSubscription)) this.attachmentSubscription.unsubscribe();
 	}
 }
\ No newline at end of file
-- 
GitLab