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

OZG-5977 WIP add multi upload in Kommentare

parent c2a670b5
No related branches found
No related tags found
1 merge request!67OZG-5977 add multi option to file upload button
Showing
with 521 additions and 72 deletions
...@@ -21,38 +21,16 @@ ...@@ -21,38 +21,16 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen * Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen. * unter der Lizenz sind dem Lizenztext zu entnehmen.
*/ */
import { import { BlobWithFileName, createEmptyStateResource, createErrorStateResource, createStateResource, EMPTY_STRING, getMessageForInvalidParam, HttpError, HttpHeader, isNotNil, isUnprocessableEntity, isValidationFieldFileSizeExceedError, sanitizeFileName, StateResource, } from '@alfa-client/tech-shared';
BlobWithFileName,
createEmptyStateResource,
createErrorStateResource,
createStateResource,
EMPTY_STRING,
getMessageForInvalidParam,
HttpError,
HttpHeader,
isNotNil,
isUnprocessableEntity,
isValidationFieldFileSizeExceedError,
sanitizeFileName,
StateResource,
} from '@alfa-client/tech-shared';
import { SnackBarService } from '@alfa-client/ui'; import { SnackBarService } from '@alfa-client/ui';
import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { getUrl, Resource, ResourceUri } from '@ngxp/rest'; import { getUrl, Resource, ResourceUri } from '@ngxp/rest';
import { randomUUID } from 'crypto';
import { saveAs } from 'file-saver'; import { saveAs } from 'file-saver';
import { isNil } from 'lodash-es'; import { isNil } from 'lodash-es';
import { BehaviorSubject, forkJoin, Observable, of, throwError } from 'rxjs'; import { BehaviorSubject, forkJoin, Observable, of, throwError } from 'rxjs';
import { catchError, map, mergeMap, startWith, switchMap } from 'rxjs/operators'; import { catchError, map, mergeMap, startWith, switchMap } from 'rxjs/operators';
import { import { BinaryFileListResource, BinaryFileResource, FileUploadType, ToUploadFile, UploadFile, UploadFilesByType, } from './binary-file.model';
BinaryFileListResource,
BinaryFileResource,
FileUploadType,
ToUploadFile,
UploadFile,
UploadFilesByType,
} from './binary-file.model';
import { BinaryFileRepository } from './binary-file.repository'; import { BinaryFileRepository } from './binary-file.repository';
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
...@@ -89,7 +67,7 @@ export class BinaryFileService { ...@@ -89,7 +67,7 @@ export class BinaryFileService {
_buildUploadFile(toUploadFile: ToUploadFile): UploadFile { _buildUploadFile(toUploadFile: ToUploadFile): UploadFile {
return { return {
key: randomUUID(), key: crypto.randomUUID(),
fileToUpload: toUploadFile.file, fileToUpload: toUploadFile.file,
uploadedFile: this._handleUpload(toUploadFile), uploadedFile: this._handleUpload(toUploadFile),
}; };
......
...@@ -22,21 +22,15 @@ ...@@ -22,21 +22,15 @@
* unter der Lizenz sind dem Lizenztext zu entnehmen. * unter der Lizenz sind dem Lizenztext zu entnehmen.
*/ */
import { BinaryFileModule } from '@alfa-client/binary-file'; import { BinaryFileModule } from '@alfa-client/binary-file';
import { BinaryFileResource, BinaryFileService, FileUploadType } from '@alfa-client/binary-file-shared'; import { BinaryFileService, FileUploadType } from '@alfa-client/binary-file-shared';
import { StateResource, TechSharedModule } from '@alfa-client/tech-shared'; import { TechSharedModule } from '@alfa-client/tech-shared';
import { Component, HostListener, inject, Input } from '@angular/core'; import { Component, HostListener, inject, Input } from '@angular/core';
import { ControlContainer, FormGroupDirective, ReactiveFormsModule } from '@angular/forms'; import { ControlContainer, FormGroupDirective, ReactiveFormsModule } from '@angular/forms';
import { getUrl, Resource } from '@ngxp/rest'; import { getUrl, Resource } from '@ngxp/rest';
import { AttachmentIconComponent, FileUploadButtonComponent, SpinnerIconComponent } from '@ods/system'; import { AttachmentIconComponent, FileUploadButtonComponent, SpinnerIconComponent } from '@ods/system';
import { uniqueId } from 'lodash-es'; import { uniqueId } from 'lodash-es';
import { Observable } from 'rxjs';
import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component'; import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component';
export interface MultiUploadItem {
file?: File;
uploadStateResource: Observable<StateResource<BinaryFileResource>>;
}
@Component({ @Component({
selector: 'ods-multi-file-upload-editor', selector: 'ods-multi-file-upload-editor',
templateUrl: './multi-file-upload-editor.component.html', templateUrl: './multi-file-upload-editor.component.html',
......
<ods-multi-file-upload-list
[uploadedFiles]="uploadedFiles$ | async"
[parentFormArrayName]="parentFormArrayName"
[listOrientation]="listOrientation"
(delete)="onDelete($event)"
></ods-multi-file-upload-list>
import { BinaryFileService, UploadFile } from '@alfa-client/binary-file-shared';
import { mock, Mock } from '@alfa-client/test-utils';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { expect } from '@jest/globals';
import { MockComponent } from 'ng-mocks';
import { createUploadFile } from '../../../../../binary-file-shared/test/binary-file';
import { singleColdCompleted } from '../../../../../tech-shared/test/marbles';
import {
MultiFileUploadListContainerComponent,
MultiFileUploadListOrientation,
} from './multi-file-upload-list-container.component';
import { MultiFileUploadListComponent } from './multi-file-upload-list/multi-file-upload-list.component';
describe('MultiFileUploadListContainerComponent', () => {
let component: MultiFileUploadListContainerComponent;
let fixture: ComponentFixture<MultiFileUploadListContainerComponent>;
let binaryFileService: Mock<BinaryFileService>;
beforeEach(() => {
binaryFileService = mock(BinaryFileService);
});
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MultiFileUploadListContainerComponent],
declarations: [MockComponent(MultiFileUploadListComponent)],
providers: [{ provide: BinaryFileService, useValue: binaryFileService }],
}).compileComponents();
fixture = TestBed.createComponent(MultiFileUploadListContainerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
describe('component', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
it('should have default value', () => {
expect(component.listOrientation).toEqual(MultiFileUploadListOrientation.HORIZONTAL);
});
describe('ngOnInit', () => {
it('should get uploaded files', () => {
component.ngOnInit();
expect(binaryFileService.getUploadedFiles).toHaveBeenCalledWith(component.fileUploadType);
});
it('should set uploaded files', () => {
const uploadFile: UploadFile = createUploadFile();
binaryFileService.getUploadedFiles = jest.fn().mockReturnValue(singleColdCompleted(uploadFile));
component.ngOnInit();
expect(component.uploadedFiles$).toBeObservable(singleColdCompleted(uploadFile));
});
});
});
});
import { BinaryFileService, UploadFile } from '@alfa-client/binary-file-shared';
import { AsyncPipe } from '@angular/common';
import { Component, inject, Input, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { MultiFileUploadListComponent } from './multi-file-upload-list/multi-file-upload-list.component';
export enum MultiFileUploadListOrientation {
HORIZONTAL = 'horizontal',
VERTICAL = 'vertical',
}
@Component({
selector: 'ods-multi-file-upload-list-container',
standalone: true,
templateUrl: './multi-file-upload-list-container.component.html',
imports: [MultiFileUploadListComponent, AsyncPipe],
})
export class MultiFileUploadListContainerComponent implements OnInit {
@Input() fileUploadType: string;
@Input() parentFormArrayName: string;
@Input() listOrientation: MultiFileUploadListOrientation = MultiFileUploadListOrientation.HORIZONTAL;
private readonly binaryFileService: BinaryFileService = inject(BinaryFileService);
public uploadedFiles$: Observable<UploadFile[]>;
ngOnInit(): void {
this.uploadedFiles$ = this.binaryFileService.getUploadedFiles(this.fileUploadType);
}
public onDelete(key: string): void {
this.binaryFileService.deleteUploadedFile(this.fileUploadType, key);
}
}
@if (uploadStateResource.loading || uploadStateResource.error) {
<ods-attachment
[loadingCaption]="file.name"
errorCaption="Fehler beim Hochladen"
[errorMessages]="uploadStateResource.error | convertProblemDetailToErrorMessages"
description="Anhang wird hochgeladen"
[isLoading]="uploadStateResource.loading"
data-test-id="multi-file-upload-list-item-attachment-upload"
></ods-attachment>
} @else if (uploadStateResource.resource) {
<ods-attachment-wrapper>
<alfa-binary-file2-container
[file]="uploadStateResource.resource"
[deletable]="true"
(startDelete)="onDelete($event)"
data-test-id="multi-file-upload-list-item-uploaded"
>
</alfa-binary-file2-container>
</ods-attachment-wrapper>
}
import { BinaryFileResource } from '@alfa-client/binary-file-shared';
import { createEmptyStateResource, createErrorStateResource, createStateResource } from '@alfa-client/tech-shared';
import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { expect } from '@jest/globals';
import {
createBinaryFileResource,
createLoadingBinaryFileStateResource,
} from '../../../../../../binary-file-shared/test/binary-file';
import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
import { createProblemDetail } from '../../../../../../tech-shared/test/error';
import { createFile } from '../../../../../../tech-shared/test/file';
import { MultiFileUploadListItemComponent } from './multi-file-upload-list-item.component';
describe('MultiFileUploadListItemComponent', () => {
let component: MultiFileUploadListItemComponent;
let fixture: ComponentFixture<MultiFileUploadListItemComponent>;
const attachmentTestId: string = getDataTestIdOf('multi-file-upload-list-item-attachment-upload');
const binaryFileContainerTestId: string = getDataTestIdOf('multi-file-upload-list-item-uploaded');
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MultiFileUploadListItemComponent],
// declarations: [MockComponent(BinaryFile2ContainerComponent)],
}).compileComponents();
fixture = TestBed.createComponent(MultiFileUploadListItemComponent);
component = fixture.componentInstance;
component.uploadStateResource = createEmptyStateResource();
fixture.detectChanges();
});
describe('component', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
describe('onDelete', () => {
beforeEach(() => {
component.delete.emit = jest.fn();
});
it('should emit', () => {
component.key = 'test';
const binaryFileResource: BinaryFileResource = createBinaryFileResource();
component.onDelete(binaryFileResource);
expect(component.delete.emit).toHaveBeenCalledWith({ key: component.key, binaryFileResource });
});
});
});
// TODO: testing standalone components with mocked components
xdescribe('template', () => {
const file: File = createFile();
beforeEach(() => {
component.file = file;
});
describe('attachment upload', () => {
it('should exists on loading', () => {
component.uploadStateResource = createLoadingBinaryFileStateResource();
fixture.detectChanges();
existsAsHtmlElement(fixture, attachmentTestId);
});
it('should exists on error', () => {
component.uploadStateResource = createErrorStateResource(createProblemDetail());
fixture.detectChanges();
existsAsHtmlElement(fixture, attachmentTestId);
});
it('should not exists on loaded', () => {
component.uploadStateResource = createStateResource(createBinaryFileResource());
fixture.detectChanges();
notExistsAsHtmlElement(fixture, attachmentTestId);
});
});
});
});
import { BinaryFileModule } from '@alfa-client/binary-file';
import { BinaryFileResource } from '@alfa-client/binary-file-shared';
import { StateResource, TechSharedModule } from '@alfa-client/tech-shared';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { AttachmentComponent, AttachmentWrapperComponent } from '@ods/system';
export interface FileToDelete {
key: string;
binaryFileResource: BinaryFileResource;
}
@Component({
selector: 'ods-multi-file-upload-list-item',
standalone: true,
templateUrl: './multi-file-upload-list-item.component.html',
imports: [AttachmentComponent, AttachmentWrapperComponent, TechSharedModule, BinaryFileModule],
})
export class MultiFileUploadListItemComponent {
@Input() uploadStateResource: StateResource<BinaryFileResource>;
@Input() file: File;
@Input() key: string;
@Output() delete: EventEmitter<FileToDelete> = new EventEmitter();
public onDelete(binaryFileResource: BinaryFileResource): void {
this.delete.emit({ key: this.key, binaryFileResource });
}
}
<div [class]="listOrientationClasses">
@for (uploadItem of uploadItems; track uploadItem.key) {
<ods-multi-file-upload-list-item
[key]="uploadItem.key"
[uploadStateResource]="uploadItem.uploadedFile | async"
[file]="uploadItem.fileToUpload"
(delete)="onDelete($event)"
></ods-multi-file-upload-list-item>
}
</div>
import { BinaryFileResource, UploadFile } from '@alfa-client/binary-file-shared';
import { createEmptyStateResource, createErrorStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormGroupDirective, ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';
import { expect } from '@jest/globals';
import { getUrl } from '@ngxp/rest';
import { MockComponent } from 'ng-mocks';
import { of } from 'rxjs';
import { createBinaryFileResource, createUploadFile } from '../../../../../../binary-file-shared/test/binary-file';
import { createProblemDetail } from '../../../../../../tech-shared/test/error';
import { MultiFileUploadListOrientation } from '../multi-file-upload-list-container.component';
import { MultiFileUploadListItemComponent } from '../multi-file-upload-list-item/multi-file-upload-list-item.component';
import { MultiFileUploadListComponent } from './multi-file-upload-list.component';
describe('MultiFileUploadListComponent', () => {
let component: MultiFileUploadListComponent;
let fixture: ComponentFixture<MultiFileUploadListComponent>;
const fb = new UntypedFormBuilder();
const formGroupDirective = new FormGroupDirective([], []);
formGroupDirective.form = fb.group({
attachments: fb.control(null),
});
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MultiFileUploadListComponent, ReactiveFormsModule],
declarations: [MockComponent(MultiFileUploadListItemComponent)],
providers: [
{
provide: FormGroupDirective,
useValue: formGroupDirective,
},
],
}).compileComponents();
fixture = TestBed.createComponent(MultiFileUploadListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
describe('component', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
describe('set list orientation', () => {
it('should update class', () => {
component._updateListOrientationClass = jest.fn();
component.listOrientation = MultiFileUploadListOrientation.VERTICAL;
expect(component._updateListOrientationClass).toHaveBeenCalledWith(MultiFileUploadListOrientation.VERTICAL);
});
});
describe('set uploaded files', () => {
it('should update upload items', () => {
component._updateUploadItems = jest.fn();
const uploadedFiles: UploadFile[] = [createUploadFile()];
component.uploadedFiles = uploadedFiles;
expect(component._updateUploadItems).toHaveBeenCalledWith(uploadedFiles);
});
});
describe('ngOnInit', () => {
it('should set file link controls', () => {
component.parentFormArrayName = 'attachments';
component.ngOnInit();
expect(component._fileLinkControls).toEqual(formGroupDirective.form.get('attachments'));
});
});
describe('_updateUploadItems', () => {
beforeEach(() => {
component._addFileUrl = jest.fn();
});
it('should set upload items', () => {
const uploadFiles: UploadFile[] = [createUploadFile()];
component._updateUploadItems(uploadFiles);
expect(component.uploadItems).toEqual(uploadFiles);
});
it('should add file url on successful upload', () => {
const uploadStateResource: StateResource<BinaryFileResource> = createStateResource(createBinaryFileResource());
const uploadFiles: UploadFile[] = [{ ...createUploadFile(), uploadedFile: of(uploadStateResource) }];
component._updateUploadItems(uploadFiles);
component.uploadItems[0].uploadedFile.subscribe();
expect(component._addFileUrl).toHaveBeenCalledWith(uploadStateResource.resource);
});
it('should NOT add file url on loading', () => {
const uploadStateResource: StateResource<BinaryFileResource> = createEmptyStateResource(true);
const uploadFiles: UploadFile[] = [{ ...createUploadFile(), uploadedFile: of(uploadStateResource) }];
component._updateUploadItems(uploadFiles);
component.uploadItems[0].uploadedFile.subscribe();
expect(component._addFileUrl).not.toHaveBeenCalled();
});
it('should NOT add file url on error', () => {
const uploadStateResource: StateResource<BinaryFileResource> = createErrorStateResource(createProblemDetail());
const uploadFiles: UploadFile[] = [{ ...createUploadFile(), uploadedFile: of(uploadStateResource) }];
component._updateUploadItems(uploadFiles);
component.uploadItems[0].uploadedFile.subscribe();
expect(component._addFileUrl).not.toHaveBeenCalled();
});
});
describe('_addFileUrl', () => {
beforeEach(() => {
component._updateForm = jest.fn();
});
it('should add file url', () => {
const binaryFileResource: BinaryFileResource = createBinaryFileResource();
component._addFileUrl(binaryFileResource);
expect(component._fileUrls).toEqual([getUrl(binaryFileResource)]);
});
it('should update form', () => {});
});
});
});
import { BinaryFileModule } from '@alfa-client/binary-file';
import { BinaryFileResource, UploadFile } from '@alfa-client/binary-file-shared';
import { doOnValidStateResource, StateResource, TechSharedModule } from '@alfa-client/tech-shared';
import { AsyncPipe } from '@angular/common';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormGroupDirective, UntypedFormArray, UntypedFormControl } from '@angular/forms';
import { getUrl } from '@ngxp/rest';
import { tap } from 'rxjs';
import { MultiFileUploadListOrientation } from '../multi-file-upload-list-container.component';
import {
FileToDelete,
MultiFileUploadListItemComponent,
} from '../multi-file-upload-list-item/multi-file-upload-list-item.component';
const verticalClasses: string = 'flex flex-col';
const horizontalClasses: string = 'flex flex-row flex-wrap';
@Component({
selector: 'ods-multi-file-upload-list',
standalone: true,
templateUrl: './multi-file-upload-list.component.html',
imports: [AsyncPipe, TechSharedModule, BinaryFileModule, MultiFileUploadListItemComponent],
})
export class MultiFileUploadListComponent implements OnInit {
@Input() parentFormArrayName: string;
@Input() set listOrientation(value: MultiFileUploadListOrientation) {
this._updateListOrientationClass(value);
}
@Input() set uploadedFiles(value: UploadFile[]) {
this._updateUploadItems(value);
}
@Output() delete: EventEmitter<string> = new EventEmitter();
public uploadItems: UploadFile[];
public listOrientationClasses: string = 'flex flex-row';
_fileLinkControls: UntypedFormArray = new UntypedFormArray([]);
_fileUrls: string[] = [];
constructor(public parentForm: FormGroupDirective) {}
ngOnInit(): void {
this._fileLinkControls = this.parentForm.form.get(this.parentFormArrayName) as UntypedFormArray;
}
_updateUploadItems(uploadFiles: UploadFile[]): void {
this.uploadItems = uploadFiles;
this.uploadItems.forEach((item) => {
item.uploadedFile = item.uploadedFile.pipe(
tap((stateResource: StateResource<BinaryFileResource>) =>
doOnValidStateResource(stateResource, () => this._addFileUrl(stateResource.resource)),
),
);
});
}
_addFileUrl(binaryFileResource: BinaryFileResource): void {
this._fileUrls = [...this._fileUrls, getUrl(binaryFileResource)];
this._updateForm(this._fileUrls);
}
_updateForm(fileUrls: string[]): void {
this._fileLinkControls.clear();
fileUrls.forEach((link: string) => this._fileLinkControls.push(new UntypedFormControl(link)));
}
_updateListOrientationClass(listOrientation: MultiFileUploadListOrientation): void {
switch (listOrientation) {
case MultiFileUploadListOrientation.VERTICAL:
this.listOrientationClasses = verticalClasses;
break;
case MultiFileUploadListOrientation.HORIZONTAL:
this.listOrientationClasses = horizontalClasses;
break;
default:
this.listOrientationClasses = horizontalClasses;
break;
}
}
public onDelete(fileToDelete: FileToDelete): void {
this._fileUrls = this._fileUrls.filter((url: string) => url !== getUrl(fileToDelete.binaryFileResource));
this.delete.emit(fileToDelete.key);
}
}
...@@ -32,4 +32,7 @@ export interface Kommentar { ...@@ -32,4 +32,7 @@ export interface Kommentar {
} }
export interface KommentarResource extends Kommentar, Resource {} export interface KommentarResource extends Kommentar, Resource {}
export interface KommentarListResource extends ListResource {} export interface KommentarListResource extends ListResource {}
export const KOMMENTAR_UPLOADED_ATTACHMENTS = 'kommentar_uploaded_attachments';
...@@ -24,21 +24,18 @@ ...@@ -24,21 +24,18 @@
--> -->
<form class="form" [formGroup]="formService.form"> <form class="form" [formGroup]="formService.form">
<ozgcloud-textarea-editor <ozgcloud-textarea-editor [formControlName]="formServiceClass.TEXT" label="Kommentar" [required]="true">
[formControlName]="formServiceClass.TEXT"
label="Kommentar"
[required]="true"
>
</ozgcloud-textarea-editor> </ozgcloud-textarea-editor>
<alfa-binary-file-attachment-container <ods-multi-file-upload-list-container
data-test-id="kommentar-attachment-list" [parentFormArrayName]="formServiceClass.FIELD_ATTACHMENTS"
[existFiles]="attachments$ | async" [fileUploadType]="KOMMENTAR_UPLOADED_ATTACHMENTS"
[formArrayName]="formServiceClass.FIELD_ATTACHMENTS" ></ods-multi-file-upload-list-container>
[uploadStateResource]="kommentarListStateResource" <ods-multi-file-upload-editor
[linkRelUploadAttachment]="kommentarListLinkRel.UPLOAD_FILE" [fileUploadType]="KOMMENTAR_UPLOADED_ATTACHMENTS"
> [uploadResource]="kommentarListStateResource.resource"
</alfa-binary-file-attachment-container> [uploadLinkRelation]="kommentarListLinkRel.UPLOAD_FILE"
></ods-multi-file-upload-editor>
<div class="buttons"> <div class="buttons">
<ozgcloud-stroked-button-with-spinner <ozgcloud-stroked-button-with-spinner
......
...@@ -21,24 +21,16 @@ ...@@ -21,24 +21,16 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen * Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen. * unter der Lizenz sind dem Lizenztext zu entnehmen.
*/ */
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'; import { BinaryFileListLinkRel, BinaryFileResource } from '@alfa-client/binary-file-shared';
import { CommandResource } from '@alfa-client/command-shared'; import { CommandResource } from '@alfa-client/command-shared';
import { import { KOMMENTAR_UPLOADED_ATTACHMENTS, KommentarListLinkRel, KommentarListResource, KommentarResource, KommentarService, } from '@alfa-client/kommentar-shared';
KommentarListLinkRel, import { createEmptyStateResource, getEmbeddedResources, StateResource } from '@alfa-client/tech-shared';
KommentarListResource, import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
KommentarResource,
KommentarService,
} from '@alfa-client/kommentar-shared';
import {
createEmptyStateResource,
getEmbeddedResources,
StateResource,
} from '@alfa-client/tech-shared';
import { isNil } from 'lodash-es'; import { isNil } from 'lodash-es';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { KommentarFormService } from './kommentar.formservice';
import { BinaryFileListLinkRel, BinaryFileResource } from '@alfa-client/binary-file-shared';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { MultiFileUploadListOrientation } from '../../../../../design-component/src/lib/form/multi-file-upload-list-container/multi-file-upload-list-container.component';
import { KommentarFormService } from './kommentar.formservice';
@Component({ @Component({
selector: 'alfa-kommentar-form', selector: 'alfa-kommentar-form',
...@@ -52,12 +44,11 @@ export class KommentarFormComponent implements OnChanges { ...@@ -52,12 +44,11 @@ export class KommentarFormComponent implements OnChanges {
@Output() cancel: EventEmitter<void> = new EventEmitter(); @Output() cancel: EventEmitter<void> = new EventEmitter();
submitInProgress$: Observable<StateResource<CommandResource>> = of( submitInProgress$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
createEmptyStateResource<CommandResource>(),
);
readonly formServiceClass = KommentarFormService; public readonly formServiceClass = KommentarFormService;
readonly kommentarListLinkRel = KommentarListLinkRel; public readonly kommentarListLinkRel = KommentarListLinkRel;
public readonly KOMMENTAR_UPLOADED_ATTACHMENTS = KOMMENTAR_UPLOADED_ATTACHMENTS;
attachments$: Observable<BinaryFileResource[]> = of([]); attachments$: Observable<BinaryFileResource[]> = of([]);
...@@ -76,11 +67,7 @@ export class KommentarFormComponent implements OnChanges { ...@@ -76,11 +67,7 @@ export class KommentarFormComponent implements OnChanges {
private updateAttachments() { private updateAttachments() {
this.attachments$ = this.kommentarService this.attachments$ = this.kommentarService
.getAttachments(this.kommentar) .getAttachments(this.kommentar)
.pipe( .pipe(map((stateResource) => getEmbeddedResources<BinaryFileResource>(stateResource, BinaryFileListLinkRel.FILE_LIST)));
map((stateResource) =>
getEmbeddedResources<BinaryFileResource>(stateResource, BinaryFileListLinkRel.FILE_LIST),
),
);
} }
patch(): void { patch(): void {
...@@ -90,4 +77,6 @@ export class KommentarFormComponent implements OnChanges { ...@@ -90,4 +77,6 @@ export class KommentarFormComponent implements OnChanges {
submit(): void { submit(): void {
this.submitInProgress$ = <Observable<StateResource<CommandResource>>>this.formService.submit(); this.submitInProgress$ = <Observable<StateResource<CommandResource>>>this.formService.submit();
} }
protected readonly ListOrientation = MultiFileUploadListOrientation;
} }
...@@ -21,14 +21,16 @@ ...@@ -21,14 +21,16 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen * Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen. * unter der Lizenz sind dem Lizenztext zu entnehmen.
*/ */
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { BinaryFileModule } from '@alfa-client/binary-file'; import { BinaryFileModule } from '@alfa-client/binary-file';
import { KommentarSharedModule } from '@alfa-client/kommentar-shared'; import { KommentarSharedModule } from '@alfa-client/kommentar-shared';
import { TechSharedModule } from '@alfa-client/tech-shared'; import { TechSharedModule } from '@alfa-client/tech-shared';
import { UiModule } from '@alfa-client/ui'; import { UiModule } from '@alfa-client/ui';
import { UserProfileModule } from '@alfa-client/user-profile'; import { UserProfileModule } from '@alfa-client/user-profile';
import { VorgangSharedModule } from '@alfa-client/vorgang-shared'; import { VorgangSharedModule } from '@alfa-client/vorgang-shared';
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MultiFileUploadEditorComponent } from '../../../design-component/src/lib/form/multi-file-upload-editor/multi-file-upload-editor.component';
import { MultiFileUploadListContainerComponent } from '../../../design-component/src/lib/form/multi-file-upload-list-container/multi-file-upload-list-container.component';
import { KommentarFormComponent } from './kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component'; import { KommentarFormComponent } from './kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component';
import { KommentarListInVorgangContainerComponent } from './kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component'; import { KommentarListInVorgangContainerComponent } from './kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component';
import { KommentarListInVorgangComponent } from './kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component'; import { KommentarListInVorgangComponent } from './kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component';
...@@ -43,6 +45,8 @@ import { KommentarListItemInVorgangComponent } from './kommentar-list-in-vorgang ...@@ -43,6 +45,8 @@ import { KommentarListItemInVorgangComponent } from './kommentar-list-in-vorgang
TechSharedModule, TechSharedModule,
UserProfileModule, UserProfileModule,
BinaryFileModule, BinaryFileModule,
MultiFileUploadEditorComponent,
MultiFileUploadListContainerComponent,
], ],
declarations: [ declarations: [
KommentarListInVorgangContainerComponent, KommentarListInVorgangContainerComponent,
......
...@@ -26,3 +26,12 @@ import { faker } from '@faker-js/faker'; ...@@ -26,3 +26,12 @@ import { faker } from '@faker-js/faker';
export function createFile(): File { export function createFile(): File {
return <any>{ name: faker.string.sample(10), type: 'image/png', size: 512 }; return <any>{ name: faker.string.sample(10), type: 'image/png', size: 512 };
} }
export function createFileList(): FileList {
const file = createFile();
return {
0: file,
length: 2,
item: (index: number) => file,
};
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment