mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Refactor uploads to service, working global dd
This commit is contained in:
		| @@ -1,3 +1,11 @@ | ||||
| <app-toasts></app-toasts> | ||||
|  | ||||
| <router-outlet></router-outlet> | ||||
| <ngx-file-drop dropZoneClassName="main-dropzone" contentClassName="main-content" [disabled]="!dragDropEnabled" | ||||
| (onFileDrop)="dropped($event)" (onFileOver)="fileOver()" (onFileLeave)="fileLeave()"> | ||||
|     <ng-template ngx-file-drop-content-tmp> | ||||
|         <div class="global-dropzone-overlay"> | ||||
|             <h1 class="display-6">Drop files to begin upload</h1> | ||||
|         </div> | ||||
|         <router-outlet></router-outlet> | ||||
|     </ng-template> | ||||
| </ngx-file-drop> | ||||
| @@ -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) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
| @@ -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) | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										16
									
								
								src-ui/src/app/services/upload-documents.service.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src-ui/src/app/services/upload-documents.service.spec.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -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(); | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										56
									
								
								src-ui/src/app/services/upload-documents.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src-ui/src/app/services/upload-documents.service.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||
|               } | ||||
|             } | ||||
|           }) | ||||
|         }); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -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 { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Michael Shamoon
					Michael Shamoon