Merge branch 'feature-websockets-status' into dev

This commit is contained in:
jonaswinkler
2021-01-31 14:37:15 +01:00
45 changed files with 1763 additions and 371 deletions

View File

@@ -2,25 +2,67 @@
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en-US" datatype="plaintext" original="ng2.template">
<body>
<trans-unit id="9103526311244275943" datatype="html">
<source>Document added</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/app.component.ts</context>
<context context-type="linenumber">51</context>
</context-group>
</trans-unit>
<trans-unit id="9204248378636247318" datatype="html">
<source>Document <x id="PH" equiv-text="status.filename"/> was added to paperless.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/app.component.ts</context>
<context context-type="linenumber">51</context>
</context-group>
</trans-unit>
<trans-unit id="1931214133925051574" datatype="html">
<source>Open document</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/app.component.ts</context>
<context context-type="linenumber">51</context>
</context-group>
</trans-unit>
<trans-unit id="8582620835547864448" datatype="html">
<source>Could not add <x id="PH" equiv-text="status.filename"/>: <x id="PH_1" equiv-text="status.message"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/app.component.ts</context>
<context context-type="linenumber">59</context>
</context-group>
</trans-unit>
<trans-unit id="1710712016675379662" datatype="html">
<source>New document detected</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/app.component.ts</context>
<context context-type="linenumber">65</context>
</context-group>
</trans-unit>
<trans-unit id="587031278561344416" datatype="html">
<source>Document <x id="PH" equiv-text="status.filename"/> is being processed by paperless.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/app.component.ts</context>
<context context-type="linenumber">65</context>
</context-group>
</trans-unit>
<trans-unit id="4733307402565258070" datatype="html">
<source>Documents</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.ts</context>
<context context-type="linenumber">43</context>
<context context-type="linenumber">49</context>
</context-group>
</trans-unit>
<trans-unit id="2155249406916744630" datatype="html">
<source>View &quot;<x id="PH" equiv-text="this.list.savedView.name"/>&quot; saved successfully.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.ts</context>
<context context-type="linenumber">94</context>
<context context-type="linenumber">109</context>
</context-group>
</trans-unit>
<trans-unit id="6837554170707123455" datatype="html">
<source>View &quot;<x id="PH" equiv-text="savedView.name"/>&quot; created successfully.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/document-list/document-list.component.ts</context>
<context context-type="linenumber">115</context>
<context context-type="linenumber">130</context>
</context-group>
</trans-unit>
<trans-unit id="9ca82952a6bc860b5391d5975322d8af8ceddfa4" datatype="html">
@@ -482,35 +524,35 @@
<source>Saved view &quot;<x id="PH" equiv-text="savedView.name"/>&quot; deleted.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">63</context>
<context context-type="linenumber">67</context>
</context-group>
</trans-unit>
<trans-unit id="5647210819299459618" datatype="html">
<source>Settings saved successfully.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">79</context>
<context context-type="linenumber">87</context>
</context-group>
</trans-unit>
<trans-unit id="6839066544204061364" datatype="html">
<source>Use system language</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">83</context>
<context context-type="linenumber">91</context>
</context-group>
</trans-unit>
<trans-unit id="7729897675462249787" datatype="html">
<source>Use date format of display language</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">87</context>
<context context-type="linenumber">95</context>
</context-group>
</trans-unit>
<trans-unit id="8488620293789898901" datatype="html">
<source>Error while storing settings on server: <x id="PH" equiv-text="JSON.stringify(error.error)"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.ts</context>
<context context-type="linenumber">103</context>
<context context-type="linenumber">111</context>
</context-group>
</trans-unit>
<trans-unit id="121cc5391cd2a5115bc2b3160379ee5b36cd7716" datatype="html">
@@ -531,7 +573,7 @@
<source>Saved views</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">114</context>
<context context-type="linenumber">128</context>
</context-group>
</trans-unit>
<trans-unit id="bbe41ac2ea4a6c00ea941a41b33105048f8e9f13" datatype="html">
@@ -639,60 +681,109 @@
<context context-type="linenumber">98</context>
</context-group>
</trans-unit>
<trans-unit id="8bcabdf6b16cad0313a86c7e940c5e3ad7f9f8ab" datatype="html">
<source>Notifications</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">102</context>
</context-group>
</trans-unit>
<trans-unit id="69c5a98f8aa92e4db060f10dcd37781c8f40a48f" datatype="html">
<source>Consumer status</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">106</context>
</context-group>
</trans-unit>
<trans-unit id="2ad4d76b36341c589d94004ad2a213fd4d6f5ca0" datatype="html">
<source>Show notifications when new documents are detected</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">109</context>
</context-group>
</trans-unit>
<trans-unit id="f2361d3f65b6c77ef0a15fad8af8e858b043ace3" datatype="html">
<source>Show notifications when document consumption completes successfully</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">110</context>
</context-group>
</trans-unit>
<trans-unit id="2bcbcbe99e207803e21183580b98d90410dd8718" datatype="html">
<source>Show notifications when document consumption fails</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">111</context>
</context-group>
</trans-unit>
<trans-unit id="af113f7c9f7e13145c3461f61a1aedf12d57bd71" datatype="html">
<source>Suppress notifications on dashboard</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">112</context>
</context-group>
</trans-unit>
<trans-unit id="59fe5c9233a2aaab3079a2300e4dfa439ddb1890" datatype="html">
<source>This will suppress all consumer related status messages on the dashboard.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">112</context>
</context-group>
</trans-unit>
<trans-unit id="3863a86cd9e69a61d143d3daf51df44203df4a82" datatype="html">
<source>Bulk editing</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">102</context>
<context context-type="linenumber">116</context>
</context-group>
</trans-unit>
<trans-unit id="c0ac61661c6c326d6e0e00c231b95cf2ac0c6586" datatype="html">
<source>Show confirmation dialogs</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">106</context>
<context context-type="linenumber">120</context>
</context-group>
</trans-unit>
<trans-unit id="291bbe56ecbe945dcf05580a57d679fa7bd1e06a" datatype="html">
<source>Deleting documents will always ask for confirmation.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">106</context>
<context context-type="linenumber">120</context>
</context-group>
</trans-unit>
<trans-unit id="8cfddc13e04f5545ac63f419ef363505d6f78c2e" datatype="html">
<source>Apply on close</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">107</context>
<context context-type="linenumber">121</context>
</context-group>
</trans-unit>
<trans-unit id="8cb90334f5dfd7fc67205085f59381e2a334ccfc" datatype="html">
<source>Appears on</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">126</context>
<context context-type="linenumber">140</context>
</context-group>
</trans-unit>
<trans-unit id="6717cf1acf04728fc2b7c39f6d3297f8ff15fde5" datatype="html">
<source>Show on dashboard</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">129</context>
<context context-type="linenumber">143</context>
</context-group>
</trans-unit>
<trans-unit id="541bfc5b123b3f8867fd681eaceefb663a811973" datatype="html">
<source>Show in sidebar</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">133</context>
<context context-type="linenumber">147</context>
</context-group>
</trans-unit>
<trans-unit id="abba764a7a595d04dc8c3b26e04b3780d4fdb540" datatype="html">
<source>No saved views defined.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/manage/settings/settings.component.html</context>
<context context-type="linenumber">143</context>
<context context-type="linenumber">157</context>
</context-group>
</trans-unit>
<trans-unit id="ef60a738a565f498b858e903e42bc5ffc3cc1299" datatype="html">
@@ -1330,25 +1421,46 @@
<context context-type="linenumber">4</context>
</context-group>
</trans-unit>
<trans-unit id="8705589528094706681" datatype="html">
<source>The document has been uploaded and will be processed by the consumer shortly.</source>
<trans-unit id="6443586946875325554" datatype="html">
<source>Processing: <x id="PH" equiv-text="countUploadingAndProcessing"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts</context>
<context context-type="linenumber">63</context>
<context context-type="linenumber">32</context>
</context-group>
</trans-unit>
<trans-unit id="4956689020592747108" datatype="html">
<source>There was an error while uploading the document: <x id="PH" equiv-text="error.error.document"/></source>
<trans-unit id="9182918211699394982" datatype="html">
<source>Failed: <x id="PH" equiv-text="countFailed"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts</context>
<context context-type="linenumber">71</context>
<context context-type="linenumber">35</context>
</context-group>
</trans-unit>
<trans-unit id="7554858521017940575" datatype="html">
<source>An error has occurred while uploading the document. Sorry!</source>
<trans-unit id="534116346205124059" datatype="html">
<source>Added: <x id="PH" equiv-text="countSuccess"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts</context>
<context context-type="linenumber">75</context>
<context context-type="linenumber">38</context>
</context-group>
</trans-unit>
<trans-unit id="3852289441366561594" datatype="html">
<source>Connecting...</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts</context>
<context context-type="linenumber">118</context>
</context-group>
</trans-unit>
<trans-unit id="1245343823699368872" datatype="html">
<source>Uploading...</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts</context>
<context context-type="linenumber">123</context>
</context-group>
</trans-unit>
<trans-unit id="3994065460580948013" datatype="html">
<source>Waiting for consumer...</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.ts</context>
<context context-type="linenumber">126</context>
</context-group>
</trans-unit>
<trans-unit id="e022072b3e4dd77e3f09960817ef3359a49963b3" datatype="html">
@@ -1362,21 +1474,35 @@
<source>Drop documents here or</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html</context>
<context context-type="linenumber">5</context>
<context context-type="linenumber">13</context>
</context-group>
</trans-unit>
<trans-unit id="865c511f4a24558ed0e954f9bbbff557bbb8954d" datatype="html">
<source>Browse files</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html</context>
<context context-type="linenumber">5</context>
<context context-type="linenumber">13</context>
</context-group>
</trans-unit>
<trans-unit id="33c76d75ce25ce3b05ab22877f1b6b09dcf603ae" datatype="html">
<source>{VAR_PLURAL, plural, =1 {Uploading file...} =other {Uploading <x id="INTERPOLATION"/> files...}}</source>
<trans-unit id="bd4a8607e4a002d939cffb347ec056664dfb2c73" datatype="html">
<source>Dismiss completed</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html</context>
<context context-type="linenumber">13</context>
<context context-type="linenumber">4</context>
</context-group>
</trans-unit>
<trans-unit id="1fc4e0a1e93fdda0ed3c9e590971d283afb68265" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{getStatusHidden().length}}"/> more hidden</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html</context>
<context context-type="linenumber">24</context>
</context-group>
</trans-unit>
<trans-unit id="710254a196a2649674438edf8a15b7ab1f48271b" datatype="html">
<source>Open document</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html</context>
<context context-type="linenumber">41</context>
</context-group>
</trans-unit>
<trans-unit id="45854ddec74086b271e62be6a363f4fa5036f7fc" datatype="html">
@@ -1474,42 +1600,133 @@
<source>English (US)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">74</context>
<context context-type="linenumber">82</context>
</context-group>
</trans-unit>
<trans-unit id="1858110241312746425" datatype="html">
<source>German</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">75</context>
<context context-type="linenumber">83</context>
</context-group>
</trans-unit>
<trans-unit id="3071065188816255493" datatype="html">
<source>Dutch</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">76</context>
<context context-type="linenumber">84</context>
</context-group>
</trans-unit>
<trans-unit id="7633754075223722162" datatype="html">
<source>French</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/settings.service.ts</context>
<context context-type="linenumber">77</context>
<context context-type="linenumber">85</context>
</context-group>
</trans-unit>
<trans-unit id="2119857572761283468" datatype="html">
<source>Document already exists.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/consumer-status.service.ts</context>
<context context-type="linenumber">14</context>
</context-group>
</trans-unit>
<trans-unit id="148389968432135849" datatype="html">
<source>File not found.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/consumer-status.service.ts</context>
<context context-type="linenumber">15</context>
</context-group>
</trans-unit>
<trans-unit id="1520671543092565667" datatype="html">
<source>Pre-consume script does not exist.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/consumer-status.service.ts</context>
<context context-type="linenumber">16</context>
</context-group>
</trans-unit>
<trans-unit id="7742915911032564889" datatype="html">
<source>Error while executing pre-consume script.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/consumer-status.service.ts</context>
<context context-type="linenumber">17</context>
</context-group>
</trans-unit>
<trans-unit id="8995193730018060346" datatype="html">
<source>Post-consume script does not exist.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/consumer-status.service.ts</context>
<context context-type="linenumber">18</context>
</context-group>
</trans-unit>
<trans-unit id="256773668518189604" datatype="html">
<source>Error while executing post-consume script.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/consumer-status.service.ts</context>
<context context-type="linenumber">19</context>
</context-group>
</trans-unit>
<trans-unit id="6252258095055634191" datatype="html">
<source>Received new file.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/consumer-status.service.ts</context>
<context context-type="linenumber">20</context>
</context-group>
</trans-unit>
<trans-unit id="7337565919209746135" datatype="html">
<source>File type not supported.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/consumer-status.service.ts</context>
<context context-type="linenumber">21</context>
</context-group>
</trans-unit>
<trans-unit id="5002399167376099234" datatype="html">
<source>Processing document...</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/consumer-status.service.ts</context>
<context context-type="linenumber">22</context>
</context-group>
</trans-unit>
<trans-unit id="1085975194762600381" datatype="html">
<source>Generating thumbnail...</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/consumer-status.service.ts</context>
<context context-type="linenumber">23</context>
</context-group>
</trans-unit>
<trans-unit id="3280851677698431426" datatype="html">
<source>Retrieving date from document...</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/consumer-status.service.ts</context>
<context context-type="linenumber">24</context>
</context-group>
</trans-unit>
<trans-unit id="7162102384876037296" datatype="html">
<source>Saving document...</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/consumer-status.service.ts</context>
<context context-type="linenumber">25</context>
</context-group>
</trans-unit>
<trans-unit id="4550450765009165976" datatype="html">
<source>Finished.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/consumer-status.service.ts</context>
<context context-type="linenumber">26</context>
</context-group>
</trans-unit>
<trans-unit id="1519954996184640001" datatype="html">
<source>Error</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/toast.service.ts</context>
<context context-type="linenumber">31</context>
<context context-type="linenumber">35</context>
</context-group>
</trans-unit>
<trans-unit id="5037437391296624618" datatype="html">
<source>Information</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/services/toast.service.ts</context>
<context context-type="linenumber">35</context>
<context context-type="linenumber">39</context>
</context-group>
</trans-unit>
<trans-unit id="7517688192215738656" datatype="html">

