Skip to content
Snippets Groups Projects
Commit 8e0af92d authored by OZGCloud's avatar OZGCloud
Browse files

OZG-5010 wip attachments

parent eabaa96b
Branches
Tags
No related merge requests found
Showing
with 226 additions and 17 deletions
...@@ -24,5 +24,6 @@ ...@@ -24,5 +24,6 @@
export * from './lib/binary-file-attachment-container/binary-file-attachment-container.component'; export * from './lib/binary-file-attachment-container/binary-file-attachment-container.component';
export * from './lib/binary-file-container/binary-file-container.component'; export * from './lib/binary-file-container/binary-file-container.component';
export * from './lib/binary-file.module'; export * from './lib/binary-file.module';
export * from './lib/binary-file2-container/binary-file2-container.component';
export * from './lib/horizontal-binary-file-list/horizontal-binary-file-list.component'; export * from './lib/horizontal-binary-file-list/horizontal-binary-file-list.component';
export * from './lib/vertical-binary-file-list/vertical-binary-file-list.component'; export * from './lib/vertical-binary-file-list/vertical-binary-file-list.component';
...@@ -21,30 +21,43 @@ ...@@ -21,30 +21,43 @@
* 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 { 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 { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { AttachmentComponent, IconComponent, SpinnerIconComponent } from 'design-system';
import { BinaryFileAttachmentContainerComponent } from './binary-file-attachment-container/binary-file-attachment-container.component'; import { BinaryFileAttachmentContainerComponent } from './binary-file-attachment-container/binary-file-attachment-container.component';
import { BinaryFileContainerComponent } from './binary-file-container/binary-file-container.component'; import { BinaryFileContainerComponent } from './binary-file-container/binary-file-container.component';
import { BinaryFileComponent } from './binary-file-container/binary-file/binary-file.component'; import { BinaryFileComponent } from './binary-file-container/binary-file/binary-file.component';
import { BinaryFile2ContainerComponent } from './binary-file2-container/binary-file2-container.component';
import { BinaryFile2Component } from './binary-file2-container/binary-file2/binary-file2.component';
import { HorizontalBinaryFileListComponent } from './horizontal-binary-file-list/horizontal-binary-file-list.component'; import { HorizontalBinaryFileListComponent } from './horizontal-binary-file-list/horizontal-binary-file-list.component';
import { VerticalBinaryFileListComponent } from './vertical-binary-file-list/vertical-binary-file-list.component'; import { VerticalBinaryFileListComponent } from './vertical-binary-file-list/vertical-binary-file-list.component';
@NgModule({ @NgModule({
imports: [CommonModule, UiModule, TechSharedModule], imports: [
CommonModule,
UiModule,
TechSharedModule,
AttachmentComponent,
IconComponent,
SpinnerIconComponent,
],
declarations: [ declarations: [
BinaryFileAttachmentContainerComponent, BinaryFileAttachmentContainerComponent,
BinaryFileComponent, BinaryFileComponent,
BinaryFileContainerComponent, BinaryFileContainerComponent,
HorizontalBinaryFileListComponent, HorizontalBinaryFileListComponent,
VerticalBinaryFileListComponent, VerticalBinaryFileListComponent,
BinaryFile2ContainerComponent,
BinaryFile2Component,
], ],
exports: [ exports: [
BinaryFileAttachmentContainerComponent, BinaryFileAttachmentContainerComponent,
BinaryFileContainerComponent, BinaryFileContainerComponent,
HorizontalBinaryFileListComponent, HorizontalBinaryFileListComponent,
VerticalBinaryFileListComponent, VerticalBinaryFileListComponent,
BinaryFile2ContainerComponent,
], ],
}) })
export class BinaryFileModule {} export class BinaryFileModule {}
<alfa-binary-file2
[attr.data-test-id]="(file.name | convertForDataTest) + '-file-item'"
[file]="file"
[stateResource]="fileStateResource$ | async"
[deletable]="deletable"
[downloadToken]="downloadToken$ | async"
(startDownload)="startDownload($event)"
(startDelete)="startDelete.emit($event)"
(getDownloadToken)="getDownloadToken()"
>
</alfa-binary-file2>
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BinaryFile2ContainerComponent } from './binary-file2-container.component';
describe('BinaryFile2ContainerComponent', () => {
let component: BinaryFile2ContainerComponent;
let fixture: ComponentFixture<BinaryFile2ContainerComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [BinaryFile2ContainerComponent],
}).compileComponents();
fixture = TestBed.createComponent(BinaryFile2ContainerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { ApiDownloadToken, ApiRootService } from '@alfa-client/api-root-shared';
import { BinaryFileResource, BinaryFileService } from '@alfa-client/binary-file-shared';
import { StateResource } from '@alfa-client/tech-shared';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Observable } from 'rxjs';
@Component({
selector: 'alfa-binary-file2-container',
templateUrl: './binary-file2-container.component.html',
//styles: [':host {@apply flex flex-grow}'],
})
export class BinaryFile2ContainerComponent {
@Input() file: BinaryFileResource;
@Input() downloadFileNamePrefix: string;
@Input() deletable: boolean = false;
@Output() startDelete: EventEmitter<BinaryFileResource> = new EventEmitter();
fileStateResource$: Observable<StateResource<any>>;
downloadToken$: Observable<ApiDownloadToken>;
constructor(
private binaryFileService: BinaryFileService,
private apiRootService: ApiRootService,
) {}
startDownload(file: BinaryFileResource): void {
this.fileStateResource$ = this.binaryFileService.downloadFile(
file,
this.downloadFileNamePrefix,
);
}
getDownloadToken(): void {
this.downloadToken$ = this.apiRootService.getDownloadToken(this.file);
}
}
<ods-attachment
[documentName]="file.name"
[description]="file.size | fileSizePlain"
(click)="downloadFile()"
[attr.aria-label]="'Anhang: Dateiname: ' + file.name"
>
<ods-spinner-icon spinner *ngIf="false" class="mr-3 size-10" />
<ods-icon icon name="file-pdf" class="mr-3 size-10 fill-primary"></ods-icon>
<button
close
*ngIf="deletable"
class="absolute right-2 top-1/2 flex size-10 -translate-y-1/2 items-center justify-center rounded-md hover:border hover:border-ozggray-600 hover:bg-ozggray-100"
(click)="deleteFile()"
title="Anhang löschen"
aria-label="Anhang löschen Button"
>
<ods-icon name="close" size="14" fillColor="black" class="ml-3 w-6"></ods-icon>
</button>
</ods-attachment>
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BinaryFile2Component } from './binary-file2.component';
describe('BinaryFile2Component', () => {
let component: BinaryFile2Component;
let fixture: ComponentFixture<BinaryFile2Component>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [BinaryFile2Component],
}).compileComponents();
fixture = TestBed.createComponent(BinaryFile2Component);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { ApiDownloadToken } from '@alfa-client/api-root-shared';
import { BinaryFileLinkRel, BinaryFileResource } from '@alfa-client/binary-file-shared';
import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared';
import { HttpParams } from '@angular/common/http';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Resource, getUrl } from '@ngxp/rest';
import { isEmpty, isNil } from 'lodash-es';
@Component({
selector: 'alfa-binary-file2',
templateUrl: './binary-file2.component.html',
styles: [':host {@apply flex flex-grow}'],
})
export class BinaryFile2Component {
@Input() file: BinaryFileResource;
@Input() stateResource: StateResource<Resource>;
@Input() deletable: boolean = false;
@Input() downloadToken: ApiDownloadToken = <ApiDownloadToken>{};
readonly fileLinkRel = BinaryFileLinkRel;
@Output() public startDownload: EventEmitter<BinaryFileResource> =
new EventEmitter<BinaryFileResource>();
@Output() public startDelete: EventEmitter<BinaryFileResource> =
new EventEmitter<BinaryFileResource>();
@Output() public getDownloadToken: EventEmitter<void> = new EventEmitter<void>();
get isDisabled(): boolean {
return this.getStateResource().loading;
}
getStateResource(): StateResource<Resource> {
return isNil(this.stateResource) ? createEmptyStateResource<Resource>() : this.stateResource;
}
downloadFile(): void {
this.startDownload.emit(this.file);
}
deleteFile(): void {
this.startDelete.emit(this.file);
}
getNewDownloadToken(): void {
this.getDownloadToken.emit();
}
dragStart(event: DragEvent): void {
event.dataTransfer.setData('DownloadURL', this.createDownloadUrl());
}
dragEnd(event: DragEvent): void {
if (this.isValidDrop(event)) {
this.handleSpinnerForDragEnd();
}
}
private isValidDrop(event: DragEvent): boolean {
return event.dataTransfer.dropEffect !== 'none';
}
handleSpinnerForDragEnd(): void {
this.stateResource = { ...this.stateResource, loading: true };
setTimeout(() => (this.stateResource = { ...this.stateResource, loading: false }), 3000);
}
createDownloadUrl(): string {
return `${this.getContentType()}:${this.file.name}:${this.createRemoteUrl()}`;
}
private getContentType(): string {
return isEmpty(this.file.contentType) ? 'application/octet-stream' : this.file.contentType;
}
private createRemoteUrl(): string {
let getParam = new HttpParams();
getParam = getParam.set('token', this.downloadToken?.token);
return getUrl(this.file, BinaryFileLinkRel.DOWNLOAD) + '?' + getParam.toString();
}
}
<div class="flex w-full items-center bg-ozggray px-3 py-2 hover:bg-ozggray-200"> <button
<ng-content select="[before-content]"></ng-content> class="relative flex flex-grow items-center rounded-md border border-black/25 bg-background-100 px-3 pb-3 pt-2 hover:bg-ozggray-200"
<div class="flex w-full flex-col"> >
<ng-content select="[spinner]"></ng-content>
<ng-content select="[icon]"></ng-content>
<div class="flex w-full flex-col items-start">
<p class="text-sm">{{ documentName }}</p> <p class="text-sm">{{ documentName }}</p>
<p class="text-xs text-ozggray-600">{{ description }}</p> <p class="text-xs text-ozggray-600">{{ description }}</p>
</div> </div>
<ng-content select="[after-content]"></ng-content> <ng-content select="[close]"></ng-content>
</div> </button>
import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { Component, Input } from '@angular/core';
@Component({ @Component({
selector: 'ods-attachment', selector: 'ods-attachment',
standalone: true, standalone: true,
imports: [CommonModule], imports: [CommonModule],
styles: [':host {@apply flex flex-grow}'],
templateUrl: './attachment.component.html', templateUrl: './attachment.component.html',
}) })
export class AttachmentComponent { export class AttachmentComponent {
......
<alfa-binary-file-container <alfa-binary-file2-container
*ngFor="let attachment of existingAttachments" *ngFor="let attachment of existingAttachments"
[file]="attachment" [file]="attachment"
[deletable]="true" [deletable]="true"
(startDelete)="deleteFile($event)" (startDelete)="deleteFile($event)"
> >
</alfa-binary-file-container> </alfa-binary-file2-container>
<ng-container *ngFor="let attachment of uploadedAttachments"> <ng-container *ngFor="let attachment of uploadedAttachments">
<alfa-vorgang-detail-bescheiden-form-error <alfa-vorgang-detail-bescheiden-form-error
*ngIf="attachment.error" *ngIf="attachment.error"
[error]="attachment.error" [error]="attachment.error"
></alfa-vorgang-detail-bescheiden-form-error> ></alfa-vorgang-detail-bescheiden-form-error>
<p *ngIf="attachment.loading">loading...</p> <p *ngIf="attachment.loading">loading...</p>
<alfa-binary-file-container <alfa-binary-file2-container
*ngIf="!attachment.error && attachment.loaded" *ngIf="!attachment.error && attachment.loaded"
[file]="attachment.resource" [file]="attachment.resource"
[deletable]="true" [deletable]="true"
(startDelete)="deleteFile($event)" (startDelete)="deleteFile($event)"
> >
</alfa-binary-file-container> </alfa-binary-file2-container>
</ng-container> </ng-container>
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
@Output() delete: EventEmitter<BinaryFileResource> @Output() delete: EventEmitter<BinaryFileResource>
--> -->
<ng-container *ngIf="bescheidDocumentFile.resource"> <ng-container *ngIf="bescheidDocumentFile.resource">
<alfa-binary-file-container <alfa-binary-file2-container
*ngIf="!bescheidDocumentFile.loading" *ngIf="!bescheidDocumentFile.loading"
[file]="bescheidDocumentFile.resource" [file]="bescheidDocumentFile.resource"
[deletable]="true" [deletable]="true"
(startDelete)="deleteFile.emit()" (startDelete)="deleteFile.emit()"
> >
</alfa-binary-file-container> </alfa-binary-file2-container>
</ng-container> </ng-container>
<ng-container *ngIf="bescheidDocumentFile.loading"> <ng-container *ngIf="bescheidDocumentFile.loading">
<span *ngIf="bescheidDocumentFile.resource">{{ bescheidDocumentFile.resource.name }}</span> <span *ngIf="bescheidDocumentFile.resource">{{ bescheidDocumentFile.resource.name }}</span>
......
...@@ -41,6 +41,7 @@ import { CommonModule } from '@angular/common'; ...@@ -41,6 +41,7 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { import {
AttachmentComponent,
BescheidGenerateIconComponent, BescheidGenerateIconComponent,
BescheidUploadIconComponent, BescheidUploadIconComponent,
ButtonComponent, ButtonComponent,
...@@ -133,6 +134,7 @@ const routes: Routes = [ ...@@ -133,6 +134,7 @@ const routes: Routes = [
SpinnerIconComponent, SpinnerIconComponent,
BescheidUploadIconComponent, BescheidUploadIconComponent,
BescheidGenerateIconComponent, BescheidGenerateIconComponent,
AttachmentComponent,
], ],
declarations: [ declarations: [
VorgangDetailPageComponent, VorgangDetailPageComponent,
......
...@@ -54,8 +54,7 @@ ...@@ -54,8 +54,7 @@
"@alfa-client/wiedervorlage": ["libs/wiedervorlage/src/index.ts"], "@alfa-client/wiedervorlage": ["libs/wiedervorlage/src/index.ts"],
"@alfa-client/wiedervorlage-shared": ["libs/wiedervorlage-shared/src/index.ts"], "@alfa-client/wiedervorlage-shared": ["libs/wiedervorlage-shared/src/index.ts"],
"authentication": ["libs/authentication/src/index.ts"], "authentication": ["libs/authentication/src/index.ts"],
"design-system": ["libs/design-system/src/index.ts"], "design-system": ["libs/design-system/src/index.ts"]
"design-ui": ["libs/design-ui/src/index.ts"]
} }
}, },
"exclude": ["node_modules", "tmp"] "exclude": ["node_modules", "tmp"]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment