SUPPORT-8381: add FileUploadV2 component

This commit is contained in:
Alexandr Shalaginov 2024-07-11 14:20:42 +03:00
parent b129794ff4
commit 09256d4ea9
3 changed files with 216 additions and 1 deletions

View file

@ -0,0 +1,29 @@
<div [id]="getObjectId()"
class="file-upload-v2"
[ngbTooltip]="tooltip | emptyIfNull">
<div ng2FileDrop
[uploader]="uploader"
class="file-drop-zone"
[hidden]="!(uploader.queue.length < maxFilesToUpload)">
<span class="select-file-field-text">{{selectFileFieldText}}</span>
<button class="select-file-btn" (click)="openFileChooseDialog()">{{selectFileButtonName}}</button>
<input type="file"
class="file-input"
ng2FileSelect
[uploader]="uploader"
[multiple]="!maxFilesToUpload || maxFilesToUpload > 1"
[accept]="getExtensions()"
hidden>
</div>
<div class="selected-file-list">
<div class="selected-file" *ngFor="let item of uploader.queue">
<span class="selected-file-name">{{item?.file?.name}}</span>
<span class="selected-file-size" [hidden]="!displayFileSize">{{item?.file?.size/1024/1024 | number: '.2'}} MB</span>
<button class="selected-file-delete-btn" (click)="removeFile(item)">{{removeFileButtonName}}</button>
</div>
</div>
<div class="file-upload-progress" [hidden]="!displayProgressBar">
<div class="file-upload-progress-bar" role="progressbar" [ngStyle]="{ 'width': uploader.progress + '%' }"></div>
</div>
<button (click)="uploader.uploadAll()" [disabled]="!uploader.getNotUploadedItems().length">Upload</button>
</div>

View file

@ -0,0 +1,184 @@
import {
InputControl,
NotNull,
Visible,
Event,
MessagesService,
UnsupportedOperationError
} from "@webbpm/base-package";
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef} from "@angular/core";
import {FileItem, FileUploader, ParsedResponseHeaders} from "ng2-file-upload";
import {FileLikeObject} from "ng2-file-upload/file-upload/file-like-object.class";
@Component({
moduleId: module.id,
selector: "file-upload-v2",
templateUrl: "./../../../../../src/resources/template/ervu/component/FileUploadV2.html",
changeDetection: ChangeDetectionStrategy.OnPush
})
export class FileUploadV2 extends InputControl {
@NotNull("true")
public selectFileFieldText: string;
@NotNull("true")
public selectFileButtonName: string;
@NotNull("true")
public removeFileButtonName: string;
public maxFileSizeMb: number;
public extensionFilter: string[] = [];
public maxFilesToUpload: number;
@NotNull("true")
public displayFileSize: boolean = false;
@NotNull("true")
public displayProgressBar: boolean = false;
@Visible("false")
public uploader: FileUploader;
@Visible("false")
public fileAddedEvent: Event<any> = new Event<any>();
@Visible("false")
public fileDeletedEvent: Event<any> = new Event<any>();
@Visible("false")
public fileUploadStartEvent: Event<any> = new Event<any>();
@Visible("false")
public fileUploadEndEvent: Event<any> = new Event<any>();
@Visible("false")
public fileUploadFailedEvent: Event<any> = new Event<any>();
private fileInputEl: any;
private url: string = '/files/upload';
private messagesService: MessagesService;
constructor(el: ElementRef, cd: ChangeDetectorRef) {
super(el, cd);
this.uploader = new FileUploader({url: this.url});
}
initialize() {
super.initialize();
this.messagesService = this.injector.get(MessagesService);
this.uploader.setOptions({
url: this.url,
autoUpload: false,
filters: [{
name: 'extension',
fn: (item: any): boolean => {
if (!this.extensionFilter.length) {
return true;
}
const fileExtension = item.name.substring(item.name.lastIndexOf('.') + 1, item.name.length);
for (let ext of this.extensionFilter) {
if (ext.toUpperCase() === fileExtension.toUpperCase()) {
return true;
}
}
return false;
}
}],
maxFileSize: this.maxFileSizeMb ? this.maxFileSizeMb * 1024 * 1024 : undefined,
queueLimit: this.maxFilesToUpload ? this.maxFilesToUpload : undefined
});
this.setUploaderMethods();
}
ngAfterViewInit() {
super.ngAfterViewInit();
this.fileInputEl = $(this.el.nativeElement).find('.file-input');
}
openFileChooseDialog() {
this.fileInputEl.click();
}
@Visible()
uploadFiles() {
this.uploader.uploadAll();
}
removeFile(item: FileItem) {
item.remove();
this.fileDeletedEvent.trigger();
}
private setUploaderMethods() {
this.uploader.onBeforeUploadItem = (fileItem: FileItem) => {
this.fileUploadStartEvent.trigger();
};
this.uploader.onErrorItem = (item: FileItem,
response: string) => {
this.fileUploadFailedEvent.trigger();
this.messagesService.error(`Не удалось отправить файл ${item.file.name}.`);
throw new Error(`Fail upload file ${item.file.name}: ${response}`);
};
this.uploader.onCompleteAll = () => {
this.fileUploadEndEvent.trigger();
};
this.uploader.onAfterAddingFile = (fileItem: FileItem) => {
this.fileAddedEvent.trigger();
}
this.uploader.onWhenAddingFileFailed = (item: FileLikeObject, filter: any, options: any) => {
switch (filter.name) {
case "fileSize":
this.messagesService.error(`Размер файла ${item.name} превышает предельно допустимый = ${this.maxFileSizeMb} MB`);
break;
case "queueLimit":
this.messagesService.error(`Не удалось добавить файл ${item.name}. `
+ `Достигнуто максимальное количество файлов для загрузки = ${this.maxFilesToUpload}`);
break;
case "extension":
this.messagesService.error(`Файл ${item.name} имеет недопустимое расширение.`);
break;
default:
this.messagesService.error(`Не удалось добавить файл ${item.name}.`);
}
};
}
@Visible()
getExtensions(): string {
if (this.extensionFilter) {
return this.extensionFilter
.map(s => '.' + s)
.join(',')
}
return undefined;
}
subscribeToModelChange() {
//empty because there is no ngModel here
}
unsubscribeToModelChange() {
//empty because there is no ngModel here
}
@Visible()
getPresentationValue(): string | number | boolean {
let fileNames: string = '';
let fileItems: FileItem[] = this.uploader.queue;
if (fileItems) {
fileItems.forEach((fileItem) => {
fileNames += fileItem.file.name;
});
}
return fileNames;
}
@Visible()
getValue(): any {
return this.uploader.queue.map(fileItem => fileItem._file);
}
getValueAsModel(): any {
throw new UnsupportedOperationError("Unsupported operation");
}
setValue(value: any): any {
throw new UnsupportedOperationError("Unsupported operation");
}
}

View file

@ -31,6 +31,7 @@ import {ProcessListComponent} from "./component/process-list.component";
import {TaskComponent} from "./component/task.component";
import {TaskNotFoundComponent} from "./component/task-not-found.component";
import {FileUploadModule} from "ng2-file-upload";
import {FileUploadV2} from "../../ervu/component/fileupload/FileUploadV2";
registerLocaleData(localeRu);
export const DIRECTIVES = [
@ -49,7 +50,8 @@ export const DIRECTIVES = [
forwardRef(() => TaskListComponent),
forwardRef(() => ProcessListComponent),
forwardRef(() => TaskComponent),
forwardRef(() => TaskNotFoundComponent)
forwardRef(() => TaskNotFoundComponent),
forwardRef(() => FileUploadV2)
];
@NgModule({