From 73cab2af2de7587d2f29a717fffa2f4804096090 Mon Sep 17 00:00:00 2001 From: Michael Shamoon <4887959+shamoon@users.noreply.github.com> Date: Thu, 10 Mar 2022 20:59:09 -0800 Subject: [PATCH] Refactor uploads to service, working global dd --- src-ui/src/app/app.component.html | 10 +++- src-ui/src/app/app.component.ts | 48 +++++++++++++++- .../upload-file-widget.component.scss | 4 ++ .../upload-file-widget.component.ts | 50 ++--------------- .../services/upload-documents.service.spec.ts | 16 ++++++ .../app/services/upload-documents.service.ts | 56 +++++++++++++++++++ src-ui/src/theme.scss | 33 ++++++++++- 7 files changed, 166 insertions(+), 51 deletions(-) create mode 100644 src-ui/src/app/services/upload-documents.service.spec.ts create mode 100644 src-ui/src/app/services/upload-documents.service.ts diff --git a/src-ui/src/app/app.component.html b/src-ui/src/app/app.component.html index d9b7dd09b..68c1692b3 100644 --- a/src-ui/src/app/app.component.html +++ b/src-ui/src/app/app.component.html @@ -1,3 +1,11 @@ - + + +
+

Drop files to begin upload

+
+ +
+
\ No newline at end of file diff --git a/src-ui/src/app/app.component.ts b/src-ui/src/app/app.component.ts index b21c771ae..374467600 100644 --- a/src-ui/src/app/app.component.ts +++ b/src-ui/src/app/app.component.ts @@ -1,9 +1,17 @@ import { SettingsService, SETTINGS_KEYS } from './services/settings.service' -import { Component, OnDestroy, OnInit } from '@angular/core' +import { + Component, + OnDestroy, + OnInit, + Renderer2, + RendererFactory2, +} from '@angular/core' import { Router } from '@angular/router' import { Subscription } from 'rxjs' import { ConsumerStatusService } from './services/consumer-status.service' import { ToastService } from './services/toast.service' +import { NgxFileDropEntry } from 'ngx-file-drop' +import { UploadDocumentsService } from './services/upload-documents.service' @Component({ selector: 'app-root', @@ -15,15 +23,22 @@ export class AppComponent implements OnInit, OnDestroy { successSubscription: Subscription failedSubscription: Subscription + private renderer: Renderer2 + private fileLeaveTimeoutID: any + constructor( private settings: SettingsService, private consumerStatusService: ConsumerStatusService, private toastService: ToastService, - private router: Router + private router: Router, + private uploadDocumentsService: UploadDocumentsService, + rendererFactory: RendererFactory2 ) { let anyWindow = window as any anyWindow.pdfWorkerSrc = 'assets/js/pdf.worker.min.js' this.settings.updateAppearanceSettings() + + this.renderer = rendererFactory.createRenderer(null, null) } ngOnDestroy(): void { @@ -100,4 +115,33 @@ export class AppComponent implements OnInit, OnDestroy { } }) } + + public get dragDropEnabled(): boolean { + return !this.router.url.includes('dashboard') + } + + public fileOver() { + this.renderer.addClass( + document.getElementsByClassName('main-content').item(0), + 'inert' + ) + clearTimeout(this.fileLeaveTimeoutID) + } + + public fileLeave() { + this.fileLeaveTimeoutID = setTimeout(() => { + this.renderer.removeClass( + document.getElementsByClassName('main-content').item(0), + 'inert' + ) + }, 1000) + } + + public dropped(files: NgxFileDropEntry[]) { + this.renderer.removeClass( + document.getElementsByClassName('main-content').item(0), + 'inert' + ) + this.uploadDocumentsService.uploadFiles(files) + } } diff --git a/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.scss b/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.scss index c13a7bd47..8f0640f0f 100644 --- a/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.scss +++ b/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.scss @@ -33,3 +33,7 @@ form { mix-blend-mode: soft-light; pointer-events: none; } + +.ngx-file-drop__drop-zone--over { + background-color: var(--ngx-primary-faded) !important; +} \ No newline at end of file diff --git a/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts b/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts index 6ba6103d3..e2f59a0a4 100644 --- a/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts +++ b/src-ui/src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts @@ -6,7 +6,7 @@ import { FileStatus, FileStatusPhase, } from 'src/app/services/consumer-status.service' -import { DocumentService } from 'src/app/services/rest/document.service' +import { UploadDocumentsService } from 'src/app/services/upload-documents.service' const MAX_ALERTS = 5 @@ -19,8 +19,8 @@ export class UploadFileWidgetComponent implements OnInit { alertsExpanded = false constructor( - private documentService: DocumentService, - private consumerStatusService: ConsumerStatusService + private consumerStatusService: ConsumerStatusService, + private uploadDocumentsService: UploadDocumentsService ) {} getStatus() { @@ -116,48 +116,6 @@ export class UploadFileWidgetComponent implements OnInit { public fileLeave(event) {} public dropped(files: NgxFileDropEntry[]) { - for (const droppedFile of files) { - if (droppedFile.fileEntry.isFile) { - const fileEntry = droppedFile.fileEntry as FileSystemFileEntry - fileEntry.file((file: File) => { - let formData = new FormData() - formData.append('document', file, file.name) - let status = this.consumerStatusService.newFileUpload(file.name) - - status.message = $localize`Connecting...` - - this.documentService.uploadDocument(formData).subscribe( - (event) => { - if (event.type == HttpEventType.UploadProgress) { - status.updateProgress( - FileStatusPhase.UPLOADING, - event.loaded, - event.total - ) - status.message = $localize`Uploading...` - } else if (event.type == HttpEventType.Response) { - status.taskId = event.body['task_id'] - status.message = $localize`Upload complete, waiting...` - } - }, - (error) => { - switch (error.status) { - case 400: { - this.consumerStatusService.fail(status, error.error.document) - break - } - default: { - this.consumerStatusService.fail( - status, - $localize`HTTP error: ${error.status} ${error.statusText}` - ) - break - } - } - } - ) - }) - } - } + this.uploadDocumentsService.uploadFiles(files) } } diff --git a/src-ui/src/app/services/upload-documents.service.spec.ts b/src-ui/src/app/services/upload-documents.service.spec.ts new file mode 100644 index 000000000..de4f6bb2e --- /dev/null +++ b/src-ui/src/app/services/upload-documents.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { UploadDocumentsService } from './upload-documents.service'; + +describe('UploadDocumentsService', () => { + let service: UploadDocumentsService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(UploadDocumentsService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src-ui/src/app/services/upload-documents.service.ts b/src-ui/src/app/services/upload-documents.service.ts new file mode 100644 index 000000000..84f09ff38 --- /dev/null +++ b/src-ui/src/app/services/upload-documents.service.ts @@ -0,0 +1,56 @@ +import { Injectable } from '@angular/core'; +import { HttpEventType } from '@angular/common/http'; +import { FileSystemFileEntry, NgxFileDropEntry } from 'ngx-file-drop'; +import { ConsumerStatusService, FileStatusPhase } from './consumer-status.service'; +import { DocumentService } from './rest/document.service'; + +@Injectable({ + providedIn: 'root' +}) +export class UploadDocumentsService { + + constructor( + private documentService: DocumentService, + private consumerStatusService: ConsumerStatusService + ) { + } + + uploadFiles(files: NgxFileDropEntry[]) { + for (const droppedFile of files) { + if (droppedFile.fileEntry.isFile) { + + const fileEntry = droppedFile.fileEntry as FileSystemFileEntry; + fileEntry.file((file: File) => { + let formData = new FormData() + formData.append('document', file, file.name) + let status = this.consumerStatusService.newFileUpload(file.name) + + status.message = $localize`Connecting...` + + this.documentService.uploadDocument(formData).subscribe(event => { + if (event.type == HttpEventType.UploadProgress) { + status.updateProgress(FileStatusPhase.UPLOADING, event.loaded, event.total) + status.message = $localize`Uploading...` + } else if (event.type == HttpEventType.Response) { + status.taskId = event.body["task_id"] + status.message = $localize`Upload complete, waiting...` + } + + }, error => { + switch (error.status) { + case 400: { + this.consumerStatusService.fail(status, error.error.document) + break; + } + default: { + this.consumerStatusService.fail(status, $localize`HTTP error: ${error.status} ${error.statusText}`) + break; + } + } + }) + }); + } + } + } + +} diff --git a/src-ui/src/theme.scss b/src-ui/src/theme.scss index cb6ee859a..9e43ad662 100644 --- a/src-ui/src/theme.scss +++ b/src-ui/src/theme.scss @@ -244,8 +244,37 @@ table.table { color: var(--bs-body-color); } -.ngx-file-drop__drop-zone--over { - background-color: var(--ngx-primary-faded) !important; +.main-dropzone { + height: 100%; + width: 100%; +} + +.global-dropzone-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: rgba(23, 84, 31, .7); + // z-index: $zindex-modal; // 1055 + z-index: 1055; + opacity: 0; + pointer-events: none !important; + user-select: none !important; + text-align: center; + padding-top: 25%; + transition: opacity 0.2s ease; +} + +.main-dropzone.ngx-file-drop__drop-zone--over { + .global-dropzone-overlay { + opacity: 1; + } +} + +.main-content.inert { + pointer-events: none !important; + user-select: none !important; } .alert-danger {