diff --git a/src-ui/messages.xlf b/src-ui/messages.xlf index 2d83d9322..06fd9a502 100644 --- a/src-ui/messages.xlf +++ b/src-ui/messages.xlf @@ -243,33 +243,22 @@ 13 - - Document added + + Document was added to Paperless-ngx. src/app/app.component.ts 83 src/app/app.component.ts - 93 - - - - Document was added to paperless. - - src/app/app.component.ts - 85 - - - src/app/app.component.ts - 95 + 92 Open document src/app/app.component.ts - 86 + 85 src/app/components/dashboard/widgets/upload-file-widget/upload-file-widget.component.html @@ -280,35 +269,28 @@ Could not add : src/app/app.component.ts - 109 + 107 - - New document detected + + Document is being processed by Paperless-ngx. src/app/app.component.ts - 124 - - - - Document is being processed by paperless. - - src/app/app.component.ts - 126 + 122 Prev src/app/app.component.ts - 131 + 128 Next src/app/app.component.ts - 132 + 129 src/app/components/document-detail/document-detail.component.html @@ -319,98 +301,98 @@ End src/app/app.component.ts - 133 + 130 The dashboard can be used to show saved views, such as an 'Inbox'. Those settings are found under Settings > Saved Views once you have created some. src/app/app.component.ts - 139 + 136 Drag-and-drop documents here to start uploading or place them in the consume folder. You can also drag-and-drop documents anywhere on all other pages of the web app. Once you do, Paperless-ngx will start training its machine learning algorithms. src/app/app.component.ts - 146 + 143 The documents list shows all of your documents and allows for filtering as well as bulk-editing. There are three different view styles: list, small cards and large cards. A list of documents currently opened for editing is shown in the sidebar. src/app/app.component.ts - 151 + 148 The filtering tools allow you to quickly find documents using various searches, dates, tags, etc. src/app/app.component.ts - 158 + 155 Any combination of filters can be saved as a 'view' which can then be displayed on the dashboard and / or sidebar. src/app/app.component.ts - 164 + 161 Tags, correspondents, document types and storage paths can all be managed using these pages. They can also be created from the document edit view. src/app/app.component.ts - 169 + 166 Manage e-mail accounts and rules for automatically importing documents. src/app/app.component.ts - 177 + 174 Consumption templates give you finer control over the document ingestion process. src/app/app.component.ts - 185 + 182 File Tasks shows you documents that have been consumed, are waiting to be, or may have failed during the process. src/app/app.component.ts - 193 + 190 Check out the settings for various tweaks to the web app and toggle settings for saved views. src/app/app.component.ts - 201 + 198 Thank you! 🙏 src/app/app.component.ts - 209 + 206 There are <em>tons</em> more features and info we didn't cover here, but this should get you started. Check out the documentation or visit the project on GitHub to learn more or to report issues. src/app/app.component.ts - 211 + 208 Lastly, on behalf of every contributor to this community-supported project, thank you for using Paperless-ngx! src/app/app.component.ts - 213 + 210 @@ -1378,39 +1360,32 @@ 370 - - Settings saved - - src/app/components/admin/settings/settings.component.ts - 492 - - Settings were saved successfully. src/app/components/admin/settings/settings.component.ts - 493 + 492 Settings were saved successfully. Reload is required to apply some changes. src/app/components/admin/settings/settings.component.ts - 497 + 496 Reload now src/app/components/admin/settings/settings.component.ts - 498 + 497 An error occurred while saving settings. src/app/components/admin/settings/settings.component.ts - 508 + 507 src/app/components/app-frame/app-frame.component.ts @@ -1421,21 +1396,21 @@ Use system language src/app/components/admin/settings/settings.component.ts - 516 + 515 Use date format of display language src/app/components/admin/settings/settings.component.ts - 523 + 522 Error while storing settings on server. src/app/components/admin/settings/settings.component.ts - 546 + 545 @@ -2595,11 +2570,7 @@ src/app/components/common/toasts/toasts.component.html - 14 - - - src/app/services/toast.service.ts - 37 + 18 @@ -3787,14 +3758,14 @@ Status src/app/components/common/toasts/toasts.component.html - 12 + 16 Copy Raw Error src/app/components/common/toasts/toasts.component.html - 23 + 27 @@ -6520,13 +6491,6 @@ 542 - - Information - - src/app/services/toast.service.ts - 46 - - Connecting... diff --git a/src-ui/src/app/app.component.ts b/src-ui/src/app/app.component.ts index fb54665f0..28ce87929 100644 --- a/src-ui/src/app/app.component.ts +++ b/src-ui/src/app/app.component.ts @@ -80,9 +80,8 @@ export class AppComponent implements OnInit, OnDestroy { ) ) { this.toastService.show({ - title: $localize`Document added`, + content: $localize`Document ${status.filename} was added to Paperless-ngx.`, delay: 10000, - content: $localize`Document ${status.filename} was added to paperless.`, actionName: $localize`Open document`, action: () => { this.router.navigate(['documents', status.documentId]) @@ -90,9 +89,8 @@ export class AppComponent implements OnInit, OnDestroy { }) } else { this.toastService.show({ - title: $localize`Document added`, + content: $localize`Document ${status.filename} was added to Paperless-ngx.`, delay: 10000, - content: $localize`Document ${status.filename} was added to paperless.`, }) } } @@ -121,9 +119,8 @@ export class AppComponent implements OnInit, OnDestroy { ) ) { this.toastService.show({ - title: $localize`New document detected`, + content: $localize`Document ${status.filename} is being processed by Paperless-ngx.`, delay: 5000, - content: $localize`Document ${status.filename} is being processed by paperless.`, }) } }) diff --git a/src-ui/src/app/components/admin/settings/settings.component.ts b/src-ui/src/app/components/admin/settings/settings.component.ts index 3a7f837f3..2d3960dc5 100644 --- a/src-ui/src/app/components/admin/settings/settings.component.ts +++ b/src-ui/src/app/components/admin/settings/settings.component.ts @@ -489,7 +489,6 @@ export class SettingsComponent this.documentListViewService.updatePageSize() this.settings.updateAppearanceSettings() let savedToast: Toast = { - title: $localize`Settings saved`, content: $localize`Settings were saved successfully.`, delay: 5000, } diff --git a/src-ui/src/app/components/common/toasts/toasts.component.html b/src-ui/src/app/components/common/toasts/toasts.component.html index dd75455e0..2372911ae 100644 --- a/src-ui/src/app/components/common/toasts/toasts.component.html +++ b/src-ui/src/app/components/common/toasts/toasts.component.html @@ -1,30 +1,43 @@ -

{{toast.content}}

-
-
-
-
URL
-
{{ toast.error.url }}
-
Status
-
{{ toast.error.status }} {{ toast.error.statusText }}
-
Error
-
{{ getErrorText(toast.error) }}
-
-
-
- + + {{ toast.delayRemaining / 1000 | number: '1.0-0' }} seconds +
+ + + + +
+

{{toast.content}}

+
+
+
+
URL
+
{{ toast.error.url }}
+
Status
+
{{ toast.error.status }} {{ toast.error.statusText }}
+
Error
+
{{ getErrorText(toast.error) }}
+
+
+
+ +
+
-
+
+

- -

+ +
diff --git a/src-ui/src/app/components/common/toasts/toasts.component.scss b/src-ui/src/app/components/common/toasts/toasts.component.scss index 52f8f8957..463f96495 100644 --- a/src-ui/src/app/components/common/toasts/toasts.component.scss +++ b/src-ui/src/app/components/common/toasts/toasts.component.scss @@ -2,7 +2,7 @@ position: fixed; top: 0; right: 0; - margin: 0.5em; + margin: 0.3em; z-index: 1200; } @@ -10,13 +10,23 @@ display: block; // this corrects an ng-bootstrap bug that prevented animations } -::ng-deep .toast.error .toast-header { - background-color: hsla(350, 79%, 40%, 0.8); // bg-danger - border-color: black; +::ng-deep .toast-body { + position: relative; +} + +::ng-deep .toast.error { + border-color: hsla(350, 79%, 40%, 0.4); // bg-danger } ::ng-deep .toast.error .toast-body { background-color: hsla(350, 79%, 40%, 0.8); // bg-danger + border-top-left-radius: inherit; + border-top-right-radius: inherit; border-bottom-left-radius: inherit; border-bottom-right-radius: inherit; } + +.progress { + background-color: var(--pngx-primary); + opacity: .07; +} diff --git a/src-ui/src/app/components/common/toasts/toasts.component.spec.ts b/src-ui/src/app/components/common/toasts/toasts.component.spec.ts index 9181240e8..bf42dc211 100644 --- a/src-ui/src/app/components/common/toasts/toasts.component.spec.ts +++ b/src-ui/src/app/components/common/toasts/toasts.component.spec.ts @@ -3,6 +3,7 @@ import { discardPeriodicTasks, fakeAsync, flush, + tick, } from '@angular/core/testing' import { ToastService } from 'src/app/services/toast.service' import { ToastsComponent } from './toasts.component' @@ -14,18 +15,15 @@ import { Clipboard } from '@angular/cdk/clipboard' const toasts = [ { - title: 'Title', - content: 'content', + content: 'foo bar', delay: 5000, }, { - title: 'Error 1', content: 'Error 1 content', delay: 5000, error: 'Error 1 string', }, { - title: 'Error 2', content: 'Error 2 content', delay: 5000, error: { @@ -75,8 +73,7 @@ describe('ToastsComponent', () => { expect(spy).toHaveBeenCalled() expect(component.toasts).toContainEqual({ - title: 'Title', - content: 'content', + content: 'foo bar', delay: 5000, }) @@ -89,13 +86,24 @@ describe('ToastsComponent', () => { component.ngOnInit() fixture.detectChanges() - expect(fixture.nativeElement.textContent).toContain('Title') + expect(fixture.nativeElement.textContent).toContain('foo bar') component.ngOnDestroy() flush() discardPeriodicTasks() })) + it('should countdown toast', fakeAsync(() => { + component.ngOnInit() + fixture.detectChanges() + component.onShow(toasts[0]) + tick(5000) + expect(component.toasts[0].delayRemaining).toEqual(0) + component.ngOnDestroy() + flush() + discardPeriodicTasks() + })) + it('should show an error if given with toast', fakeAsync(() => { component.ngOnInit() fixture.detectChanges() @@ -134,6 +142,9 @@ describe('ToastsComponent', () => { 'Error string no detail' ) expect(component.getErrorText('Error string')).toEqual('') + expect( + component.getErrorText({ error: { message: 'foo error bar' } }) + ).toContain('{"message":"foo error bar"}') expect( component.getErrorText({ error: new Array(205).join('a') }) ).toContain('...') diff --git a/src-ui/src/app/components/common/toasts/toasts.component.ts b/src-ui/src/app/components/common/toasts/toasts.component.ts index d271c7f7d..dac65c37f 100644 --- a/src-ui/src/app/components/common/toasts/toasts.component.ts +++ b/src-ui/src/app/components/common/toasts/toasts.component.ts @@ -1,5 +1,5 @@ import { Component, OnDestroy, OnInit } from '@angular/core' -import { Subscription } from 'rxjs' +import { Subscription, interval, take } from 'rxjs' import { Toast, ToastService } from 'src/app/services/toast.service' import { Clipboard } from '@angular/cdk/clipboard' @@ -20,6 +20,8 @@ export class ToastsComponent implements OnInit, OnDestroy { public copied: boolean = false + public seconds: number = 0 + ngOnDestroy(): void { this.subscription?.unsubscribe() } @@ -37,6 +39,20 @@ export class ToastsComponent implements OnInit, OnDestroy { }) } + onShow(toast: Toast) { + const refreshInterval = 150 + const delay = toast.delay - 500 // for fade animation + + interval(refreshInterval) + .pipe(take(delay / refreshInterval)) + .subscribe((count) => { + toast.delayRemaining = Math.max( + 0, + delay - refreshInterval * (count + 1) + ) + }) + } + public isDetailedError(error: any): boolean { return ( typeof error === 'object' && diff --git a/src-ui/src/app/services/toast.service.ts b/src-ui/src/app/services/toast.service.ts index b1caaf9b5..16c534b5c 100644 --- a/src-ui/src/app/services/toast.service.ts +++ b/src-ui/src/app/services/toast.service.ts @@ -2,12 +2,12 @@ import { Injectable } from '@angular/core' import { Subject } from 'rxjs' export interface Toast { - title: string - content: string delay: number + delayRemaining?: number + action?: any actionName?: string @@ -34,7 +34,6 @@ export class ToastService { showError(content: string, error: any = null, delay: number = 10000) { this.show({ - title: $localize`Error`, content: content, delay: delay, classname: 'error', @@ -43,7 +42,7 @@ export class ToastService { } showInfo(content: string, delay: number = 5000) { - this.show({ title: $localize`Information`, content: content, delay: delay }) + this.show({ content: content, delay: delay }) } closeToast(toast: Toast) { diff --git a/src-ui/src/theme.scss b/src-ui/src/theme.scss index 095b83d20..0518f9bbe 100644 --- a/src-ui/src/theme.scss +++ b/src-ui/src/theme.scss @@ -249,12 +249,11 @@ $form-check-radio-checked-bg-image-dark: url("data:image/svg+xml,