From f035d4ece36a0810a166be111c778b0c500329cc Mon Sep 17 00:00:00 2001
From: Yanek Voloshchuk
Date: Mon, 16 Sep 2024 12:02:30 +0200
Subject: [PATCH] update upload and add remove to upload-file component
---
.../file-upload/file-upload.component.html | 18 ++++-
.../lib/file-upload/file-upload.component.ts | 79 +++++++++++++------
.../upload-demo-api-spec.component.html | 77 ++++++++++++++++++
.../upload-demo-api-spec.component.scss | 24 ++++++
.../upload-demo-api-spec.component.ts | 12 +++
.../upload-demo/upload-demo.component.html | 16 ++--
.../upload-demo/upload-demo.component.ts | 3 +-
.../upload-file/upload-file.component.html | 2 +
.../upload-file/upload-file.component.ts | 1 +
9 files changed, 194 insertions(+), 38 deletions(-)
create mode 100644 src/app/component-demos/upload-demo/upload-demo-api-spec/upload-demo-api-spec.component.html
create mode 100644 src/app/component-demos/upload-demo/upload-demo-api-spec/upload-demo-api-spec.component.scss
create mode 100644 src/app/component-demos/upload-demo/upload-demo-api-spec/upload-demo-api-spec.component.ts
diff --git a/projects/material-addons/src/lib/file-upload/file-upload.component.html b/projects/material-addons/src/lib/file-upload/file-upload.component.html
index 0c478b95..7946fc47 100644
--- a/projects/material-addons/src/lib/file-upload/file-upload.component.html
+++ b/projects/material-addons/src/lib/file-upload/file-upload.component.html
@@ -9,20 +9,30 @@
#fileInput
(change)="uploadFile($event.target.files)"
(click)="fileInput.value = null"
- [accept]="acceptForInput"
+ [accept]="acceptedFileTypes"
[id]="id"
[multiple]="multiple"
hidden
type="file"
/>
- vertical_align_top
- {{ text ? text : 'Upload' }}
+
+ {{ fileList[0].name }}
+
+
+
+ vertical_align_top
+ {{ text ? text : 'Upload' }}
+
- {{ file.name }}
+
+ {{ file.name }}
+ delete_forever
+
diff --git a/projects/material-addons/src/lib/file-upload/file-upload.component.ts b/projects/material-addons/src/lib/file-upload/file-upload.component.ts
index 9884e92b..b2adb2f0 100644
--- a/projects/material-addons/src/lib/file-upload/file-upload.component.ts
+++ b/projects/material-addons/src/lib/file-upload/file-upload.component.ts
@@ -22,48 +22,83 @@ export class FileUploadComponent implements OnInit {
@Input() accept: string[];
@Input() text: string;
@Input() showFileList: boolean = false;
+ @Input() removable: boolean = true;
@Output() fileEmitter = new EventEmitter();
@Output() errorEmitter = new EventEmitter();
fileList: File[] = [];
- acceptForInput: string[] = [];
- private uploadError: boolean = false;
+ acceptedFileTypes: string[] = [];
ngOnInit(): void {
+ this.setAcceptedFileTypes();
+ }
+
+ private setAcceptedFileTypes(): void {
if (this.accept?.length) {
- this.accept.forEach((accepted) => this.acceptForInput.push(`.${accepted}`));
+ this.acceptedFileTypes = this.accept.map(ext => `.${ext.toLowerCase()}`);
}
}
- uploadFile(fileList: FileList): void {
- if (!this.multiple && (fileList.length > 1 || this.fileList.length === 1)) {
- this.errorEmitter.emit('ONLY_SINGLE_FILE');
- this.uploadError = false;
+ uploadFile(files: FileList): void {
+ const fileArray = Array.from(files);
+
+ if (!this.validateFileList(fileArray)) {
return;
}
- if (this.accept && this.accept.length > 0) {
- for (let i = 0; i < fileList.length; i++) {
- this.getFileEnding(fileList.item(i).name);
- }
+
+ this.addFiles(fileArray);
+ this.fileEmitter.emit(this.createFileListFromArray(this.fileList));
+ }
+
+ private validateFileList(fileArray: File[]): boolean {
+ if (!this.multiple && fileArray.length > 1) {
+ this.emitError('ONLY_SINGLE_FILE');
+ return false;
}
- if (!this.uploadError) {
- for (let i = 0; i < fileList.length; i++) {
- this.fileList.push(fileList.item(i));
+
+ for (const file of fileArray) {
+ if (!this.isAcceptedFileType(file.name)) {
+ this.emitError('FILETYPE_NOT_SUPPORTED');
+ return false;
}
- this.fileEmitter.emit(fileList);
}
- this.uploadError = false;
+
+ return true;
+ }
+
+ private emitError(errorType: UploadError): void {
+ this.errorEmitter.emit(errorType);
+ }
+
+ private isAcceptedFileType(fileName: string): boolean {
+ const fileExtension = fileName.split('.').pop()?.toLowerCase();
+ return this.acceptedFileTypes.includes(`.${fileExtension}`);
}
- getFileEnding(name: string): void {
- const ending = name.substring(name.lastIndexOf('.') + 1);
- if (this.accept.filter((a) => a.toLowerCase() === ending.toLowerCase()).length === 0) {
- this.errorEmitter.emit('FILETYPE_NOT_SUPPORTED');
- this.uploadError = true;
+ private addFiles(fileArray: File[]): void {
+ if (!this.multiple) {
+ this.fileList = [];
}
+ this.fileList.push(...fileArray);
}
- openFile(file: File) {
+ openFile(file: File): void {
window.open(window.URL.createObjectURL(file));
}
+
+ remove(file: File): void {
+ this.fileList = this.fileList.filter(f => f !== file);
+ this.fileEmitter.emit(this.createFileListFromArray(this.fileList));
+ }
+
+ private createFileListFromArray(files: File[]): FileList {
+ const dataTransfer = new DataTransfer();
+ files.forEach(file => dataTransfer.items.add(file));
+ return dataTransfer.files;
+ }
+
+ hasSingleFile(): boolean {
+ return !this.multiple && this.fileList.length === 1;
+ }
+
}
diff --git a/src/app/component-demos/upload-demo/upload-demo-api-spec/upload-demo-api-spec.component.html b/src/app/component-demos/upload-demo/upload-demo-api-spec/upload-demo-api-spec.component.html
new file mode 100644
index 00000000..eaa5e067
--- /dev/null
+++ b/src/app/component-demos/upload-demo/upload-demo-api-spec/upload-demo-api-spec.component.html
@@ -0,0 +1,77 @@
+
+
Properties
+
+
+
+ Property |
+ Type |
+ Default Value |
+ Description |
+
+
+
+
+ id |
+ string |
+ '' |
+
+ HTML id of the element.
+ |
+
+
+ multiple |
+ boolean |
+
|
+ if false only 1 document can be added, otherwise you can add as much documents as you want. |
+
+
+ accept |
+ string[] |
+ '[]' |
+ is a string array which contains all valid document types. |
+
+
+ text |
+ string |
+ 'Upload' |
+ Text in the Upload Field. |
+
+
+ showFileList |
+ boolean |
+ false |
+ Shows the list of added files. |
+
+
+ removable |
+ boolean |
+ true |
+ Uploaded file can be deleted using icon in chip. |
+
+
+
+
+
Events
+
+
+
+ Event |
+ Description |
+
+
+
+
+ fileEmitter |
+ Emits when file is uploaded/removed. Contains file list |
+
+
+ errorEmitter |
+ (ErrorType) ONLY_SINGLE_FILE: if only 1 File is allowed and user tries to add more than 1 File in 1 dialog. |
+
+
+ errorEmitter |
+ (ErrorType) FILETYPE_NOT_SUPPORTED: if user tries to add unsupported file type |
+
+
+
+
diff --git a/src/app/component-demos/upload-demo/upload-demo-api-spec/upload-demo-api-spec.component.scss b/src/app/component-demos/upload-demo/upload-demo-api-spec/upload-demo-api-spec.component.scss
new file mode 100644
index 00000000..421d448b
--- /dev/null
+++ b/src/app/component-demos/upload-demo/upload-demo-api-spec/upload-demo-api-spec.component.scss
@@ -0,0 +1,24 @@
+.api-specification {
+ font-family: Arial, sans-serif;
+}
+
+.api-specification h2 {
+ color: #333;
+}
+
+.api-specification table {
+ width: 100%;
+ border-collapse: collapse;
+ margin-bottom: 20px;
+}
+
+.api-specification th,
+.api-specification td {
+ border: 1px solid #ccc;
+ padding: 8px;
+ text-align: left;
+}
+
+.api-specification th {
+ background-color: #f2f2f2;
+}
diff --git a/src/app/component-demos/upload-demo/upload-demo-api-spec/upload-demo-api-spec.component.ts b/src/app/component-demos/upload-demo/upload-demo-api-spec/upload-demo-api-spec.component.ts
new file mode 100644
index 00000000..2cc53d0b
--- /dev/null
+++ b/src/app/component-demos/upload-demo/upload-demo-api-spec/upload-demo-api-spec.component.ts
@@ -0,0 +1,12 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app-upload-demo-api-spec',
+ standalone: true,
+ imports: [],
+ templateUrl: './upload-demo-api-spec.component.html',
+ styleUrl: './upload-demo-api-spec.component.scss'
+})
+export class UploadDemoApiSpecComponent {
+
+}
diff --git a/src/app/component-demos/upload-demo/upload-demo.component.html b/src/app/component-demos/upload-demo/upload-demo.component.html
index da956ada..3212e49e 100644
--- a/src/app/component-demos/upload-demo/upload-demo.component.html
+++ b/src/app/component-demos/upload-demo/upload-demo.component.html
@@ -2,18 +2,10 @@
Behavior
- - clickable with dialog to select files
+ - Clickable with dialog to select files
- Drag And Drop Functionality
-
-
-
-Inputs
-
- - accept: is a string array which contains all valid document types
- - multiple: if false only 1 document can be added, otherwise you can add as much documents as you want
- - text: Text in the Upload Field
- - id: HTML id of the element
- - showFileList: Shows the list of added files
+ - Replace file with a new one in single upload mode
+ - Show the
@@ -37,3 +29,5 @@ Output
+API Specification
+
diff --git a/src/app/component-demos/upload-demo/upload-demo.component.ts b/src/app/component-demos/upload-demo/upload-demo.component.ts
index 5b14f981..6ec8ed9f 100644
--- a/src/app/component-demos/upload-demo/upload-demo.component.ts
+++ b/src/app/component-demos/upload-demo/upload-demo.component.ts
@@ -3,13 +3,14 @@ import { Example } from '../../components/example-viewer/example.class';
import { UploadFileComponent } from '../../example-components/upload-file/upload-file.component';
import { ExampleViewerComponent } from '../../components/example-viewer/example-viewer.component';
import { TextCodeComponent } from '../../components/text-code/text-code.component';
+import {UploadDemoApiSpecComponent} from './upload-demo-api-spec/upload-demo-api-spec.component';
@Component({
selector: 'app-upload-demo',
templateUrl: './upload-demo.component.html',
styleUrl: './upload-demo.component.scss',
standalone: true,
- imports: [TextCodeComponent, ExampleViewerComponent],
+ imports: [TextCodeComponent, ExampleViewerComponent, UploadDemoApiSpecComponent],
})
export class UploadDemoComponent {
uploadComponent = new Example(UploadFileComponent, 'upload-file', 'upload');
diff --git a/src/app/example-components/upload-file/upload-file.component.html b/src/app/example-components/upload-file/upload-file.component.html
index ec316452..cd418baf 100644
--- a/src/app/example-components/upload-file/upload-file.component.html
+++ b/src/app/example-components/upload-file/upload-file.component.html
@@ -7,12 +7,14 @@
{{ 'Allow Multiple Uploads' }}
{{ 'Show File List' }}
+{{ 'Removable File' }}