mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	settings and localization
This commit is contained in:
		| @@ -1,9 +1,9 @@ | ||||
| import { SettingsService } from './services/settings.service'; | ||||
| import { SettingsService, SETTINGS_KEYS } from './services/settings.service'; | ||||
| import { Component, OnDestroy, OnInit } from '@angular/core'; | ||||
| import { Router } from '@angular/router'; | ||||
| import { Subscription } from 'rxjs'; | ||||
| import { ConsumerStatusService } from './services/consumer-status.service'; | ||||
| import { Toast, ToastService } from './services/toast.service'; | ||||
| import { ToastService } from './services/toast.service'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-root', | ||||
| @@ -12,6 +12,7 @@ import { Toast, ToastService } from './services/toast.service'; | ||||
| }) | ||||
| export class AppComponent implements OnInit, OnDestroy { | ||||
|  | ||||
|   newDocumentSubscription: Subscription; | ||||
|   successSubscription: Subscription; | ||||
|   failedSubscription: Subscription; | ||||
|  | ||||
| @@ -23,23 +24,47 @@ export class AppComponent implements OnInit, OnDestroy { | ||||
|  | ||||
|   ngOnDestroy(): void { | ||||
|     this.consumerStatusService.disconnect() | ||||
|     this.successSubscription.unsubscribe() | ||||
|     this.failedSubscription.unsubscribe() | ||||
|     if (this.successSubscription) { | ||||
|       this.successSubscription.unsubscribe() | ||||
|     } | ||||
|     if (this.failedSubscription) { | ||||
|       this.failedSubscription.unsubscribe() | ||||
|     } | ||||
|     if (this.newDocumentSubscription) { | ||||
|       this.newDocumentSubscription.unsubscribe() | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private showNotification(key) { | ||||
|     if (this.router.url == '/dashboard' && this.settings.get(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUPPRESS_ON_DASHBOARD)) { | ||||
|       return false | ||||
|     } | ||||
|     return this.settings.get(key) | ||||
|   } | ||||
|  | ||||
|   ngOnInit(): void { | ||||
|     this.consumerStatusService.connect() | ||||
|  | ||||
|      | ||||
|     this.successSubscription = this.consumerStatusService.onDocumentConsumptionFinished().subscribe(status => { | ||||
|       this.toastService.show({title: "Document added", delay: 10000, content: `Document ${status.filename} was added to paperless.`, actionName: "Open document", action: () => { | ||||
|         this.router.navigate(['documents', status.documentId]) | ||||
|       }}) | ||||
|       if (this.showNotification(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUCCESS)) { | ||||
|         this.toastService.show({title: $localize`Document added`, delay: 10000, content: $localize`Document ${status.filename} was added to paperless.`, actionName: $localize`Open document`, action: () => { | ||||
|           this.router.navigate(['documents', status.documentId]) | ||||
|         }}) | ||||
|       } | ||||
|     }) | ||||
|  | ||||
|     this.failedSubscription = this.consumerStatusService.onDocumentConsumptionFailed().subscribe(status => { | ||||
|       this.toastService.showError(`Could not consume ${status.filename}: ${status.message}`) | ||||
|       if (this.showNotification(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_FAILED)) { | ||||
|         this.toastService.showError($localize`Could not add ${status.filename}\: ${status.message}`) | ||||
|       } | ||||
|     }) | ||||
|  | ||||
|     this.newDocumentSubscription = this.consumerStatusService.onDocumentDetected().subscribe(status => { | ||||
|       if (this.showNotification(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_NEW_DOCUMENT)) { | ||||
|         this.toastService.show({title: $localize`New document detected`, delay: 5000, content: $localize`Document ${status.filename} is being processed by paperless.`}) | ||||
|       } | ||||
|     }) | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <app-widget-frame title="Upload new documents" i18n-title [class.has-multiple-status]="(getStatus().length + getStatusesHidden().length)> 1"> | ||||
|   <div header-buttons> | ||||
|     <button type="button" class="btn btn-link dismiss-all" [disabled]="!getStatus().length" (click)="dismissAll()"> | ||||
|       <small class="mr-1">Hide all</small> | ||||
|       <small class="mr-1" i18n>Dismiss completed</small> | ||||
|       <svg xmlns="http://www.w3.org/2000/svg" width="1rem" height="1rem" fill="currentColor" class="bi bi-check2-all" viewBox="0 0 16 16"> | ||||
|         <path d="M12.354 4.354a.5.5 0 0 0-.708-.708L5 10.293 1.854 7.146a.5.5 0 1 0-.708.708l3.5 3.5a.5.5 0 0 0 .708 0l7-7zm-4.208 7l-.896-.897.707-.707.543.543 6.646-6.647a.5.5 0 0 1 .708.708l-7 7a.5.5 0 0 1-.708 0z"/> | ||||
|         <path d="M5.354 7.146l.896.897-.707.707-.897-.896a.5.5 0 1 1 .708-.708z"/> | ||||
| @@ -37,7 +37,7 @@ | ||||
|     <ngb-progressbar [value]="status.getProgress()" [max]="1" [type]="getStatusColor(status)"></ngb-progressbar> | ||||
|     <div *ngIf="isFinished(status)"> | ||||
|       <button *ngIf="status.documentId" class="btn btn-sm btn-outline-primary btn-open" routerLink="/documents/{{status.documentId}}" (click)="dismiss(status)"> | ||||
|         <small>Open document</small> | ||||
|         <small i18n>Open document</small> | ||||
|         <svg xmlns="http://www.w3.org/2000/svg" width="1rem" height="1rem" fill="currentColor" class="bi bi-arrow-right-short" viewBox="0 0 16 16"> | ||||
|           <path fill-rule="evenodd" d="M4 8a.5.5 0 0 1 .5-.5h5.793L8.146 5.354a.5.5 0 1 1 .708-.708l3 3a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708-.708L10.293 8.5H4.5A.5.5 0 0 1 4 8z"/> | ||||
|         </svg> | ||||
|   | ||||
| @@ -99,6 +99,20 @@ | ||||
|           </div> | ||||
|         </div> | ||||
|  | ||||
|         <h4 class="mt-4" i18n>Notifications</h4> | ||||
|  | ||||
|         <div class="form-row form-group"> | ||||
|           <div class="col-md-3 col-form-label"> | ||||
|             <span i18n>Consumer status</span> | ||||
|           </div> | ||||
|           <div class="col"> | ||||
|             <app-input-check i18n-title title="Show notifications when new documents are detected" formControlName="notificationsConsumerNewDocument"></app-input-check> | ||||
|             <app-input-check i18n-title title="Show notifications when document consumption completes successfully" formControlName="notificationsConsumerSuccess"></app-input-check> | ||||
|             <app-input-check i18n-title title="Show notifications when document consumption fails" formControlName="notificationsConsumerFailed"></app-input-check> | ||||
|             <app-input-check i18n-title title="Suppress notifications on dashboard" formControlName="notificationsConsumerSuppressOnDashboard" i18n-hint hint="This will suppress all consumer related status messages on the dashboard."></app-input-check> | ||||
|           </div> | ||||
|         </div> | ||||
|  | ||||
|         <h4 class="mt-4" i18n>Bulk editing</h4> | ||||
|  | ||||
|         <div class="form-row form-group"> | ||||
|   | ||||
| @@ -26,6 +26,10 @@ export class SettingsComponent implements OnInit { | ||||
|     'displayLanguage': new FormControl(this.settings.getLanguage()), | ||||
|     'dateLocale': new FormControl(this.settings.get(SETTINGS_KEYS.DATE_LOCALE)), | ||||
|     'dateFormat': new FormControl(this.settings.get(SETTINGS_KEYS.DATE_FORMAT)), | ||||
|     'notificationsConsumerNewDocument': new FormControl(this.settings.get(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_NEW_DOCUMENT)), | ||||
|     'notificationsConsumerSuccess': new FormControl(this.settings.get(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUCCESS)), | ||||
|     'notificationsConsumerFailed': new FormControl(this.settings.get(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_FAILED)), | ||||
|     'notificationsConsumerSuppressOnDashboard': new FormControl(this.settings.get(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUPPRESS_ON_DASHBOARD)), | ||||
|   }) | ||||
|  | ||||
|   savedViews: PaperlessSavedView[] | ||||
| @@ -73,6 +77,10 @@ export class SettingsComponent implements OnInit { | ||||
|     this.settings.set(SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, this.settingsForm.value.useNativePdfViewer) | ||||
|     this.settings.set(SETTINGS_KEYS.DATE_LOCALE, this.settingsForm.value.dateLocale) | ||||
|     this.settings.set(SETTINGS_KEYS.DATE_FORMAT, this.settingsForm.value.dateFormat) | ||||
|     this.settings.set(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_NEW_DOCUMENT, this.settingsForm.value.notificationsConsumerNewDocument) | ||||
|     this.settings.set(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUCCESS, this.settingsForm.value.notificationsConsumerSuccess) | ||||
|     this.settings.set(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_FAILED, this.settingsForm.value.notificationsConsumerFailed) | ||||
|     this.settings.set(SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUPPRESS_ON_DASHBOARD, this.settingsForm.value.notificationsConsumerSuppressOnDashboard) | ||||
|     this.settings.setLanguage(this.settingsForm.value.displayLanguage) | ||||
|     this.documentListViewService.updatePageSize() | ||||
|     this.settings.updateDarkModeSettings() | ||||
|   | ||||
| @@ -65,19 +65,21 @@ export class ConsumerStatusService { | ||||
|  | ||||
|   private consumerStatus: FileStatus[] = [] | ||||
|  | ||||
|  | ||||
|   private documentDetectedSubject = new Subject<FileStatus>() | ||||
|   private documentConsumptionFinishedSubject = new Subject<FileStatus>() | ||||
|   private documentConsumptionFailedSubject = new Subject<FileStatus>() | ||||
|  | ||||
|   private get(taskId: string, filename?: string) { | ||||
|     let status = this.consumerStatus.find(e => e.taskId == taskId) || this.consumerStatus.find(e => e.filename == filename && e.taskId == null) | ||||
|     let created = false | ||||
|     if (!status) { | ||||
|       status = new FileStatus() | ||||
|       this.consumerStatus.push(status) | ||||
|       created = true | ||||
|     } | ||||
|     status.taskId = taskId | ||||
|     status.filename = filename | ||||
|     return status | ||||
|     return {'status': status, 'created': created} | ||||
|   } | ||||
|  | ||||
|   newFileUpload(filename: string): FileStatus { | ||||
| @@ -101,11 +103,17 @@ export class ConsumerStatusService { | ||||
|     this.statusWebSocked.onmessage = (ev) => { | ||||
|       let statusMessage: WebsocketConsumerStatusMessage = JSON.parse(ev['data']) | ||||
|  | ||||
|       let status = this.get(statusMessage.task_id, statusMessage.filename) | ||||
|       let statusMessageGet = this.get(statusMessage.task_id, statusMessage.filename) | ||||
|       let status = statusMessageGet.status | ||||
|       let created = statusMessageGet.created | ||||
|  | ||||
|       status.updateProgress(FileStatusPhase.PROCESSING, statusMessage.current_progress, statusMessage.max_progress) | ||||
|       status.message = statusMessage.message | ||||
|       status.documentId = statusMessage.document_id | ||||
|  | ||||
|       if (created && statusMessage.status == 'STARTING') { | ||||
|         this.documentDetectedSubject.next(status) | ||||
|       } | ||||
|       if (statusMessage.status == "SUCCESS") { | ||||
|         status.phase = FileStatusPhase.SUCCESS | ||||
|         this.documentConsumptionFinishedSubject.next(status) | ||||
| @@ -150,4 +158,8 @@ export class ConsumerStatusService { | ||||
|     return this.documentConsumptionFailedSubject | ||||
|   } | ||||
|  | ||||
|   onDocumentDetected() { | ||||
|     return this.documentDetectedSubject | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -23,7 +23,11 @@ export const SETTINGS_KEYS = { | ||||
|   DARK_MODE_ENABLED: 'general-settings:dark-mode:enabled', | ||||
|   USE_NATIVE_PDF_VIEWER: 'general-settings:document-details:native-pdf-viewer', | ||||
|   DATE_LOCALE: 'general-settings:date-display:date-locale', | ||||
|   DATE_FORMAT: 'general-settings:date-display:date-format' | ||||
|   DATE_FORMAT: 'general-settings:date-display:date-format', | ||||
|   NOTIFICATIONS_CONSUMER_NEW_DOCUMENT: 'general-settings:notifications:consumer-new-documents', | ||||
|   NOTIFICATIONS_CONSUMER_SUCCESS: 'general-settings:notifications:consumer-success', | ||||
|   NOTIFICATIONS_CONSUMER_FAILED: 'general-settings:notifications:consumer-failed', | ||||
|   NOTIFICATIONS_CONSUMER_SUPPRESS_ON_DASHBOARD: 'general-settings:notifications:consumer-suppress-on-dashboard', | ||||
| } | ||||
|  | ||||
| const SETTINGS: PaperlessSettings[] = [ | ||||
| @@ -34,7 +38,11 @@ const SETTINGS: PaperlessSettings[] = [ | ||||
|   {key: SETTINGS_KEYS.DARK_MODE_ENABLED, type: "boolean", default: false}, | ||||
|   {key: SETTINGS_KEYS.USE_NATIVE_PDF_VIEWER, type: "boolean", default: false}, | ||||
|   {key: SETTINGS_KEYS.DATE_LOCALE, type: "string", default: ""}, | ||||
|   {key: SETTINGS_KEYS.DATE_FORMAT, type: "string", default: "mediumDate"} | ||||
|   {key: SETTINGS_KEYS.DATE_FORMAT, type: "string", default: "mediumDate"}, | ||||
|   {key: SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_NEW_DOCUMENT, type: "boolean", default: true}, | ||||
|   {key: SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUCCESS, type: "boolean", default: true}, | ||||
|   {key: SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_FAILED, type: "boolean", default: true}, | ||||
|   {key: SETTINGS_KEYS.NOTIFICATIONS_CONSUMER_SUPPRESS_ON_DASHBOARD, type: "boolean", default: true}, | ||||
| ] | ||||
|  | ||||
| @Injectable({ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 jonaswinkler
					jonaswinkler