From c695f5c4419f4fd8d76946d5a474dccbda0edad2 Mon Sep 17 00:00:00 2001 From: Valentin Mihai Date: Mon, 16 May 2022 00:33:50 +0300 Subject: [PATCH] RED-3982 - added upload component --- src/lib/common-ui.module.ts | 7 ++- .../help-mode/help-mode.component.ts | 2 +- .../drag-drop-file-upload.directive.ts | 41 +++++++++++++ .../upload-file/upload-file.component.html | 17 ++++++ .../upload-file/upload-file.component.scss | 58 +++++++++++++++++++ src/lib/upload-file/upload-file.component.ts | 40 +++++++++++++ 6 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 src/lib/upload-file/drag-drop-file-upload.directive.ts create mode 100644 src/lib/upload-file/upload-file.component.html create mode 100644 src/lib/upload-file/upload-file.component.scss create mode 100644 src/lib/upload-file/upload-file.component.ts diff --git a/src/lib/common-ui.module.ts b/src/lib/common-ui.module.ts index c116fa3..d3cb898 100644 --- a/src/lib/common-ui.module.ts +++ b/src/lib/common-ui.module.ts @@ -32,6 +32,8 @@ import { MatDialogModule } from '@angular/material/dialog'; import { CapitalizePipe } from './utils/pipes/capitalize.pipe'; import { KeycloakAngularModule } from 'keycloak-angular'; import { MatCheckboxModule } from '@angular/material/checkbox'; +import { UploadFileComponent } from './upload-file/upload-file.component'; +import { DragDropFileUploadDirective } from './upload-file/drag-drop-file-upload.directive'; const matModules = [MatIconModule, MatProgressSpinnerModule, MatButtonModule, MatDialogModule, MatCheckboxModule]; const modules = [ @@ -57,9 +59,12 @@ const components = [ ToastComponent, SmallChipComponent, ProgressBarComponent, + UploadFileComponent, + DragDropFileUploadDirective, ]; -const pipes = [SortByPipe, HumanizePipe, CapitalizePipe, LogPipe]; + +const pipes = [SortByPipe, HumanizePipe, CapitalizePipe, LogPipe]; @NgModule({ declarations: [...components, ...pipes], imports: [CommonModule, ...matModules, ...modules, FormsModule, ReactiveFormsModule, KeycloakAngularModule], diff --git a/src/lib/help-mode/help-mode/help-mode.component.ts b/src/lib/help-mode/help-mode/help-mode.component.ts index 89a2663..bd6f46d 100644 --- a/src/lib/help-mode/help-mode/help-mode.component.ts +++ b/src/lib/help-mode/help-mode/help-mode.component.ts @@ -38,7 +38,7 @@ export class HelpModeComponent { } } - @HostListener('window:resize') onResize(event: any) { + @HostListener('window:resize') onResize() { if (this.helpModeService.isHelpModeActive) { this.helpModeService.updateHelperElements(); } diff --git a/src/lib/upload-file/drag-drop-file-upload.directive.ts b/src/lib/upload-file/drag-drop-file-upload.directive.ts new file mode 100644 index 0000000..060f21f --- /dev/null +++ b/src/lib/upload-file/drag-drop-file-upload.directive.ts @@ -0,0 +1,41 @@ +import { Directive, EventEmitter, Output, HostListener, HostBinding } from '@angular/core'; + +const DRAG_OVER_BACKGROUND_COLOR = '#e2eefd'; +const DEFAULT_BACKGROUND_COLOR = '#f4f5f7'; + +@Directive({ + selector: '[iqserDragDropFileUpload]', +}) +export class DragDropFileUploadDirective { + @Output() readonly fileDropped = new EventEmitter(); + @HostBinding('style.background-color') private _background = DEFAULT_BACKGROUND_COLOR; + + @HostListener('dragover', ['$event']) + onDragOver(event: DragEvent) { + event.preventDefault(); + event.stopPropagation(); + if (event.dataTransfer?.types.includes('Files')) { + this._background = DRAG_OVER_BACKGROUND_COLOR; + } + } + + @HostListener('dragleave', ['$event']) + onDragLeave(event: DragEvent) { + event.preventDefault(); + event.stopPropagation(); + this._background = DEFAULT_BACKGROUND_COLOR; + } + + @HostListener('drop', ['$event']) + onDrop(event: DragEvent) { + event.preventDefault(); + event.stopPropagation(); + if (event?.dataTransfer?.types.includes('Files')) { + this._background = DEFAULT_BACKGROUND_COLOR; + const files = event.dataTransfer.files; + if (files.length > 0) { + this.fileDropped.emit({ target: { files } }); + } + } + } +} diff --git a/src/lib/upload-file/upload-file.component.html b/src/lib/upload-file/upload-file.component.html new file mode 100644 index 0000000..039f67e --- /dev/null +++ b/src/lib/upload-file/upload-file.component.html @@ -0,0 +1,17 @@ +
+ +
+
+
+ +

{{ file.name }}

+ +
+ + diff --git a/src/lib/upload-file/upload-file.component.scss b/src/lib/upload-file/upload-file.component.scss new file mode 100644 index 0000000..d057e23 --- /dev/null +++ b/src/lib/upload-file/upload-file.component.scss @@ -0,0 +1,58 @@ +@import '../../assets/styles/common-variables'; + +.upload-area, +.file-area { + display: flex; + align-items: center; + border-radius: 8px; + width: 586px; + background: var(--iqser-grey-2); +} + +.upload-area { + gap: 16px; + height: 88px; + cursor: pointer; + + mat-icon, + div { + opacity: 0.5; + transition: 0.1s; + } + + mat-icon { + margin-left: 32px; + } + + div { + font-size: 16px; + font-weight: 500; + } +} + +.file-area { + gap: 10px; + height: 48px; + + mat-icon:first-child { + opacity: 0.5; + margin-left: 16px; + } + + mat-icon:last-child { + margin-left: auto; + margin-right: 16px; + cursor: pointer; + } + + mat-icon { + transform: scale(0.7); + } + + p { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 490px; + } +} diff --git a/src/lib/upload-file/upload-file.component.ts b/src/lib/upload-file/upload-file.component.ts new file mode 100644 index 0000000..cb2a02d --- /dev/null +++ b/src/lib/upload-file/upload-file.component.ts @@ -0,0 +1,40 @@ +import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; + +@Component({ + selector: 'iqser-upload-file', + templateUrl: './upload-file.component.html', + styleUrls: ['./upload-file.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) + +export class UploadFileComponent { + @ViewChild('attachFileInput', { static: true }) attachFileInput: ElementRef; + + @Output() readonly fileChanged = new EventEmitter(); + + file!: File | null; + + triggerAttachFile() { + this.attachFileInput.nativeElement.click(); + } + + attachFile(event) { + const files = event?.target?.files; + this.file = files[0]; + + // input field needs to be set as empty in case the same file will be selected second time + event.target.value = ''; + + if (!this.file) { + console.error('No file to import!'); + return; + } + this.fileChanged.emit(this.file); + } + + removeFile() { + this.file = null; + this.fileChanged.emit(null); + } +}