View File

@@ -1,17 +1,70 @@
import { Component } from '@angular/core';
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 { ToastService } from './services/toast.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
export class AppComponent implements OnInit, OnDestroy {
constructor (private settings: SettingsService) {
newDocumentSubscription: Subscription;
successSubscription: Subscription;
failedSubscription: Subscription;
constructor (private settings: SettingsService, private consumerStatusService: ConsumerStatusService, private toastService: ToastService, private router: Router) {
let anyWindow = (window as any)
anyWindow.pdfWorkerSrc = '/assets/js/pdf.worker.min.js';
this.settings.updateDarkModeSettings()
}
ngOnDestroy(): void {
this.consumerStatusService.disconnect()
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 => {
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 => {
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.`})
}
})
}
}

View File

@@ -3,5 +3,6 @@
[header]="toast.title" [autohide]="true" [delay]="toast.delay"
[class]="toast.classname"
(hide)="toastService.closeToast(toast)">
{{toast.content}}
</ngb-toast>
<p>{{toast.content}}</p>
<p *ngIf="toast.action"><button class="btn btn-sm btn-outline-secondary" (click)="toastService.closeToast(toast); toast.action()">{{toast.actionName}}</button></p>
</ngb-toast>

View File

@@ -19,6 +19,6 @@
<app-statistics-widget></app-statistics-widget>
<app-upload-file-widget></app-upload-file-widget>
</div>
</div>

View File

@@ -18,4 +18,4 @@
</tbody>
</table>
</app-widget-frame>
</app-widget-frame>

View File

@@ -1,8 +1,10 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { PaperlessDocument } from 'src/app/data/paperless-document';
import { PaperlessSavedView } from 'src/app/data/paperless-saved-view';
import { DocumentListViewService } from 'src/app/services/document-list-view.service';
import { ConsumerStatusService } from 'src/app/services/consumer-status.service';
import { DocumentService } from 'src/app/services/rest/document.service';
@Component({
@@ -15,14 +17,28 @@ export class SavedViewWidgetComponent implements OnInit {
constructor(
private documentService: DocumentService,
private router: Router,
private list: DocumentListViewService) { }
private list: DocumentListViewService,
private consumerStatusService: ConsumerStatusService) { }
@Input()
savedView: PaperlessSavedView
documents: PaperlessDocument[] = []
subscription: Subscription
ngOnInit(): void {
this.reload()
this.subscription = this.consumerStatusService.onDocumentConsumptionFinished().subscribe(status => {
this.reload()
})
}
ngOnDestroy(): void {
this.subscription.unsubscribe()
}
reload() {
this.documentService.listFiltered(1,10,this.savedView.sort_field, this.savedView.sort_reverse, this.savedView.filter_rules).subscribe(result => {
this.documents = result.results
})

View File

@@ -3,4 +3,4 @@
<p class="card-text" i18n>Documents in inbox: {{statistics.documents_inbox}}</p>
<p class="card-text" i18n>Total documents: {{statistics.documents_total}}</p>
</ng-container>
</app-widget-frame>
</app-widget-frame>

View File

@@ -23,7 +23,7 @@ export class StatisticsWidgetComponent implements OnInit {
getStatistics(): Observable<Statistics> {
return this.http.get(`${environment.apiBaseUrl}statistics/`)
}
ngOnInit(): void {
this.getStatistics().subscribe(statistics => {
this.statistics = statistics

View File

@@ -1,18 +1,48 @@
<app-widget-frame title="Upload new documents" i18n-title>
<div header-buttons>
<a *ngIf="getStatusCompleted().length > 0" (click)="dismissAll()" [routerLink]="" >
<span i18n>Dismiss completed</span>&nbsp;
<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"/>
</svg>
</a>
</div>
<div content>
<form>
<ngx-file-drop dropZoneLabel="Drop documents here or" browseBtnLabel="Browse files" (onFileDrop)="dropped($event)"
(onFileOver)="fileOver($event)" (onFileLeave)="fileLeave($event)" dropZoneClassName="bg-light card"
multiple="true" contentClassName="justify-content-center d-flex align-items-center p-5" [showBrowseBtn]=true
multiple="true" contentClassName="justify-content-center d-flex align-items-center py-5 px-2" [showBrowseBtn]=true
browseBtnClassName="btn btn-sm btn-outline-primary ml-2" i18n-dropZoneLabel i18n-browseBtnLabel>
</ngx-file-drop>
</form>
<div *ngIf="uploadVisible" class="mt-3">
<p i18n>{uploadStatus.length, plural, =1 {Uploading file...} =other {Uploading {{uploadStatus.length}} files...}}</p>
<ngb-progressbar [value]="loadedSum" [max]="totalSum" [striped]="true" [animated]="uploadStatus.length > 0">
</ngb-progressbar>
<p class="mt-3" *ngIf="getStatus().length > 0">{{getStatusSummary()}}</p>
<div *ngFor="let status of getStatus()">
<ng-container [ngTemplateOutlet]="consumerAlert" [ngTemplateOutletContext]="{ $implicit: status }"></ng-container>
</div>
<div *ngIf="getStatusHidden().length" class="alerts-hidden">
<p *ngIf="!alertsExpanded" class="mt-3 mb-0 text-center"><span i18n>{{getStatusHidden().length}} more hidden</span> <button class="btn btn-sm btn-link py-0" (click)="alertsExpanded = !alertsExpanded" aria-controls="hiddenAlerts" [attr.aria-expanded]="alertsExpanded" i18n>Show all</button></p>
<div #hiddenAlerts="ngbCollapse" [(ngbCollapse)]="!alertsExpanded">
<div *ngFor="let status of getStatusHidden()">
<ng-container [ngTemplateOutlet]="consumerAlert" [ngTemplateOutletContext]="{ $implicit: status }"></ng-container>
</div>
</div>
</div>
</div>
</app-widget-frame>
</app-widget-frame>
<ng-template #consumerAlert let-status>
<ngb-alert type="secondary" class="mt-2 mb-0" [dismissible]="isFinished(status)" (closed)="dismiss(status)">
<h6 class="alert-heading">{{status.filename}}</h6>
<p class="mb-0 pb-1" *ngIf="!isFinished(status) || (isFinished(status) && !status.documentId)">{{status.message}}</p>
<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 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>
</button>
</div>
</ngb-alert>
</ng-template>

View File

@@ -0,0 +1,35 @@
@import "/src/theme";
form {
position: relative;
}
.alert-heading {
font-size: 80%;
font-weight: bold;
}
.alerts-hidden {
.btn {
line-height: 1;
}
}
.btn-open {
line-height: 1;
svg {
margin-top: -1px;
}
}
::ng-deep .progress {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
height: auto;
mix-blend-mode: soft-light;
pointer-events: none;
}

View File

@@ -1,14 +1,10 @@
import { HttpEventType } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { FileSystemFileEntry, NgxFileDropEntry } from 'ngx-file-drop';
import { ConsumerStatusService, FileStatus, FileStatusPhase } from 'src/app/services/consumer-status.service';
import { DocumentService } from 'src/app/services/rest/document.service';
import { ToastService } from 'src/app/services/toast.service';
interface UploadStatus {
loaded: number
total: number
}
const MAX_ALERTS = 5
@Component({
selector: 'app-upload-file-widget',
@@ -16,8 +12,89 @@ interface UploadStatus {
styleUrls: ['./upload-file-widget.component.scss']
})
export class UploadFileWidgetComponent implements OnInit {
alertsExpanded = false
constructor(private documentService: DocumentService, private toastService: ToastService) { }
constructor(
private documentService: DocumentService,
private consumerStatusService: ConsumerStatusService
) { }
getStatus() {
return this.consumerStatusService.getConsumerStatus().slice(0, MAX_ALERTS)
}
getStatusSummary() {
let strings = []
let countUploadingAndProcessing = this.consumerStatusService.getConsumerStatusNotCompleted().length
let countFailed = this.getStatusFailed().length
let countSuccess = this.getStatusSuccess().length
if (countUploadingAndProcessing > 0) {
strings.push($localize`Processing: ${countUploadingAndProcessing}`)
}
if (countFailed > 0) {
strings.push($localize`Failed: ${countFailed}`)
}
if (countSuccess > 0) {
strings.push($localize`Added: ${countSuccess}`)
}
return strings.join($localize`:this string is used to separate processing, failed and added on the file upload widget:, `)
}
getStatusHidden() {
if (this.consumerStatusService.getConsumerStatus().length < MAX_ALERTS) return []
else return this.consumerStatusService.getConsumerStatus().slice(MAX_ALERTS)
}
getStatusUploading() {
return this.consumerStatusService.getConsumerStatus(FileStatusPhase.UPLOADING)
}
getStatusFailed() {
return this.consumerStatusService.getConsumerStatus(FileStatusPhase.FAILED)
}
getStatusSuccess() {
return this.consumerStatusService.getConsumerStatus(FileStatusPhase.SUCCESS)
}
getStatusCompleted() {
return this.consumerStatusService.getConsumerStatusCompleted()
}
getTotalUploadProgress() {
let current = 0
let max = 0
this.getStatusUploading().forEach(status => {
current += status.currentPhaseProgress
max += status.currentPhaseMaxProgress
})
return current / Math.max(max, 1)
}
isFinished(status: FileStatus) {
return status.phase == FileStatusPhase.FAILED || status.phase == FileStatusPhase.SUCCESS
}
getStatusColor(status: FileStatus) {
switch (status.phase) {
case FileStatusPhase.PROCESSING:
case FileStatusPhase.UPLOADING:
return "primary"
case FileStatusPhase.FAILED:
return "danger"
case FileStatusPhase.SUCCESS:
return "success"
}
}
dismiss(status: FileStatus) {
this.consumerStatusService.dismiss(status)
}
dismissAll() {
this.consumerStatusService.dismissAll()
}
ngOnInit(): void {
}
@@ -28,54 +105,39 @@ export class UploadFileWidgetComponent implements OnInit {
public fileLeave(event){
}
uploadStatus: UploadStatus[] = []
completedFiles = 0
uploadVisible = false
get loadedSum() {
return this.uploadStatus.map(s => s.loaded).reduce((a,b) => a+b, this.completedFiles > 0 ? 1 : 0)
}
get totalSum() {
return this.uploadStatus.map(s => s.total).reduce((a,b) => a+b, 1)
}
public dropped(files: NgxFileDropEntry[]) {
for (const droppedFile of files) {
if (droppedFile.fileEntry.isFile) {
let uploadStatusObject: UploadStatus = {loaded: 0, total: 1}
this.uploadStatus.push(uploadStatusObject)
this.uploadVisible = true
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) {
uploadStatusObject.loaded = event.loaded
uploadStatusObject.total = event.total
status.updateProgress(FileStatusPhase.UPLOADING, event.loaded, event.total)
status.message = $localize`Uploading...`
} else if (event.type == HttpEventType.Response) {
this.uploadStatus.splice(this.uploadStatus.indexOf(uploadStatusObject), 1)
this.completedFiles += 1
this.toastService.showInfo($localize`The document has been uploaded and will be processed by the consumer shortly.`)
status.taskId = event.body["task_id"]
status.message = $localize`Waiting for consumer...`
}
}, error => {
this.uploadStatus.splice(this.uploadStatus.indexOf(uploadStatusObject), 1)
this.completedFiles += 1
switch (error.status) {
case 400: {
this.toastService.showInfo($localize`There was an error while uploading the document: ${error.error.document}`)
this.consumerStatusService.fail(status, error.error.document)
break;
}
default: {
this.toastService.showInfo($localize`An error has occurred while uploading the document. Sorry!`)
this.consumerStatusService.fail(status, `${error.status} ${error.statusText}`)
break;
}
}
})
});
}

View File

@@ -1,9 +1,11 @@
import { AfterViewInit, Component, OnInit, QueryList, ViewChild, ViewChildren } from '@angular/core';
import { AfterViewInit, Component, OnDestroy, OnInit, QueryList, ViewChild, ViewChildren } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { Subscription } from 'rxjs';
import { PaperlessDocument } from 'src/app/data/paperless-document';
import { PaperlessSavedView } from 'src/app/data/paperless-saved-view';
import { SortableDirective, SortEvent } from 'src/app/directives/sortable.directive';
import { ConsumerStatusService } from 'src/app/services/consumer-status.service';
import { DocumentListViewService } from 'src/app/services/document-list-view.service';
import { DOCUMENT_SORT_FIELDS } from 'src/app/services/rest/document.service';
import { SavedViewService } from 'src/app/services/rest/saved-view.service';
@@ -16,7 +18,7 @@ import { SaveViewConfigDialogComponent } from './save-view-config-dialog/save-vi
templateUrl: './document-list.component.html',
styleUrls: ['./document-list.component.scss']
})
export class DocumentListComponent implements OnInit {
export class DocumentListComponent implements OnInit, OnDestroy {
constructor(
public list: DocumentListViewService,
@@ -24,7 +26,9 @@ export class DocumentListComponent implements OnInit {
public route: ActivatedRoute,
private router: Router,
private toastService: ToastService,
private modalService: NgbModal) { }
private modalService: NgbModal,
private consumerStatusService: ConsumerStatusService
) { }
@ViewChild("filterEditor")
private filterEditor: FilterEditorComponent
@@ -35,6 +39,8 @@ export class DocumentListComponent implements OnInit {
filterRulesModified: boolean = false
private consumptionFinishedSubscription: Subscription
get isFiltered() {
return this.list.filterRules?.length > 0
}
@@ -63,6 +69,9 @@ export class DocumentListComponent implements OnInit {
if (localStorage.getItem('document-list:displayMode') != null) {
this.displayMode = localStorage.getItem('document-list:displayMode')
}
this.consumptionFinishedSubscription = this.consumerStatusService.onDocumentConsumptionFinished().subscribe(() => {
this.list.reload()
})
this.route.paramMap.subscribe(params => {
this.list.clear()
if (params.has('id')) {
@@ -83,6 +92,12 @@ export class DocumentListComponent implements OnInit {
})
}
ngOnDestroy() {
if (this.consumptionFinishedSubscription) {
this.consumptionFinishedSubscription.unsubscribe()
}
}
loadViewConfig(view: PaperlessSavedView) {
this.list.load(view)
this.list.reload()

View File

@@ -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">

View File

@@ -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()

View File

@@ -0,0 +1,11 @@
export interface WebsocketConsumerStatusMessage {
filename?: string
task_id?: string
current_progress?: number
max_progress?: number
status?: string
message?: string
document_id: number
}

View File

@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { ConsumerStatusService } from './consumer-status.service';
describe('ConsumerStatusService', () => {
let service: ConsumerStatusService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(ConsumerStatusService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@@ -0,0 +1,193 @@
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
import { WebsocketConsumerStatusMessage } from '../data/websocket-consumer-status-message';
export enum FileStatusPhase {
STARTED = 0,
UPLOADING = 1,
PROCESSING = 2,
SUCCESS = 3,
FAILED = 4
}
export const FILE_STATUS_MESSAGES = {
"document_already_exists": $localize`Document already exists.`,
"file_not_found": $localize`File not found.`,
"pre_consume_script_not_found": $localize`Pre-consume script does not exist.`,
"pre_consume_script_error": $localize`Error while executing pre-consume script.`,
"post_consume_script_not_found": $localize`Post-consume script does not exist.`,
"post_consume_script_error": $localize`Error while executing post-consume script.`,
"new_file": $localize`Received new file.`,
"unsupported_type": $localize`File type not supported.`,
"parsing_document": $localize`Processing document...`,
"generating_thumbnail": $localize`Generating thumbnail...`,
"parse_date": $localize`Retrieving date from document...`,
"save_document": $localize`Saving document...`,
"finished": $localize`Finished.`
}
export class FileStatus {
filename: string
taskId: string
phase: FileStatusPhase = FileStatusPhase.STARTED
currentPhaseProgress: number
currentPhaseMaxProgress: number
message: string
documentId: number
getProgress(): number {
switch (this.phase) {
case FileStatusPhase.STARTED:
return 0.0
case FileStatusPhase.UPLOADING:
return this.currentPhaseProgress / this.currentPhaseMaxProgress * 0.2
case FileStatusPhase.PROCESSING:
return (this.currentPhaseProgress / this.currentPhaseMaxProgress * 0.8) + 0.2
case FileStatusPhase.SUCCESS:
case FileStatusPhase.FAILED:
return 1.0
}
}
updateProgress(status: FileStatusPhase, currentProgress?: number, maxProgress?: number) {
if (status >= this.phase) {
this.phase = status
if (currentProgress != null) {
this.currentPhaseProgress = currentProgress
}
if (maxProgress != null) {
this.currentPhaseMaxProgress = maxProgress
}
}
}
}
@Injectable({
providedIn: 'root'
})
export class ConsumerStatusService {
constructor() { }
private statusWebSocked: WebSocket
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': status, 'created': created}
}
newFileUpload(filename: string): FileStatus {
let status = new FileStatus()
status.filename = filename
this.consumerStatus.push(status)
return status
}
getConsumerStatus(phase?: FileStatusPhase) {
if (phase != null) {
return this.consumerStatus.filter(s => s.phase == phase)
} else {
return this.consumerStatus
}
}
getConsumerStatusNotCompleted() {
return this.consumerStatus.filter(s => s.phase < FileStatusPhase.SUCCESS)
}
getConsumerStatusCompleted() {
return this.consumerStatus.filter(s => s.phase == FileStatusPhase.FAILED || s.phase == FileStatusPhase.SUCCESS)
}
connect() {
this.disconnect()
this.statusWebSocked = new WebSocket("ws://localhost:8000/ws/status/");
this.statusWebSocked.onmessage = (ev) => {
let statusMessage: WebsocketConsumerStatusMessage = JSON.parse(ev['data'])
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)
if (statusMessage.message && statusMessage.message in FILE_STATUS_MESSAGES) {
status.message = FILE_STATUS_MESSAGES[statusMessage.message]
} else if (statusMessage.message) {
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)
}
if (statusMessage.status == "FAILED") {
status.phase = FileStatusPhase.FAILED
this.documentConsumptionFailedSubject.next(status)
}
}
}
fail(status: FileStatus, message: string) {
status.message = message
status.phase = FileStatusPhase.FAILED
this.documentConsumptionFailedSubject.next(status)
}
disconnect() {
if (this.statusWebSocked) {
this.statusWebSocked.close()
this.statusWebSocked = null
}
}
dismiss(status: FileStatus) {
let index = this.consumerStatus.findIndex(s => s.filename == status.filename)
if (index > -1) {
this.consumerStatus.splice(index, 1)
}
}
dismissAll() {
this.consumerStatus = this.consumerStatus.filter(status => status.phase < FileStatusPhase.SUCCESS)
}
onDocumentConsumptionFinished() {
return this.documentConsumptionFinishedSubject
}
onDocumentConsumptionFailed() {
return this.documentConsumptionFailedSubject
}
onDocumentDetected() {
return this.documentDetectedSubject
}
}

View File

@@ -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({

View File

@@ -9,6 +9,10 @@ export interface Toast {
delay: number
action?: any
actionName?: string
}
@Injectable({

View File

@@ -6,7 +6,8 @@ export const environment = {
production: false,
apiBaseUrl: "http://localhost:8000/api/",
appTitle: "Paperless-ng",
version: "DEVELOPMENT"
version: "DEVELOPMENT",
wsBaseUrl: "ws://localhost:8000/ws/"
};
/*

View File

@@ -111,3 +111,7 @@ body {
font-size: 16px;
}
}
.ngx-file-drop__drop-zone--over {
background-color: $primaryFaded !important;
}

View File

@@ -352,6 +352,20 @@ $border-color-dark-mode: #47494f;
.bg-dark {
background-color: $bg-light-dark-mode !important;
}
.ngx-file-drop__drop-zone--over {
background-color: darken($primary-dark-mode, 35%) !important;
}
.alert-secondary {
background-color: $bg-light-dark-mode;
border-color: darken($bg-light-dark-mode, 10%);
color: $text-color-dark-mode-accent;
}
.progress-bar.bg-primary {
background-color: darken($primary-dark-mode, 5%) !important;
}
}
body.color-scheme-dark {